diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..4d7a8d65a Binary files /dev/null and b/.DS_Store differ diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..deb52f2cd --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +require 'rake/testtask' + +Rake::TestTask.new do |t| + t.libs = ["lib"] + t.warning = true + t.test_files = FileList['specs/*_spec.rb'] +end + +task default: :test diff --git a/design-activity.md b/design-activity.md new file mode 100644 index 000000000..074173db7 --- /dev/null +++ b/design-activity.md @@ -0,0 +1,32 @@ +- What classes does each implementation include? Are the lists the same? + - Yes , both include same classes. They are CartEntry, ShoppingCart and Order. + +- Write down a sentence to describe each class. + - CartEntry- It represents a shopping cart item entry. + - ShoppingCart- It contains all the entries. + - Order- It represent initialization of new shopping cart instance. + +- How do the classes relate to each other? It might be helpful to draw a diagram on a whiteboard or piece of paper. + - Order has a ShoppingCart. + - ShoppingCart has a list of CartEntry + +- What data does each class store? How (if at all) does this differ between the two implementations? + - CartEntry has unit_price and quantity, ShoppingCart has entries and Order has cart and total_price. In implementation A only the class Order has the responsibility of calculating total_cost.In implementation B CartEntry calculates price, ShoppingCart return sum and Order return total_price. + +- What methods does each class have? How (if at all) does this differ between the two implementations? + - CartEntry, ShoppingCart, and Order has initialize and Order has total_price method in both implementations. In implementation B CartEntry and ShoppingCart both have their price method. + +- Consider the Order#total_price method. In each implementation: +- Is logic to compute the price delegated to "lower level" classes like ShoppingCart and CartEntry, or is it retained in Order? + - In implementation A it's retained in Order and in implementation B it's delegated. +- Does total_price directly manipulate the instance variables of other classes? + - NO. + +- If we decide items are cheaper if bought in bulk, how would this change the code? Which implementation is easier to modify? + - In implementation A Order#total_price has to be updated to add a if condition when calculating the sum. In implementation B the CartEntry price method can be updated. Implementation B is easier to modify and easier to supoort different use cases. + +- Which implementation better adheres to the single responsibility principle? + - Implementation B + +- Bonus question once you've read Metz ch. 3: Which implementation is more loosely coupled? + - Implementation B diff --git a/lib/administrator.rb b/lib/administrator.rb new file mode 100644 index 000000000..5d90b74a2 --- /dev/null +++ b/lib/administrator.rb @@ -0,0 +1,114 @@ +require 'csv' +require 'date' +require_relative 'room' +require_relative 'reservation' +require_relative 'block' +require_relative 'room_not_available_error' + +module BookingSystem + class Administrator + attr_reader :rooms, :reservations, :range, :blocks + + def initialize + @rooms = load_rooms + #{} + # (1..20).each{ |num| @rooms[num] = BookingSystem::Room.new(num, 200.00) } + @reservations = {} + @range = (1..500).to_a + @blocks = {} + end + + def load_rooms + number = nil + cost = nil + rooms = {} + CSV.read("support/rooms.csv", :headers => true, :header_converters => :symbol, :converters => :all).each { |line| + number = line[0].to_i + cost = line[1].to_f + rooms[number] = BookingSystem::Room.new(number, cost) + } + return rooms + end + + + def list_rooms + return @rooms.values + end + + def reserve_room(room_num, check_in, check_out) + raise ArgumentError.new("Incorrect room number") if !rooms.keys.include?(room_num) + + room = @rooms[room_num] + raise RoomNotAvailableError.new("That room is not available")if !list_available_rooms(check_in, check_out).include?(room) + + reservation_details = {id: @range.shift, check_in: check_in, check_out: check_out, room: room} + new_reservation = BookingSystem::Reservation.new(reservation_details) + @reservations[new_reservation.id] = new_reservation + return new_reservation + end + + def find_reservation(date) + return @reservations.select{|id, reservation|reservation.check_in <= date && reservation.check_out > date}.values + end + + def total_cost(reservation_id) + return @reservations[reservation_id].total_cost + end + + def list_reserved_rooms(start_date, end_date) + reserved_rooms = [] + (start_date..end_date).each{ |date| + reserved_rooms += find_reservation(date).map{ |reservation| reservation.room } + } + return reserved_rooms.flatten.uniq + end + + def list_blocked_rooms(start_date, end_date) + blocked_rooms = [] + (start_date..end_date).each{ |date| + selected_blocks = @blocks.select{|id, block|block.check_in <= date && block.check_out > date}.values + blocked_rooms += selected_blocks.map{ |block| block.rooms } + } + return blocked_rooms.flatten.uniq + end + + def list_available_rooms(start_date, end_date) + return @rooms.values - list_reserved_rooms(start_date, end_date-1) - list_blocked_rooms(start_date, end_date-1) + end + + def create_block(room_numbers, check_in, check_out, discounted_rate) + raise ArgumentError.new("Room numbers should be an Array") if room_numbers.class != Array + raise ArgumentError.new("Room count should be between 1 & 5") if room_numbers.count < 1 || room_numbers.count > 5 + + block_rooms = [] + room_numbers.each { |room_num| + raise ArgumentError.new("Incorrect room number #{room_num}") if !@rooms.keys.include?(room_num) + raise RoomNotAvailableError.new("Room #{room_num} is not available") if !(list_available_rooms(check_in, check_out).map{|room|room.number}).include?(room_num) + block_rooms << @rooms[room_num] + } + + block_details = {id: @range.shift, check_in: check_in, check_out: check_out, rooms: block_rooms, rate: discounted_rate} + new_block = BookingSystem::Block.new(block_details) + @blocks[new_block.id] = new_block + return new_block + end + + def list_available_rooms_in_block(block_id) + block = @blocks[block_id] + return block.rooms - list_reserved_rooms(block.check_in, block.check_out - 1) + end + + def reserve_in_block(block_id, room_number) + block = @blocks[block_id] + raise ArgumentError.new("Room #{room_number} not in block") if !block.rooms.map{ |room| room.number }.include?(room_number) + room = @rooms[room_number] + raise RoomNotAvailableError.new("That room is not available") if list_reserved_rooms(block.check_in, block.check_out - 1).include?(room) + + reservation_details = {id: @range.shift, check_in: block.check_in, check_out: block.check_out, room: room} + new_reservation = BookingSystem::Reservation.new(reservation_details) + @reservations[new_reservation.id] = new_reservation + return new_reservation + end + + end +end diff --git a/lib/block.rb b/lib/block.rb new file mode 100644 index 000000000..894658f32 --- /dev/null +++ b/lib/block.rb @@ -0,0 +1,16 @@ +require 'date' +require_relative 'booking' +require_relative 'invalid_duration_error' + +module BookingSystem + class Block < Booking + attr_reader :rooms, :rate + + def initialize(input) + super(input) + @rooms = input[:rooms] + @rate = input[:rate] + end + + end +end diff --git a/lib/booking.rb b/lib/booking.rb new file mode 100644 index 000000000..af05df0a0 --- /dev/null +++ b/lib/booking.rb @@ -0,0 +1,20 @@ +require 'date' +require_relative 'invalid_duration_error' + +module BookingSystem + class Booking + attr_reader :id, :check_in, :check_out + + def initialize(input) + @id = input[:id] + @check_in = input[:check_in] + @check_out = input[:check_out] + raise InvalidDurationError.new("Check out time can not be before check in time") if booking_duration < 0 + end + + def booking_duration + return (@check_out - @check_in).to_i + end + + end +end diff --git a/lib/invalid_duration_error.rb b/lib/invalid_duration_error.rb new file mode 100644 index 000000000..d0da3c8e5 --- /dev/null +++ b/lib/invalid_duration_error.rb @@ -0,0 +1,2 @@ +class InvalidDurationError < StandardError +end diff --git a/lib/reservation.rb b/lib/reservation.rb new file mode 100644 index 000000000..e0a7f652b --- /dev/null +++ b/lib/reservation.rb @@ -0,0 +1,21 @@ +require 'date' +require_relative 'booking' +require_relative 'room' +require_relative 'invalid_duration_error' + +module BookingSystem + class Reservation < Booking + attr_reader :room, :cost + + def initialize(input) + super(input) + @room = input[:room] + @cost = input.has_key?(:rate) ? input[:rate] : @room.cost + end + + def total_cost + return booking_duration * @cost + end + + end +end diff --git a/lib/room.rb b/lib/room.rb new file mode 100644 index 000000000..b66d30fc2 --- /dev/null +++ b/lib/room.rb @@ -0,0 +1,10 @@ +module BookingSystem + class Room + attr_reader :number, :cost + + def initialize number, cost + @number = number + @cost = cost + end + end +end diff --git a/lib/room_not_available_error.rb b/lib/room_not_available_error.rb new file mode 100644 index 000000000..e95e55b9c --- /dev/null +++ b/lib/room_not_available_error.rb @@ -0,0 +1,2 @@ +class RoomNotAvailableError < StandardError +end diff --git a/specs/administrator_spec.rb b/specs/administrator_spec.rb new file mode 100644 index 000000000..0847ecd35 --- /dev/null +++ b/specs/administrator_spec.rb @@ -0,0 +1,237 @@ +require_relative 'spec_helper' +describe "Administrator class" do + let(:admin){BookingSystem::Administrator.new} + + describe "#Initializer" do + it "is an instance of Administrator" do + admin.must_be_kind_of BookingSystem::Administrator + end + + it "establishes the base data structures when instantiated" do + [:rooms, :reservations, :range].each do |prop| + admin.must_respond_to prop + end + + admin.rooms.must_be_kind_of Hash + admin.reservations.must_be_kind_of Hash + admin.range.must_be_kind_of Array + end + end + + describe "#list_rooms" do + it "can access the list of all of the rooms in the hotel" do + admin.list_rooms.must_be_instance_of Array + admin.list_rooms.each{|room| room.must_be_instance_of BookingSystem::Room} + end + end + + describe "#reserve_room" do + reservation_data = { + id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-27"), room: BookingSystem::Room.new(1, 200)} + + let(:reservation) {BookingSystem::Reservation.new(reservation_data)} + it "raises an error for Incorrect room number" do + proc { admin.reserve_room(21, Date.parse('2018-03-27'), Date.parse('2018-03-30')) + }.must_raise ArgumentError + + proc { admin.reserve_room(0, Date.parse('2018-03-27'), Date.parse('2018-03-30')) + }.must_raise ArgumentError + + proc { admin.reserve_room("7", Date.parse('2018-03-27'), Date.parse('2018-03-30')) + }.must_raise ArgumentError + end + it "raises an error if room is not available" do + admin.reserve_room(5, Date.parse('2018-03-27'), Date.parse('2018-03-30')) + proc { admin.reserve_room(5, Date.parse('2018-03-29'), Date.parse('2018-03-30'))}.must_raise RoomNotAvailableError + + admin.create_block([7,8],Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) + proc { admin.reserve_room(7, Date.parse('2018-03-27'), Date.parse('2018-03-30'))}.must_raise RoomNotAvailableError + end + + it "allows start on the same day that another reservation for the same room ends" do + admin.reserve_room(5, Date.parse('2018-03-27'), Date.parse('2018-03-30')) + admin.reserve_room(5, Date.parse('2018-03-23'), Date.parse('2018-03-27')).must_be_instance_of BookingSystem::Reservation + admin.reserve_room(5, Date.parse('2018-03-30'), Date.parse('2018-04-01')).must_be_instance_of BookingSystem::Reservation + end + + it "can reserve a room for a given date range" do + admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-27")).must_be_instance_of BookingSystem::Reservation + end + + it "adds to the reservations" do + before = admin.reservations.count + admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-27")) + admin.reservations.count.must_equal before + 1 + end + + it "raises an error if all rooms are booked" do + (1..20).each{ |num| admin.reserve_room(num, Date.parse('2018-03-27'), Date.parse('2018-03-30')) } + proc { admin.reserve_room(5, Date.parse('2018-03-29'), Date.parse('2018-03-30'))}.must_raise RoomNotAvailableError + end + + end + + describe "#find_reservation" do + reservation_data = { + id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-27"), room: BookingSystem::Room.new(1, 200)} + + let(:reservation) {BookingSystem::Reservation.new(reservation_data)} + + it "can access the list of reservations for a specific date" do + admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-27")) + admin.find_reservation(Date.parse("2018-03-20")).must_be_instance_of Array + admin.find_reservation(Date.parse("2018-03-20"))[0].must_be_kind_of BookingSystem::Reservation + end + + it "returns an empty array when there are no reservations" do + admin.find_reservation(Date.parse("2018-03-20")).must_be_instance_of Array + admin.find_reservation(Date.parse("2018-03-20")).must_be_empty + end + end + + describe "#total_cost" do + + it "can get the total cost for a given reservation" do + new_reservation = admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-27")) + admin.total_cost(new_reservation.id).must_equal 1400.00 + end + end + + describe "#list_reserved_rooms" do + it "can view a list of rooms that are reserved for a given date range" do + admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-25")) + admin.list_reserved_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")).must_be_instance_of Array + admin.list_reserved_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")).count.must_equal 1 + end + it "can view multiple rooms that are reserved for a given date range" do + admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-25")) + admin.reserve_room(2, Date.parse("2018-03-20"), Date.parse("2018-03-25")) + admin.reserve_room(3, Date.parse("2018-03-20"), Date.parse("2018-03-25")) + admin.list_reserved_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")).must_be_instance_of Array + admin.list_reserved_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")).count.must_equal 3 + end + end + + describe "#list_available_rooms" do + it "can view a list of rooms that are available for a given date range" do + admin.reserve_room(1, Date.parse("2018-03-20"), Date.parse("2018-03-25")) + admin.list_available_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")).must_be_instance_of Array + admin.list_available_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")).count.must_equal 19 + end + + it "returns all rooms when none is reserved" do + rooms = admin.list_available_rooms(Date.parse("2018-03-20"), Date.parse("2018-03-25")) + rooms.count.must_equal 20 + rooms.map{|room| room.number}.sort.must_equal (1..20).to_a + end + it "returns empty when all are reserved" do + 20.times{ |index| admin.reserve_room(index+1, Date.parse('2018-03-27'), Date.parse('2018-03-30')) } + admin.list_available_rooms(Date.parse("2018-03-27"), Date.parse("2018-03-30")).must_be_empty + end + end + + describe "#create_block" do + it "raises error if room numbers is not an instance of an array" do + proc { admin.create_block( + 1, Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise ArgumentError + end + + it "raises error if room count is <1 or >5 in block" do + proc { admin.create_block( + [], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise ArgumentError + + proc { admin.create_block( + [1,2,3,4,5,6], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise ArgumentError + end + + it "raises error if room number is invalid" do + proc { admin.create_block([-1], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise ArgumentError + + proc { admin.create_block(["1"], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise ArgumentError + + proc { admin.create_block(["one"], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise ArgumentError + end + + it "raises an error if room is not available" do + admin.reserve_room(4, Date.parse('2018-03-27'), Date.parse('2018-03-30')) + proc { admin.create_block([1,4,5], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) }.must_raise RoomNotAvailableError + + admin.create_block([9], Date.parse('2018-03-29'), Date.parse('2018-03-30'), 180.00) + proc { admin.create_block([8,9,10], Date.parse('2018-03-29'), Date.parse('2018-03-30'), 180.00) }.must_raise RoomNotAvailableError + end + + it "allows creation of blocks on the same day when another block for the same room ends" do + admin.create_block([5], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) + admin.create_block([5], Date.parse('2018-03-23'), Date.parse('2018-03-27'), 180.00).must_be_instance_of BookingSystem::Block + admin.create_block([5], Date.parse('2018-03-30'), Date.parse('2018-04-01'), 180.00).must_be_instance_of BookingSystem::Block + end + + it "allows reservation before block start and on block end date" do + admin.create_block([5], Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) + admin.reserve_room(5, Date.parse('2018-03-23'), Date.parse('2018-03-27')).must_be_instance_of BookingSystem::Reservation + admin.reserve_room(5, Date.parse('2018-03-30'), Date.parse('2018-04-01')).must_be_instance_of BookingSystem::Reservation + end + + it "can block a room for a given date range" do + admin.create_block([1,2], Date.parse("2018-03-20"), Date.parse("2018-03-27"), 180.00).must_be_instance_of BookingSystem::Block + end + + it "raises an error if all rooms are reserved" do + (1..20).each{ |num| admin.reserve_room(num, Date.parse('2018-03-27'), Date.parse('2018-03-30')) } + proc { admin.create_block([5], Date.parse('2018-03-29'), Date.parse('2018-03-30'), 180.00)}.must_raise RoomNotAvailableError + end + + it "raises an error if all rooms are blocked" do + admin.create_block((1..5).to_a, Date.parse('2018-03-27'), Date.parse('2018-03-30'), 180.00) + proc { admin.create_block([5], Date.parse('2018-03-29'), Date.parse('2018-03-30'), 180.00)}.must_raise RoomNotAvailableError + end + end + + describe "#list_available_rooms_in_block" do + it "can view a list of rooms that are available" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + admin.list_available_rooms_in_block(block.id).must_be_instance_of Array + admin.list_available_rooms_in_block(block.id).count.must_equal 3 + end + + it "returns all rooms in block when none is reserved" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + rooms = admin.list_available_rooms_in_block(block.id) + rooms.count.must_equal 3 + rooms.map{|room| room.number}.sort.must_equal (1..3).to_a + end + + it "returns empty when all are reserved" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + 3.times{ |index| admin.reserve_in_block(block.id, index+1) } + admin.list_available_rooms_in_block(block.id).must_be_empty + end + end + + describe "#reserve_in_block" do + it "can reserve a room in the block" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + admin.reserve_in_block(block.id, 1).must_be_instance_of BookingSystem::Reservation + end + + it "reservation dates will always match the date range of the block" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + reservation = admin.reserve_in_block(block.id, 1) + reservation.check_in.must_equal Date.parse("2018-03-20") + reservation.check_out.must_equal Date.parse("2018-03-25") + end + + it "raises an error if room is not in block" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + proc { admin.reserve_in_block(block.id, 4) }.must_raise ArgumentError + end + + it "raises an error if room is already reserved" do + block = admin.create_block([1,2,3], Date.parse("2018-03-20"), Date.parse("2018-03-25"), 180.00) + admin.reserve_in_block(block.id, 3) + proc { admin.reserve_in_block(block.id, 3) }.must_raise RoomNotAvailableError + end + + end + + end diff --git a/specs/block_spec.rb b/specs/block_spec.rb new file mode 100644 index 000000000..2699ea9be --- /dev/null +++ b/specs/block_spec.rb @@ -0,0 +1,39 @@ +require_relative 'spec_helper' + +describe "Block class" do + block_data = { + id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-27"), rooms: [BookingSystem::Room.new(1, 200.00)], rate: 180.00 } + + let(:block) {BookingSystem::Block.new(block_data)} + + describe "#initialize" do + it "raises an InvalidDurationError if Check out time is before check in time" do + proc { BookingSystem::Block.new({id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-15"), rooms: [BookingSystem::Room.new(1, 200.00)], rate: 180.00 }) + }.must_raise InvalidDurationError + end + + it "is an instance of Block" do + block.must_be_kind_of BookingSystem::Block + end + + it "stores an array of rooms" do + block.rooms.must_be_instance_of Array + block.rooms.each { |room| room.must_be_kind_of BookingSystem::Room } + end + + it "is set up for specific attributes and data types" do + [:id, :check_in, :check_out, :rooms].each{|prop| block.must_respond_to prop} + block.id.must_be_kind_of Integer + block.check_in.must_be_kind_of Date + block.check_out.must_be_kind_of Date + block.rate.must_be_kind_of Numeric + end + end + + describe "#booking_duration" do + it "returns the duration of the block in days" do + block.booking_duration.must_equal 7 + block.booking_duration.must_be_instance_of Integer + end + end +end diff --git a/specs/reservation_spec.rb b/specs/reservation_spec.rb new file mode 100644 index 000000000..d4972381d --- /dev/null +++ b/specs/reservation_spec.rb @@ -0,0 +1,58 @@ +require_relative 'spec_helper' + +describe "Reservation class" do + reservation_data = { + id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-27"), room: BookingSystem::Room.new(1, 200)} + + let(:reservation) {BookingSystem::Reservation.new(reservation_data)} + + describe "#initialize" do + it "raises an InvalidDurationError if Check out time is before check in time" do + proc { BookingSystem::Reservation.new({id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-15"), room: BookingSystem::Room.new(1, 200)}) + }.must_raise InvalidDurationError + end + + it "is an instance of Reservation" do + reservation.must_be_kind_of BookingSystem::Reservation + end + + it "stores an instance of room" do + reservation.room.must_be_kind_of BookingSystem::Room + end + + it "is set up for specific attributes and data types" do + [:id, :check_in, :check_out, :room].each{|prop| reservation.must_respond_to prop} + + reservation.id.must_be_kind_of Integer + reservation.check_in.must_be_kind_of Date + reservation.check_out.must_be_kind_of Date + end + end + + describe "#booking_duration" do + it "returns the duration of the booking in days" do + reservation.booking_duration.must_equal 7 + reservation.booking_duration.must_be_instance_of Integer + end + end + + describe "#total_cost" do + it "returns total cost for a given reservation" do + reservation.total_cost.must_equal 1400 + reservation.total_cost.must_be_instance_of Integer + end + + it "does not charge for the checkout day" do + reservation_for_2_days = BookingSystem::Reservation.new({ + id: 1, check_in: Date.parse("2018-03-01"), check_out: Date.parse("2018-03-02"), room: BookingSystem::Room.new(1, 200)}) + reservation_for_2_days.total_cost.must_equal 200 + end + + it "uses the rate if provided" do + discounted_reservation = BookingSystem::Reservation.new({id: 1, check_in: Date.parse("2018-03-20"), check_out: Date.parse("2018-03-27"), room: BookingSystem::Room.new(1, 200), rate: 100.00}) + discounted_reservation.total_cost.must_equal 700.00 + end + end + + +end diff --git a/specs/room_spec.rb b/specs/room_spec.rb new file mode 100644 index 000000000..e00f06ad3 --- /dev/null +++ b/specs/room_spec.rb @@ -0,0 +1,20 @@ +require_relative 'spec_helper' + +describe "Room class" do + number = 1 + cost = 200 + let(:room) {BookingSystem::Room.new(number, cost)} + + describe "#initialize" do + it "is an instance of Room" do + room.must_be_kind_of BookingSystem::Room + end + it "is set up for specific attributes and data types" do + [:number, :cost].each{|prop| room.must_respond_to prop} + + room.number.must_be_kind_of Integer + room.cost.must_be_kind_of Integer + end + + end +end diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb new file mode 100644 index 000000000..5fbe95f08 --- /dev/null +++ b/specs/spec_helper.rb @@ -0,0 +1,19 @@ +require 'date' +require "simplecov" +SimpleCov.start + +require 'minitest' +require 'minitest/autorun' +require 'minitest/reporters' +require 'minitest/skip_dsl' +# Add simplecov + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + +# Require_relative your lib files here! +require_relative '../lib/administrator' +require_relative '../lib/reservation' +require_relative '../lib/room' +require_relative '../lib/block' +require_relative '../lib/invalid_duration_error' +require_relative '../lib/room_not_available_error' diff --git a/support/rooms.csv b/support/rooms.csv new file mode 100644 index 000000000..b100c43d9 --- /dev/null +++ b/support/rooms.csv @@ -0,0 +1,21 @@ +number, cost +1, 200.00 +2, 200.00 +3, 200.00 +4, 200.00 +5, 200.00 +6, 200.00 +7, 200.00 +8, 200.00 +9, 200.00 +10, 200.00 +11, 200.00 +12, 200.00 +13, 200.00 +14, 200.00 +15, 200.00 +16, 200.00 +17, 200.00 +18, 200.00 +19, 200.00 +20, 200.00