|
|
|
require "rails_helper"
|
|
|
|
|
|
|
|
RSpec.describe Location, type: :model do
|
|
|
|
describe "#new" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
stub_request(:get, /api.postcodes.io/)
|
|
|
|
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\",\"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
|
|
|
|
end
|
|
|
|
|
|
|
|
it "belongs to an organisation" do
|
|
|
|
expect(location.scheme).to be_a(Scheme)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "infers the local authority" do
|
|
|
|
location.postcode = "M1 1AE"
|
|
|
|
location.save!
|
|
|
|
expect(location.location_code).to eq("E08000003")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#postcode" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does not add an error if postcode is valid" do
|
|
|
|
location.postcode = "M1 1AE"
|
|
|
|
location.save!
|
|
|
|
expect(location.errors).to be_empty
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does add an error when the postcode is invalid" do
|
|
|
|
location.postcode = "invalid"
|
|
|
|
location.valid?(:postcode)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does add an error when the postcode is missing" do
|
|
|
|
location.postcode = nil
|
|
|
|
location.valid?(:postcode)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#local_authority" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does add an error when the local authority is invalid" do
|
|
|
|
location.location_admin_district = nil
|
|
|
|
location.valid?(:location_admin_district)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#name" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does not add an error when the name is invalid" do
|
|
|
|
location.name = nil
|
|
|
|
location.valid?
|
|
|
|
expect(location.errors.count).to eq(0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#units" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does add an error when the number of units is invalid" do
|
|
|
|
location.units = nil
|
|
|
|
location.valid?(:units)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#type_of_unit" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does add an error when the type of unit is invalid" do
|
|
|
|
location.type_of_unit = nil
|
|
|
|
location.valid?(:type_of_unit)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#mobility_type" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does add an error when the mobility type is invalid" do
|
|
|
|
location.mobility_type = nil
|
|
|
|
location.valid?(:mobility_type)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "#availability" do
|
|
|
|
let(:location) { FactoryBot.build(:location) }
|
|
|
|
|
|
|
|
it "does add an error when the availability is invalid" do
|
|
|
|
location.startdate = Time.zone.local(1, 1, 1)
|
|
|
|
location.valid?(:startdate)
|
|
|
|
expect(location.errors.count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "paper trail" do
|
|
|
|
let(:location) { FactoryBot.create(:location) }
|
|
|
|
let!(:name) { location.name }
|
|
|
|
|
|
|
|
it "creates a record of changes to a log" do
|
|
|
|
expect { location.update!(name: "new test name") }.to change(location.versions, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "allows lettings logs to be restored to a previous version" do
|
|
|
|
location.update!(name: "new test name")
|
|
|
|
expect(location.paper_trail.previous_version.name).to eq(name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "scopes" do
|
|
|
|
before do
|
|
|
|
FactoryBot.create(:location, name: "ABC", postcode: "NW1 8RR", startdate: Time.zone.today)
|
|
|
|
FactoryBot.create(:location, name: "XYZ", postcode: "SE1 6HJ", startdate: Time.zone.today + 1.day)
|
|
|
|
FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: Time.zone.today - 1.day, units: nil)
|
|
|
|
FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when searching by name" do
|
|
|
|
it "returns case insensitive matching records" do
|
|
|
|
expect(described_class.search_by_name("abc").count).to eq(1)
|
|
|
|
expect(described_class.search_by_name("AbC").count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when searching by postcode" do
|
|
|
|
it "returns case insensitive matching records" do
|
|
|
|
expect(described_class.search_by_postcode("se1 6hj").count).to eq(1)
|
|
|
|
expect(described_class.search_by_postcode("SE1 6HJ").count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when searching by all searchable field" do
|
|
|
|
it "returns case insensitive matching records" do
|
|
|
|
expect(described_class.search_by("aBc").count).to eq(1)
|
|
|
|
expect(described_class.search_by("nw18rr").count).to eq(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when filtering by started locations" do
|
|
|
|
it "returns only locations that started today or earlier" do
|
|
|
|
expect(described_class.started.count).to eq(3)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when filtering by active locations" do
|
|
|
|
it "returns only locations that started today or earlier and are complete (and so confirmed)" do
|
|
|
|
expect(described_class.active.count).to eq(2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "status" do
|
|
|
|
let(:location) { FactoryBot.build(:location, startdate: Time.zone.local(2022, 4, 1)) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
Timecop.freeze(2022, 6, 7)
|
|
|
|
end
|
|
|
|
|
|
|
|
after do
|
|
|
|
Timecop.unfreeze
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when location is not confirmed" do
|
|
|
|
it "returns incomplete " do
|
|
|
|
location.confirmed = false
|
|
|
|
expect(location.status).to eq(:incomplete)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when there have not been any previous deactivations" do
|
|
|
|
it "returns active if the location has no deactivation records" do
|
|
|
|
expect(location.status).to eq(:active)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns deactivating soon if deactivation_date is in the future" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:deactivating_soon)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns deactivated if deactivation_date is in the past" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:deactivated)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns deactivated if deactivation_date is today" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:deactivated)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns reactivating soon if the location has a future reactivation date" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), reactivation_date: Time.zone.local(2022, 6, 8), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:reactivating_soon)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns activating soon if the location has a future startdate" do
|
|
|
|
location.startdate = Time.zone.local(2022, 7, 7)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:activating_soon)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when there have been previous deactivations" do
|
|
|
|
before do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 4), reactivation_date: Time.zone.local(2022, 6, 5), location:)
|
|
|
|
location.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns active if the location has no relevant deactivation records" do
|
|
|
|
expect(location.status).to eq(:active)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns deactivating soon if deactivation_date is in the future" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:deactivating_soon)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns deactivated if deactivation_date is in the past" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:deactivated)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns deactivated if deactivation_date is today" do
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:deactivated)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns reactivating soon if the location has a future reactivation date" do
|
|
|
|
Timecop.freeze(2022, 6, 8)
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), reactivation_date: Time.zone.local(2022, 6, 9), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:reactivating_soon)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns reactivating soon if the location had a deactivation during another deactivation" do
|
|
|
|
Timecop.freeze(2022, 6, 4)
|
|
|
|
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 2), location:)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:reactivating_soon)
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns activating soon if the location has a future startdate" do
|
|
|
|
location.startdate = Time.zone.local(2022, 7, 7)
|
|
|
|
location.save!
|
|
|
|
expect(location.status).to eq(:activating_soon)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "available_from" do
|
|
|
|
context "when there is a startdate" do
|
|
|
|
let(:location) { FactoryBot.build(:location, startdate: Time.zone.local(2022, 4, 6)) }
|
|
|
|
|
|
|
|
it "returns the startdate" do
|
|
|
|
expect(location.available_from).to eq(Time.zone.local(2022, 4, 6))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when there is no start date" do
|
|
|
|
context "and the location was created at the start of the 2022/23 collection window" do
|
|
|
|
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2022, 4, 6), startdate: nil) }
|
|
|
|
|
|
|
|
it "returns the beginning of 22/23 collection window" do
|
|
|
|
expect(location.available_from).to eq(Time.zone.local(2022, 4, 1))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "and the location was created at the end of the 2022/23 collection window" do
|
|
|
|
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2023, 2, 6), startdate: nil) }
|
|
|
|
|
|
|
|
it "returns the beginning of 22/23 collection window" do
|
|
|
|
expect(location.available_from).to eq(Time.zone.local(2022, 4, 1))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "and the location was created at the start of the 2021/22 collection window" do
|
|
|
|
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2021, 4, 6), startdate: nil) }
|
|
|
|
|
|
|
|
it "returns the beginning of 21/22 collection window" do
|
|
|
|
expect(location.available_from).to eq(Time.zone.local(2021, 4, 1))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "and the location was created at the end of the 2021/22 collection window" do
|
|
|
|
let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2022, 2, 6), startdate: nil) }
|
|
|
|
|
|
|
|
it "returns the beginning of 21/22 collection window" do
|
|
|
|
expect(location.available_from).to eq(Time.zone.local(2021, 4, 1))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|