Browse Source

Update validator_spec

pull/2509/head
Rachael Booth 2 years ago
parent
commit
5db0480bfd
  1. 2
      spec/factories/bulk_upload.rb
  2. 360
      spec/services/bulk_upload/lettings/validator_spec.rb
  3. 35
      spec/support/bulk_upload/lettings_log_to_csv.rb

2
spec/factories/bulk_upload.rb

@ -4,7 +4,7 @@ FactoryBot.define do
factory :bulk_upload do factory :bulk_upload do
user user
log_type { BulkUpload.log_types.values.sample } log_type { BulkUpload.log_types.values.sample }
year { 2023 } year { 2024 }
identifier { SecureRandom.uuid } identifier { SecureRandom.uuid }
sequence(:filename) { |n| "bulk-upload-#{n}.csv" } sequence(:filename) { |n| "bulk-upload-#{n}.csv" }
needstype { 1 } needstype { 1 }

360
spec/services/bulk_upload/lettings/validator_spec.rb

@ -3,186 +3,112 @@ require "rails_helper"
RSpec.describe BulkUpload::Lettings::Validator do RSpec.describe BulkUpload::Lettings::Validator do
subject(:validator) { described_class.new(bulk_upload:, path:) } subject(:validator) { described_class.new(bulk_upload:, path:) }
let(:organisation) { create(:organisation, old_visible_id: "3") } let(:organisation) { create(:organisation, old_visible_id: "3", rent_periods: [2]) }
let(:user) { create(:user, organisation:) } let(:user) { create(:user, organisation:) }
let(:log) { build(:lettings_log, :completed, startdate: Time.zone.local(2024, 3, 3)) } let(:log) { build(:lettings_log, :completed, renttype: 1, period: 2, assigned_to: user, owning_organisation: organisation, managing_organisation: organisation) }
let(:bulk_upload) { create(:bulk_upload, user:) } let(:bulk_upload) { create(:bulk_upload, user:, year: 2024) }
let(:path) { file.path } let(:path) { file.path }
let(:file) { Tempfile.new } let(:file) { Tempfile.new }
describe "validations" do describe "validations" do
context "when 2023" do context "when file has headers" do
let(:bulk_upload) { create(:bulk_upload, user:, year: 2023) } context "and is empty" do
it "is not valid" do
context "when file has no headers" do expect(validator).not_to be_valid
context "and too many columns" do expect(validator.errors["base"]).to eql(["Template is blank - The template must be filled in for us to create the logs and check if data is correct."])
before do
file.write(("a" * 143).chars.join(","))
file.write("\n")
file.rewind
end
it "is not valid" do
expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Too many columns, please ensure you have used the correct template"])
end
end
context "and is empty" do
it "is not valid" do
expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Template is blank - The template must be filled in for us to create the logs and check if data is correct."])
end
end
context "and doesn't have too many columns" do
before do
file.write(("a" * 142).chars.join(","))
file.write("\n")
file.rewind
end
it "is valid" do
expect(validator).to be_valid
end
end end
end end
context "when file has headers" do context "and file has extra invalid headers" do
context "and is empty" do let(:seed) { rand }
it "is not valid" do let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
expect(validator).not_to be_valid let(:field_numbers) { log_to_csv.default_2024_field_numbers + %w[invalid_field_number] }
expect(validator.errors["base"]).to eql(["Template is blank - The template must be filled in for us to create the logs and check if data is correct."]) let(:field_values) { log_to_csv.to_2024_row + %w[value_for_invalid_field_number] }
end
end
context "and file has extra invalid headers" do before do
let(:seed) { rand } file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) } file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
let(:field_numbers) { log_to_csv.default_2023_field_numbers + %w[invalid_field_number] } file.rewind
let(:field_values) { log_to_csv.to_2023_row + %w[value_for_invalid_field_number] }
before do
file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.rewind
end
it "is valid" do
expect(validator).to be_valid
end
end end
context "and file has too few valid headers" do it "is valid" do
let(:seed) { rand } expect(validator).to be_valid
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
let(:field_numbers) { log_to_csv.default_2023_field_numbers }
let(:field_values) { log_to_csv.to_2023_row }
before do
field_numbers.delete_at(20)
field_values.delete_at(20)
file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.rewind
end
it "is not valid" do
expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Incorrect number of fields, please ensure you have used the correct template"])
end
end end
end
context "and file has too many valid headers" do context "and file has too few valid headers" do
let(:seed) { rand } let(:seed) { rand }
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) } let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
let(:field_numbers) { log_to_csv.default_2023_field_numbers + %w[23] } let(:field_numbers) { log_to_csv.default_2024_field_numbers }
let(:field_values) { log_to_csv.to_2023_row + %w[value] } let(:field_values) { log_to_csv.to_2024_row }
before do before do
file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:)) field_numbers.delete_at(20)
file.write(log_to_csv.to_custom_csv_row(seed:, field_values:)) field_values.delete_at(20)
file.rewind file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
end file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.rewind
end
it "is not valid" do it "is not valid" do
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Incorrect number of fields, please ensure you have used the correct template"]) expect(validator.errors["base"]).to eql(["Incorrect number of fields, please ensure you have used the correct template"])
end
end end
end end
context "when uploading a 2022 logs for 2023 bulk upload" do context "and file has too many valid headers" do
let(:bulk_upload) { create(:bulk_upload, user:, year: 2023) } let(:seed) { rand }
let(:log) { build(:lettings_log, :completed, startdate: Time.zone.local(2022, 5, 6), tenancycode: "5") } let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
let(:field_numbers) { log_to_csv.default_2024_field_numbers + %w[23] }
let(:field_values) { log_to_csv.to_2024_row + %w[value] }
context "with no headers" do before do
before do file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.close file.rewind
end
it "is not valid" do
expect(validator).not_to be_valid
end
end end
context "with headers" do it "is not valid" do
let(:seed) { rand } expect(validator).not_to be_valid
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) } expect(validator.errors["base"]).to eql(["Incorrect number of fields, please ensure you have used the correct template"])
let(:field_numbers) { log_to_csv.default_2023_field_numbers }
let(:field_values) { log_to_csv.to_2023_row }
before do
file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.rewind
end
it "is not valid" do
expect(validator).not_to be_valid
end
end end
end end
end
context "when uploading a 2023 logs for 2024 bulk upload" do context "when uploading a 2023 logs for 2024 bulk upload" do
let(:bulk_upload) { create(:bulk_upload, user:, year: 2024) } let(:log) { build(:lettings_log, :completed, startdate: Time.zone.local(2023, 5, 6), tenancycode: "5234234234234") }
let(:log) { build(:lettings_log, :completed, startdate: Time.zone.local(2023, 5, 6), tenancycode: "5234234234234") }
context "with no headers" do context "with headers" do
before do let(:seed) { rand }
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n", col_offset: 0).to_2024_csv_row) let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
file.close let(:field_numbers) { log_to_csv.default_2024_field_numbers }
end let(:field_values) { log_to_csv.to_2024_row }
it "is not valid" do before do
expect(validator).not_to be_valid file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
end file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.rewind
end end
context "with headers" do it "is not valid" do
let(:seed) { rand } expect(validator).not_to be_valid
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) } expect(validator.errors["base"]).to eql(["Incorrect start dates, please ensure you have used the correct template"])
let(:field_numbers) { log_to_csv.default_2024_field_numbers }
let(:field_values) { log_to_csv.to_2024_row }
before do
file.write(log_to_csv.custom_field_numbers_row(seed:, field_numbers:))
file.write(log_to_csv.to_custom_csv_row(seed:, field_values:))
file.rewind
end
it "is not valid" do
expect(validator).not_to be_valid
end
end end
end end
end end
end end
describe "#call" do describe "#call" do
context "when a valid csv" do context "with an invalid 2024 csv" do
let(:path) { file_fixture("2023_24_lettings_bulk_upload_invalid.csv") } let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
before do
values = log_to_csv.to_2024_row
values[7] = nil
file.write(log_to_csv.default_2024_field_numbers_row)
file.write(log_to_csv.to_custom_csv_row(seed: nil, field_values: values))
file.rewind
end
it "creates validation errors" do it "creates validation errors" do
expect { validator.call }.to change(BulkUploadError, :count) expect { validator.call }.to change(BulkUploadError, :count)
@ -191,36 +117,41 @@ RSpec.describe BulkUpload::Lettings::Validator do
it "create validation error with correct values" do it "create validation error with correct values" do
validator.call validator.call
error = BulkUploadError.find_by(row: "9", field: "field_7", category: "setup") error = BulkUploadError.find_by(row: "2", field: "field_8", category: "setup")
expect(error.field).to eql("field_7") expect(error.field).to eql("field_8")
expect(error.error).to eql("You must answer tenancy start date (day)") expect(error.error).to eql("You must answer tenancy start date (day)")
expect(error.tenant_code).to eql("123") expect(error.tenant_code).to eql(log.tenancycode)
expect(error.property_ref).to be_nil expect(error.property_ref).to eql(log.propcode)
expect(error.row).to eql("9") expect(error.row).to eql("2")
expect(error.cell).to eql("H9") expect(error.cell).to eql("I2")
expect(error.col).to eql("H") expect(error.col).to eql("I")
end end
end end
context "with arbitrary ordered 23/24 csv" do context "with a valid 2024 csv" do
let(:bulk_upload) { create(:bulk_upload, user:, year: 2023) } let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
let(:log) { build(:lettings_log, :completed) }
let(:file) { Tempfile.new }
let(:path) { file.path }
let(:seed) { 321 }
around do |example| before do
FormHandler.instance.use_real_forms! file.write(log_to_csv.default_2024_field_numbers_row)
file.write(log_to_csv.to_2024_csv_row)
example.run file.rewind
end
FormHandler.instance.use_fake_forms! it "does not create validation errors" do
expect { validator.call }.not_to change(BulkUploadError, :count)
end end
end
context "with arbitrary ordered invalid csv" do
let(:seed) { 321 }
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:) }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").default_2023_field_numbers_row(seed:)) values = log_to_csv.to_2024_row
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").to_2023_csv_row(seed:)) values[3] = nil
file.write(log_to_csv.default_2024_field_numbers_row(seed:))
file.write(log_to_csv.to_custom_csv_row(seed:, field_values: values))
file.close file.close
end end
@ -231,15 +162,15 @@ RSpec.describe BulkUpload::Lettings::Validator do
it "create validation error with correct values" do it "create validation error with correct values" do
validator.call validator.call
error = BulkUploadError.find_by(field: "field_5") error = BulkUploadError.find_by(field: "field_4")
expect(error.field).to eql("field_5") expect(error.field).to eql("field_4")
expect(error.error).to eql("You must answer letting type") expect(error.error).to eql("You must answer needs type")
expect(error.tenant_code).to eql(log.tenancycode) expect(error.tenant_code).to eql(log.tenancycode)
expect(error.property_ref).to eql(log.propcode) expect(error.property_ref).to eql(log.propcode)
expect(error.row).to eql("2") expect(error.row).to eql("2")
expect(error.cell).to eql("DD2") expect(error.cell).to eql("CY2")
expect(error.col).to eql("DD") expect(error.col).to eql("CY")
end end
end end
@ -249,31 +180,50 @@ RSpec.describe BulkUpload::Lettings::Validator do
let(:log) { build(:lettings_log, :completed) } let(:log) { build(:lettings_log, :completed) }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").default_2023_field_numbers_row) file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").default_2024_field_numbers_row)
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").to_2024_csv_row)
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n").to_2024_csv_row)
file.close file.close
end end
it "creates errors" do it "creates errors" do
expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file"), :count).by(22) expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file"), :count)
end end
end end
context "with unix line endings" do [
let(:fixture_path) { file_fixture("2023_24_lettings_bulk_upload.csv") } { line_ending: "\n", name: "unix" },
let(:file) { Tempfile.new } { line_ending: "\r\n", name: "windows" },
let(:path) { file.path } ].each do |test_case|
context "with #{test_case[:name]} line endings" do
context "with a valid file" do
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:, line_ending: test_case[:line_ending]) }
before do before do
string = File.read(fixture_path) file.write(log_to_csv.default_2024_field_numbers_row)
string.gsub!("\r\n", "\n") file.write(log_to_csv.to_2024_csv_row)
file.write(string) file.rewind
file.rewind end
end
it "creates validation errors" do it "does not create validation errors" do
expect { validator.call }.to change(BulkUploadError, :count) expect { validator.call }.not_to change(BulkUploadError, :count)
end
end
context "with an invalid file" do
let(:log) { build(:lettings_log, :completed, assigned_to: user, owning_organisation: organisation, managing_organisation: organisation, declaration: nil) }
let(:log_to_csv) { BulkUpload::LettingsLogToCsv.new(log:, line_ending: test_case[:line_ending]) }
before do
file.write(log_to_csv.default_2024_field_numbers_row)
file.write(log_to_csv.to_2024_csv_row)
file.rewind
end
it "creates validation errors" do
expect { validator.call }.to change(BulkUploadError, :count)
end
end
end end
end end
@ -283,7 +233,7 @@ RSpec.describe BulkUpload::Lettings::Validator do
let(:path) { file.path } let(:path) { file.path }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n", col_offset: 0).to_2024_csv_row)
file.close file.close
end end
@ -294,31 +244,13 @@ RSpec.describe BulkUpload::Lettings::Validator do
end end
describe "#create_logs?" do describe "#create_logs?" do
context "when all logs are valid" do
let(:target_path) { file_fixture("2023_24_lettings_bulk_upload.csv") }
it "returns truthy" do
validator.call
expect(validator).to be_create_logs
end
end
context "when there is an invalid log" do
let(:path) { file_fixture("2023_24_lettings_bulk_upload_invalid.csv") }
it "returns falsey" do
validator.call
expect(validator).not_to be_create_logs
end
end
context "when a log is not valid?" do context "when a log is not valid?" do
let(:log_1) { build(:lettings_log, :completed, assigned_to: user) } let(:log_1) { build(:lettings_log, :completed, assigned_to: user) }
let(:log_2) { build(:lettings_log, :completed, assigned_to: user) } let(:log_2) { build(:lettings_log, :completed, assigned_to: user) }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log: log_1, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log: log_1, line_ending: "\r\n", col_offset: 0).to_2024_csv_row)
file.write(BulkUpload::LettingsLogToCsv.new(log: log_2, line_ending: "\r\n", col_offset: 0, overrides: { illness: 100 }).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log: log_2, line_ending: "\r\n", col_offset: 0, overrides: { illness: 100 }).to_2024_csv_row)
file.close file.close
end end
@ -333,8 +265,8 @@ RSpec.describe BulkUpload::Lettings::Validator do
let(:log_2) { build(:lettings_log, :completed, renttype: 1, assigned_to: user) } let(:log_2) { build(:lettings_log, :completed, renttype: 1, assigned_to: user) }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log: log_1, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log: log_1, line_ending: "\r\n", col_offset: 0).to_2024_csv_row)
file.write(BulkUpload::LettingsLogToCsv.new(log: log_2, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log: log_2, line_ending: "\r\n", col_offset: 0).to_2024_csv_row)
file.close file.close
end end
@ -350,7 +282,7 @@ RSpec.describe BulkUpload::Lettings::Validator do
let(:log_1) { build(:lettings_log, :completed, renttype: 1, assigned_to: user, owning_organisation: unaffiliated_org) } let(:log_1) { build(:lettings_log, :completed, renttype: 1, assigned_to: user, owning_organisation: unaffiliated_org) }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log: log_1, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log: log_1, line_ending: "\r\n", col_offset: 0).to_2024_csv_row)
file.close file.close
end end
@ -361,10 +293,10 @@ RSpec.describe BulkUpload::Lettings::Validator do
end end
context "when a log has incomplete setup section" do context "when a log has incomplete setup section" do
let(:log) { build(:lettings_log, :in_progress, assigned_to: user, startdate: Time.zone.local(2022, 5, 1)) } let(:log) { build(:lettings_log, :completed, renttype: 1, declaration: nil, assigned_to: user) }
before do before do
file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n", col_offset: 0).to_2023_csv_row) file.write(BulkUpload::LettingsLogToCsv.new(log:, line_ending: "\r\n", col_offset: 0).to_2024_csv_row)
file.close file.close
end end

35
spec/support/bulk_upload/lettings_log_to_csv.rb

@ -93,14 +93,14 @@ class BulkUpload::LettingsLogToCsv
log.managing_organisation&.old_visible_id, log.managing_organisation&.old_visible_id,
log.assigned_to&.email, log.assigned_to&.email,
log.needstype, log.needstype,
"S#{log.scheme&.id}", log.scheme&.id ? "S#{log.scheme&.id}" : "",
log.location&.id, log.location&.id,
renewal, renewal,
log.startdate&.day, log.startdate&.day,
log.startdate&.month, log.startdate&.month,
log.startdate&.strftime("%y"), # 10 log.startdate&.strftime("%y"), # 10
london_affordable_rent, rent_type,
log.irproduct_other, log.irproduct_other,
log.tenancycode, log.tenancycode,
log.propcode, log.propcode,
@ -137,7 +137,7 @@ class BulkUpload::LettingsLogToCsv
log.age1 || overrides[:age1], log.age1 || overrides[:age1],
log.sex1, log.sex1,
log.ethnic, log.ethnic,
log.national, log.nationality_all_group,
log.ecstat1, log.ecstat1,
log.relat2, log.relat2,
log.age2 || overrides[:age2], log.age2 || overrides[:age2],
@ -214,11 +214,11 @@ class BulkUpload::LettingsLogToCsv
cbl, cbl,
chr, chr,
cap, cap,
nil, # accessible register accessible_register,
log.referral, log.referral,
net_income_known, net_income_known,
log.earnings,
log.incfreq, log.incfreq,
log.earnings,
log.hb, # 120 log.hb, # 120
log.benefits, log.benefits,
@ -392,9 +392,7 @@ class BulkUpload::LettingsLogToCsv
end end
def to_custom_csv_row(seed: nil, field_values: nil) def to_custom_csv_row(seed: nil, field_values: nil)
if seed row = seed ? field_values.shuffle(random: Random.new(seed)) : field_values
row = field_values.shuffle(random: Random.new(seed))
end
(row_prefix + row).flatten.join(",") + line_ending (row_prefix + row).flatten.join(",") + line_ending
end end
@ -422,6 +420,23 @@ private
end end
end end
def rent_type
case log.renttype
when LettingsLog::RENT_TYPE[:social_rent]
1
when LettingsLog::RENT_TYPE[:affordable_rent]
2
when LettingsLog::RENT_TYPE[:london_affordable_rent]
3
when LettingsLog::RENT_TYPE[:rent_to_buy]
4
when LettingsLog::RENT_TYPE[:london_living_rent]
5
when LettingsLog::RENT_TYPE[:other_intermediate_rent_product]
6
end
end
def leftreg def leftreg
case log.leftreg case log.leftreg
when 3 when 3
@ -471,6 +486,10 @@ private
checkbox_value(log.cap) checkbox_value(log.cap)
end end
def accessible_register
checkbox_value(log.accessible_register)
end
def checkbox_value(field) def checkbox_value(field)
case field case field
when 0 when 0

Loading…
Cancel
Save