Browse Source

Merge branch 'main' into CLDC-1436-csv-schemes-info

# Conflicts:
#	app/services/csv/case_log_csv_service.rb
#	spec/fixtures/files/case_logs_download.csv
#	spec/services/csv/case_log_csv_service_spec.rb
pull/852/head
natdeanlewissoftwire 3 years ago
parent
commit
6f374c90d0
  1. 53
      app/models/case_log.rb
  2. 23
      app/models/derived_variables/case_log_variables.rb
  3. 2
      app/models/scheme.rb
  4. 10
      app/models/validations/household_validations.rb
  5. 24
      app/services/archive_storage_service.rb
  6. 54
      app/services/configuration/configuration_service.rb
  7. 37
      app/services/configuration/env_configuration_service.rb
  8. 23
      app/services/configuration/paas_configuration_service.rb
  9. 9
      app/services/imports/case_logs_import_service.rb
  10. 62
      app/services/paas_configuration_service.rb
  11. 78
      app/services/s3_storage_service.rb
  12. 26
      app/services/storage/archive_service.rb
  13. 80
      app/services/storage/s3_service.rb
  14. 19
      app/services/storage/storage_service.rb
  15. 17
      app/services/storage_service.rb
  16. 82
      config/forms/2021_2022.json
  17. 82
      config/forms/2022_2023.json
  18. 5
      config/initializers/rack_attack.rb
  19. 4
      config/locales/en.yml
  20. 8
      db/migrate/20220809100723_add_accessibility_requirements_fields.rb
  21. 43
      docs/infrastructure.md
  22. 2
      lib/tasks/data_export.rake
  23. 2
      lib/tasks/data_import.rake
  24. 2
      lib/tasks/data_import_field.rake
  25. 4
      lib/tasks/full_import.rake
  26. 3
      spec/factories/case_log.rb
  27. 16
      spec/features/form/checkboxes_spec.rb
  28. 11
      spec/fixtures/complete_case_log.json
  29. 656
      spec/fixtures/forms/2021_2022.json
  30. 12
      spec/lib/tasks/data_export_spec.rb
  31. 22
      spec/lib/tasks/data_import_spec.rb
  32. 14
      spec/lib/tasks/date_import_field_spec.rb
  33. 12
      spec/lib/tasks/full_import_spec.rb
  34. 125
      spec/models/case_log_spec.rb
  35. 40
      spec/models/validations/household_validations_spec.rb
  36. 128
      spec/services/configuration/env_configuration_service_spec.rb
  37. 120
      spec/services/configuration/paas_configuration_service_spec.rb
  38. 18
      spec/services/csv/case_log_csv_service_spec.rb
  39. 2
      spec/services/exports/case_log_export_service_spec.rb
  40. 2
      spec/services/imports/case_logs_field_import_service_spec.rb
  41. 2
      spec/services/imports/case_logs_import_service_spec.rb
  42. 2
      spec/services/imports/data_protection_confirmation_import_service_spec.rb
  43. 2
      spec/services/imports/organisation_import_service_spec.rb
  44. 2
      spec/services/imports/organisation_rent_period_import_service_spec.rb
  45. 2
      spec/services/imports/scheme_import_service_spec.rb
  46. 2
      spec/services/imports/scheme_location_import_service_spec.rb
  47. 2
      spec/services/imports/user_import_service_spec.rb
  48. 2
      spec/services/storage/archive_service_spec.rb
  49. 28
      spec/services/storage/s3_service_spec.rb

53
app/models/case_log.rb

@ -567,7 +567,6 @@ private
def reset_derived_questions
dependent_questions = { waityear: [{ key: :renewal, value: 0 }],
homeless: [{ key: :renewal, value: 0 }],
referral: [{ key: :renewal, value: 0 }],
underoccupation_benefitcap: [{ key: :renewal, value: 0 }],
wchair: [{ key: :needstype, value: 1 }],
@ -693,30 +692,6 @@ private
end
end
def get_housingneeds
return 1 if has_housingneeds?
return 2 if no_housingneeds?
return 3 if unknown_housingneeds?
end
def has_housingneeds?
if [housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f].any?(1)
1
end
end
def no_housingneeds?
if housingneeds_g == 1
1
end
end
def unknown_housingneeds?
if housingneeds_h == 1
1
end
end
def all_fields_completed?
subsection_statuses = form.subsections.map { |subsection| subsection.status(self) }.uniq
subsection_statuses == [:completed]
@ -754,4 +729,32 @@ private
def upcase_and_remove_whitespace(string)
string.present? ? string.upcase.gsub(/\s+/, "") : string
end
def fully_wheelchair_accessible?
housingneeds_type.present? && housingneeds_type.zero?
end
def essential_wheelchair_access?
housingneeds_type == 1
end
def level_access_housing?
housingneeds_type == 2
end
def other_housingneeds?
housingneeds_other == 1
end
def has_housingneeds?
housingneeds == 1
end
def no_housingneeds?
housingneeds == 2
end
def unknown_housingneeds?
housingneeds == 3
end
end

23
app/models/derived_variables/case_log_variables.rb

@ -43,10 +43,8 @@ module DerivedVariables::CaseLogVariables
self.has_benefits = get_has_benefits
self.tshortfall_known = 0 if tshortfall
self.nocharge = household_charge&.zero? ? 1 : 0
self.housingneeds = get_housingneeds
if is_renewal?
self.underoccupation_benefitcap = 2 if collection_start_year == 2021
self.homeless = 1
self.referral = 0
self.waityear = 2
if is_general_needs?
@ -70,6 +68,8 @@ module DerivedVariables::CaseLogVariables
self.voiddate = startdate
end
end
set_housingneeds_fields if housingneeds?
end
private
@ -186,4 +186,23 @@ private
self.location = scheme.locations.first
end
end
def set_housingneeds_fields
self.housingneeds_a = fully_wheelchair_accessible? ? 1 : 0
self.housingneeds_b = essential_wheelchair_access? ? 1 : 0
self.housingneeds_c = level_access_housing? ? 1 : 0
self.housingneeds_f = other_housingneeds? ? 1 : 0
set_housingneeds_values_to_zero unless has_housingneeds?
self.housingneeds_g = no_housingneeds? ? 1 : 0
self.housingneeds_h = unknown_housingneeds? ? 1 : 0
end
def set_housingneeds_values_to_zero
self.housingneeds_a = 0
self.housingneeds_b = 0
self.housingneeds_c = 0
self.housingneeds_f = 0
self.housingneeds_g = 0
self.housingneeds_h = 0
end
end

2
app/models/scheme.rb

@ -112,7 +112,7 @@ class Scheme < ApplicationRecord
def check_details_attributes
[
{ name: "Service code", value: id_to_display, id: "id" },
{ name: "Scheme code", value: id_to_display, id: "id" },
{ name: "Name", value: service_name, id: "service_name" },
{ name: "Confidential information", value: sensitive, id: "sensitive" },
{ name: "Type of scheme", value: scheme_type, id: "scheme_type" },

10
app/models/validations/household_validations.rb

@ -54,16 +54,6 @@ module Validations::HouseholdValidations
validate_person_age_matches_economic_status(record, 1)
end
def validate_accessibility_requirements(record)
all_options = [record.housingneeds_a, record.housingneeds_b, record.housingneeds_c, record.housingneeds_f, record.housingneeds_g, record.housingneeds_h]
if all_options.count(1) > 1
mobility_accessibility_options = [record.housingneeds_a, record.housingneeds_b, record.housingneeds_c]
unless all_options.count(1) == 2 && record.housingneeds_f == 1 && mobility_accessibility_options.any? { |x| x == 1 }
record.errors.add :accessibility_requirements, I18n.t("validations.household.housingneeds_a.one_or_two_choices")
end
end
end
def validate_condition_effects(record)
all_options = [record.illness_type_1, record.illness_type_2, record.illness_type_3, record.illness_type_4, record.illness_type_5, record.illness_type_6, record.illness_type_7, record.illness_type_8, record.illness_type_9, record.illness_type_10]
if all_options.count(1) >= 1 && household_no_illness?(record)

24
app/services/archive_storage_service.rb

@ -1,24 +0,0 @@
class ArchiveStorageService < StorageService
MAX_SIZE = 50 * (1024**2) # 50MiB
def initialize(archive_io)
super()
@archive = Zip::File.open_buffer(archive_io)
end
def list_files(folder)
@archive.glob(File.join(folder, "*.*"))
.map(&:name)
end
def folder_present?(folder)
!list_files(folder).empty?
end
def get_file_io(file_name)
entry = @archive.get_entry(file_name)
raise "File too large to be extracted" if entry.size > MAX_SIZE
entry.get_input_stream
end
end

54
app/services/configuration/configuration_service.rb

@ -0,0 +1,54 @@
module Configuration
class ConfigurationService
attr_reader :s3_buckets, :redis_uris
def initialize(logger = Rails.logger)
@logger = logger
@config = read_config
@s3_buckets = read_s3_buckets
@redis_uris = read_redis_uris
end
def s3_config_present?
config_present? && @config.key?(:"aws-s3-bucket")
end
def redis_config_present?
config_present? && @config.key?(:redis)
end
private
def config_present?
raise NotImplementedError
end
def read_config
raise NotImplementedError
end
def read_s3_buckets
return {} unless s3_config_present?
s3_buckets = {}
@config[:"aws-s3-bucket"].each do |bucket_config|
if bucket_config.key?(:instance_name)
s3_buckets[bucket_config[:instance_name].to_sym] = bucket_config
end
end
s3_buckets
end
def read_redis_uris
return {} unless redis_config_present?
redis_uris = {}
@config[:redis].each do |redis_config|
if redis_config.key?(:instance_name)
redis_uris[redis_config[:instance_name].to_sym] = redis_config.dig(:credentials, :uri)
end
end
redis_uris
end
end
end

37
app/services/configuration/env_configuration_service.rb

@ -0,0 +1,37 @@
module Configuration
class EnvConfigurationService < ConfigurationService
private
def config_present?
!ENV["S3_CONFIG"].nil? || !ENV["REDIS_CONFIG"].nil?
end
def read_config
unless config_present?
@logger.warn("Could not find S3_CONFIG or REDIS_CONFIG in the environment variables!")
return {}
end
config = {}
assign_config(config, :"aws-s3-bucket", "S3_CONFIG")
assign_config(config, :redis, "REDIS_CONFIG")
config
end
def assign_config(config, symbol, env_variable)
config_hash = parse_json_config(env_variable)
config[symbol] = config_hash unless config_hash.empty?
end
def parse_json_config(env_variable_name)
if ENV[env_variable_name].present?
begin
return JSON.parse(ENV[env_variable_name], { symbolize_names: true })
rescue StandardError
@logger.warn("Could not parse #{env_variable_name}!")
end
end
{}
end
end
end

23
app/services/configuration/paas_configuration_service.rb

@ -0,0 +1,23 @@
module Configuration
class PaasConfigurationService < ConfigurationService
private
def config_present?
!ENV["VCAP_SERVICES"].nil?
end
def read_config
unless config_present?
@logger.warn("Could not find VCAP_SERVICES in the environment variables!")
return {}
end
begin
JSON.parse(ENV["VCAP_SERVICES"], { symbolize_names: true })
rescue StandardError
@logger.warn("Could not parse VCAP_SERVICES!")
{}
end
end
end
end

9
app/services/imports/case_logs_import_service.rb

@ -107,6 +107,13 @@ module Imports
%w[a b c f g h].each do |letter|
attributes["housingneeds_#{letter}"] = housing_needs(xml_doc, letter)
end
attributes["housingneeds"] = 1 if [attributes["housingneeds_a"], attributes["housingneeds_b"], attributes["housingneeds_c"], attributes["housingneeds_f"]].any? { |housingneed| housingneed == 1 }
attributes["housingneeds"] = 2 if attributes["housingneeds_g"] == 1
attributes["housingneeds"] = 3 if attributes["housingneeds_h"] == 1
attributes["housingneeds_type"] = 0 if attributes["housingneeds_a"] == 1
attributes["housingneeds_type"] = 1 if attributes["housingneeds_b"] == 1
attributes["housingneeds_type"] = 2 if attributes["housingneeds_c"] == 1
attributes["housingneeds_other"] = attributes["housingneeds_f"] == 1 ? 1 : 0
attributes["illness"] = unsafe_string_as_integer(xml_doc, "Q10ia")
(1..10).each do |index|
@ -275,7 +282,7 @@ module Imports
end
def fields_not_present_in_softwire_data
%w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check]
%w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other]
end
def check_status_completed(case_log, previous_status)

62
app/services/paas_configuration_service.rb

@ -1,62 +0,0 @@
class PaasConfigurationService
attr_reader :s3_buckets, :redis_uris
def initialize(logger = Rails.logger)
@logger = logger
@paas_config = read_pass_config
@s3_buckets = read_s3_buckets
@redis_uris = read_redis_uris
end
def config_present?
!ENV["VCAP_SERVICES"].nil?
end
def s3_config_present?
config_present? && @paas_config.key?(:"aws-s3-bucket")
end
def redis_config_present?
config_present? && @paas_config.key?(:redis)
end
private
def read_pass_config
unless config_present?
@logger.warn("Could not find VCAP_SERVICES in the environment!")
return {}
end
begin
JSON.parse(ENV["VCAP_SERVICES"], { symbolize_names: true })
rescue StandardError
@logger.warn("Could not parse VCAP_SERVICES!")
{}
end
end
def read_s3_buckets
return {} unless s3_config_present?
s3_buckets = {}
@paas_config[:"aws-s3-bucket"].each do |bucket_config|
if bucket_config.key?(:instance_name)
s3_buckets[bucket_config[:instance_name].to_sym] = bucket_config
end
end
s3_buckets
end
def read_redis_uris
return {} unless redis_config_present?
redis_uris = {}
@paas_config[:redis].each do |redis_config|
if redis_config.key?(:instance_name)
redis_uris[redis_config[:instance_name].to_sym] = redis_config.dig(:credentials, :uri)
end
end
redis_uris
end
end

78
app/services/s3_storage_service.rb

@ -1,78 +0,0 @@
class S3StorageService < StorageService
attr_reader :configuration
def initialize(paas_config_service, paas_instance_name)
super()
@paas_config_service = paas_config_service
@paas_instance_name = (paas_instance_name || "").to_sym
@configuration = create_configuration
@client = create_client
end
def list_files(folder)
@client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder)
.flat_map { |response| response.contents.map(&:key) }
end
def folder_present?(folder)
response = @client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder, max_keys: 1)
response.key_count == 1
end
def get_file_io(file_name)
@client.get_object(bucket: @configuration.bucket_name, key: file_name)
.body
end
def write_file(file_name, data)
@client.put_object(
body: data,
bucket: @configuration.bucket_name,
key: file_name,
)
end
private
def create_configuration
unless @paas_config_service.config_present?
raise "No PaaS configuration present"
end
unless @paas_config_service.s3_buckets.key?(@paas_instance_name)
raise "#{@paas_instance_name} instance name could not be found"
end
bucket_config = @paas_config_service.s3_buckets[@paas_instance_name]
StorageConfiguration.new(bucket_config[:credentials])
end
def create_client
credentials =
Aws::Credentials.new(
@configuration.access_key_id,
@configuration.secret_access_key,
)
Aws::S3::Client.new(
region: @configuration.region,
credentials:,
)
end
end
class StorageConfiguration
attr_reader :access_key_id, :secret_access_key, :bucket_name, :region
def initialize(credentials)
@access_key_id = credentials[:aws_access_key_id]
@secret_access_key = credentials[:aws_secret_access_key]
@bucket_name = credentials[:bucket_name]
@region = credentials[:aws_region]
end
def ==(other)
@access_key_id == other.access_key_id &&
@secret_access_key == other.secret_access_key &&
@bucket_name == other.bucket_name &&
@region == other.region
end
end

26
app/services/storage/archive_service.rb

@ -0,0 +1,26 @@
module Storage
class ArchiveService < StorageService
MAX_SIZE = 50 * (1024**2) # 50MiB
def initialize(archive_io)
super()
@archive = Zip::File.open_buffer(archive_io)
end
def list_files(folder)
@archive.glob(File.join(folder, "*.*"))
.map(&:name)
end
def folder_present?(folder)
!list_files(folder).empty?
end
def get_file_io(file_name)
entry = @archive.get_entry(file_name)
raise "File too large to be extracted" if entry.size > MAX_SIZE
entry.get_input_stream
end
end
end

80
app/services/storage/s3_service.rb

@ -0,0 +1,80 @@
module Storage
class S3Service < StorageService
attr_reader :configuration
def initialize(config_service, paas_instance_name)
super()
@config_service = config_service
@instance_name = (paas_instance_name || "").to_sym
@configuration = create_configuration
@client = create_client
end
def list_files(folder)
@client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder)
.flat_map { |response| response.contents.map(&:key) }
end
def folder_present?(folder)
response = @client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder, max_keys: 1)
response.key_count == 1
end
def get_file_io(file_name)
@client.get_object(bucket: @configuration.bucket_name, key: file_name)
.body
end
def write_file(file_name, data)
@client.put_object(
body: data,
bucket: @configuration.bucket_name,
key: file_name,
)
end
private
def create_configuration
unless @config_service.s3_config_present?
raise "No S3 bucket is present in the PaaS configuration"
end
unless @config_service.s3_buckets.key?(@instance_name)
raise "#{@instance_name} instance name could not be found"
end
bucket_config = @config_service.s3_buckets[@instance_name]
StorageConfiguration.new(bucket_config[:credentials])
end
def create_client
credentials =
Aws::Credentials.new(
@configuration.access_key_id,
@configuration.secret_access_key,
)
Aws::S3::Client.new(
region: @configuration.region,
credentials:,
)
end
end
class StorageConfiguration
attr_reader :access_key_id, :secret_access_key, :bucket_name, :region
def initialize(credentials)
@access_key_id = credentials[:aws_access_key_id]
@secret_access_key = credentials[:aws_secret_access_key]
@bucket_name = credentials[:bucket_name]
@region = credentials[:aws_region]
end
def ==(other)
@access_key_id == other.access_key_id &&
@secret_access_key == other.secret_access_key &&
@bucket_name == other.bucket_name &&
@region == other.region
end
end
end

19
app/services/storage/storage_service.rb

@ -0,0 +1,19 @@
module Storage
class StorageService
def list_files(_folder)
raise NotImplementedError
end
def folder_present?(_folder)
raise NotImplementedError
end
def get_file_io(_file_name)
raise NotImplementedError
end
def write_file(_file_name, _data)
raise NotImplementedError
end
end
end

17
app/services/storage_service.rb

@ -1,17 +0,0 @@
class StorageService
def list_files(_folder)
raise NotImplementedError
end
def folder_present?(_folder)
raise NotImplementedError
end
def get_file_io(_file_name)
raise NotImplementedError
end
def write_file(_file_name, _data)
raise NotImplementedError
end
end

82
config/forms/2021_2022.json

@ -790,7 +790,7 @@
}
]
},
"header": "Are you sure the time between these dates is correct?",
"header": "Are you sure the property has been vacant for this long?",
"type": "interruption_screen",
"answer_options": {
"0": {
@ -919,7 +919,7 @@
}
]
},
"header": "Are you sure the time between these dates is correct?",
"header": "Are you sure the property has been vacant for this long?",
"type": "interruption_screen",
"answer_options": {
"0": {
@ -1242,7 +1242,7 @@
"description": "",
"questions": {
"age1_known": {
"check_answers_card_number": 1,
"check_answers_card_number": 1,
"header": "Do you know the lead tenant’s age?",
"hint_text": "The ’lead’ or ’main’ tenant is the person in the household who does the most paid work. If several people do the same paid work, the lead tenant is whoever is the oldest.",
"type": "radio",
@ -5667,40 +5667,79 @@
}
}
},
"access_needs": {
"access_needs_exist": {
"header": "",
"description": "",
"questions": {
"accessibility_requirements": {
"housingneeds": {
"header": "Does anybody in the household have any disabled access needs?",
"hint_text": "",
"type": "checkbox",
"check_answer_label": "Anybody in household with disabled access needs",
"type": "radio",
"check_answer_label": "Anybody with disabled access needs",
"answer_options": {
"housingneeds_a": {
"1": {
"value": "Yes"
},
"2": {
"value": "No"
},
"divider": {
"value": true
},
"3": {
"value": "Don’t know"
}
}
}
}
},
"type_of_access_needs": {
"header": "Disabled access needs",
"description": "",
"questions": {
"housingneeds_type": {
"header": "What type of access need do they have?",
"hint_text": "",
"type": "radio",
"check_answer_label": "Disabled access needs",
"answer_options": {
"0": {
"value": "Fully wheelchair accessible housing"
},
"housingneeds_b": {
"1": {
"value": "Wheelchair access to essential rooms"
},
"housingneeds_c": {
"2": {
"value": "Level access housing"
},
"housingneeds_f": {
"value": "Other disabled access needs"
},
"divider": {
"value": true
},
"housingneeds_g": {
"value": "No disabled access needs"
"3": {
"value": "None of the above"
}
}
},
"housingneeds_other": {
"header": "Do they have any other access needs?",
"hint_text": "",
"type": "radio",
"check_answer_label": "Other disabled access needs",
"answer_options": {
"1": {
"value": "Yes"
},
"housingneeds_h": {
"value": "Don’t know"
"0": {
"value": "No"
}
}
}
}
},
"depends_on": [
{
"housingneeds": 1
}
]
},
"health_conditions": {
"header": "",
@ -6209,12 +6248,7 @@
}
}
}
},
"depends_on": [
{
"renewal": 0
}
]
}
},
"previous_postcode": {
"header": "",

82
config/forms/2022_2023.json

@ -790,7 +790,7 @@
}
]
},
"header": "Are you sure the time between these dates is correct?",
"header": "Are you sure the property has been vacant for this long?",
"type": "interruption_screen",
"answer_options": {
"0": {
@ -919,7 +919,7 @@
}
]
},
"header": "Are you sure the time between these dates is correct?",
"header": "Are you sure the property has been vacant for this long?",
"type": "interruption_screen",
"answer_options": {
"0": {
@ -1277,7 +1277,7 @@
"description": "",
"questions": {
"age1_known": {
"check_answers_card_number": 1,
"check_answers_card_number": 1,
"header": "Do you know the lead tenant’s age?",
"hint_text": "The ’lead’ or ’main’ tenant is the person in the household who does the most paid work. If several people do the same paid work, the lead tenant is whoever is the oldest.",
"type": "radio",
@ -5669,40 +5669,79 @@
}
}
},
"access_needs": {
"access_needs_exist": {
"header": "",
"description": "",
"questions": {
"accessibility_requirements": {
"housingneeds": {
"header": "Does anybody in the household have any disabled access needs?",
"hint_text": "",
"type": "checkbox",
"check_answer_label": "Anybody in household with disabled access needs",
"type": "radio",
"check_answer_label": "Anybody with disabled access needs",
"answer_options": {
"housingneeds_a": {
"1": {
"value": "Yes"
},
"2": {
"value": "No"
},
"divider": {
"value": true
},
"3": {
"value": "Don’t know"
}
}
}
}
},
"type_of_access_needs": {
"header": "Disabled access needs",
"description": "",
"questions": {
"housingneeds_type": {
"header": "What type of access need do they have?",
"hint_text": "",
"type": "radio",
"check_answer_label": "Disabled access needs",
"answer_options": {
"0": {
"value": "Fully wheelchair accessible housing"
},
"housingneeds_b": {
"1": {
"value": "Wheelchair access to essential rooms"
},
"housingneeds_c": {
"2": {
"value": "Level access housing"
},
"housingneeds_f": {
"value": "Other disabled access needs"
},
"divider": {
"value": true
},
"housingneeds_g": {
"value": "No disabled access needs"
"3": {
"value": "None of the above"
}
}
},
"housingneeds_other": {
"header": "Do they have any other access needs?",
"hint_text": "",
"type": "radio",
"check_answer_label": "Other disabled access needs",
"answer_options": {
"1": {
"value": "Yes"
},
"housingneeds_h": {
"value": "Don’t know"
"0": {
"value": "No"
}
}
}
}
},
"depends_on": [
{
"housingneeds": 1
}
]
},
"health_conditions": {
"header": "",
@ -6168,12 +6207,7 @@
}
}
}
},
"depends_on": [
{
"renewal": 0
}
]
}
},
"previous_postcode": {
"header": "",

5
config/initializers/rack_attack.rb

@ -1,10 +1,11 @@
require "paas_configuration_service"
require "configuration/configuration_service"
require "configuration/paas_configuration_service"
if Rails.env.development? || Rails.env.test?
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
Rack::Attack.enabled = false
else
redis_url = PaasConfigurationService.new.redis_uris[:"dluhc-core-#{Rails.env}-redis-rate-limit"]
redis_url = Configuration::PaasConfigurationService.new.redis_uris[:"dluhc-core-#{Rails.env}-redis-rate-limit"]
Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: redis_url)
end

4
config/locales/en.yml

@ -124,8 +124,8 @@ en:
not_first_let: "Major repairs date must not be completed if the tenancy is a first let"
ten_years_before_tenancy_start: "Enter a major repairs completion date that is no more than 10 years before the tenancy start date"
void_date:
ten_years_before_tenancy_start: "Enter a void date must no more than 10 years before the tenancy start date"
before_tenancy_start: "Enter a void date must that is before the tenancy start date"
ten_years_before_tenancy_start: "Enter a void date no more than 10 years before the tenancy start date"
before_tenancy_start: "Enter a void date that is before the tenancy start date"
after_mrcdate: "Void date must be before the major repairs date if provided"
offered:
relet_number: "Enter a number between 0 and 20 for the amount of times the property has been re-let"

8
db/migrate/20220809100723_add_accessibility_requirements_fields.rb

@ -0,0 +1,8 @@
class AddAccessibilityRequirementsFields < ActiveRecord::Migration[7.0]
def change
change_table :case_logs, bulk: true do |t|
t.column :housingneeds_type, :integer
t.column :housingneeds_other, :integer
end
end
end

43
docs/infrastructure.md

@ -4,6 +4,49 @@ nav_order: 5
# Infrastructure
## Configuration
On [GOV.UK PaaS](https://www.cloud.service.gov.uk/), service credentials are appended to the environment variable `VCAP_SERVICES` when services [are bound](https://docs.cloud.service.gov.uk/deploying_services/s3/#bind-an-aws-s3-bucket-to-your-app) to an application.
Such services include datastores and S3 buckets.
Our application uses S3 and Redis clients and supports two different ways of parsing their configuration:
* Via the environment variable `VCAP_SERVICES` using the `PaasConfigurationService` class
* Via the environment variables `S3_CONFIG` and `REDIS_CONFIG` using the `EnvConfigurationService` class
`S3_CONFIG` and `REDIS_CONFIG` are populated using a similar structure than `VCAP_SERVICES`:
S3_CONFIG:
```json
[
{
"instance_name": "bucket_1",
"credentials": {
"aws_access_key_id": "123",
"aws_secret_access_key": "456",
"aws_region": "eu-west-1",
"bucket_name": "my-bucket"
}
}
]
```
REDIS_CONFIG:
```json
[
{
"instance_name": "redis_1",
"credentials": {
"uri": "redis_uri"
}
}
]
```
In order to switch from using [GOV.UK PaaS](https://www.cloud.service.gov.uk/) provided services to external ones, instances of `PaasConfigurationService` need to be replaced by `EnvConfigurationService`.
This assumes that `S3_CONFIG` or/and `REDIS_CONFIG` are available.
Please check `full_import.rake` and `rack_attack.rb` for examples of how the configuration is used.
## Deployment
This application is running on [GOV.UK PaaS](https://www.cloud.service.gov.uk/). To deploy you need to:

2
lib/tasks/data_export.rake

@ -4,7 +4,7 @@ namespace :core do
format = args[:format]
full_update = args[:full_update].present? && args[:full_update] == "true"
storage_service = S3StorageService.new(PaasConfigurationService.new, ENV["EXPORT_PAAS_INSTANCE"])
storage_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["EXPORT_PAAS_INSTANCE"])
export_service = Exports::CaseLogExportService.new(storage_service)
if format.present? && format == "CSV"

2
lib/tasks/data_import.rake

@ -5,7 +5,7 @@ namespace :core do
path = args[:path]
raise "Usage: rake core:data_import['data_type', 'path/to/xml_files']" if path.blank? || type.blank?
storage_service = S3StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"])
storage_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"])
case type
when "organisation"

2
lib/tasks/data_import_field.rake

@ -5,7 +5,7 @@ namespace :core do
path = args[:path]
raise "Usage: rake core:data_import_field['field','path/to/xml_files']" if path.blank? || field.blank?
storage_service = S3StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"])
storage_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"])
# We only allow a reduced list of known fields to be updatable
case field

4
lib/tasks/full_import.rake

@ -6,9 +6,9 @@ namespace :core do
archive_path = args[:archive_path]
raise "Usage: rake core:full_import['path/to/archive']" if archive_path.blank?
s3_service = S3StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"])
s3_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"])
archive_io = s3_service.get_file_io(archive_path)
archive_service = ArchiveStorageService.new(archive_io)
archive_service = Storage::ArchiveService.new(archive_io)
import_list = [
Import.new(Imports::OrganisationImportService, :create_organisations, "institution"),

3
spec/factories/case_log.rb

@ -87,6 +87,9 @@ FactoryBot.define do
chr { 1 }
cap { 0 }
reasonother { nil }
housingneeds { 1 }
housingneeds_type { 0 }
housingneeds_other { 0 }
housingneeds_a { 1 }
housingneeds_b { 0 }
housingneeds_c { 0 }

16
spec/features/form/checkboxes_spec.rb

@ -41,24 +41,24 @@ RSpec.describe "Checkboxes" do
context "when a checkbox question is submitted with invalid answers" do
before do
case_log.update!(illness: 100)
allow(case_log).to receive(:update).and_return(false)
end
it "shows an error summary" do
visit("/logs/#{id}/accessibility-requirements")
page.check("case-log-accessibility-requirements-housingneeds-a-field")
page.check("case-log-accessibility-requirements-housingneeds-c-field")
visit("/logs/#{id}/condition-effects")
page.check("case-log-condition-effects-illness-type-1-field")
page.check("case-log-condition-effects-illness-type-2-field")
click_button("Save and continue")
expect(page).to have_title("Error")
end
it "persists the original selections" do
visit("/logs/#{id}/accessibility-requirements")
page.check("case-log-accessibility-requirements-housingneeds-a-field")
page.check("case-log-accessibility-requirements-housingneeds-c-field")
visit("/logs/#{id}/condition-effects")
page.check("case-log-condition-effects-illness-type-1-field")
page.check("case-log-condition-effects-illness-type-2-field")
click_button("Save and continue")
expect(page).to have_checked_field("case-log-accessibility-requirements-housingneeds-a-field")
expect(page).to have_checked_field("case-log-accessibility-requirements-housingneeds-c-field")
expect(page).to have_checked_field("case-log-condition-effects-illness-type-2-field")
end
end
end

11
spec/fixtures/complete_case_log.json vendored

@ -56,12 +56,10 @@
"chr":0,
"cap":0,
"reasonother":"",
"housingneeds_a":0,
"housingneeds_b":0,
"housingneeds_c":1,
"housingneeds_f":0,
"housingneeds_g":0,
"housingneeds_h":0,
"housingneeds": 1,
"housingneeds_type": 2,
"housingneeds_other": 0,
"housingneeds_c": 1,
"illness_type_1":null,
"illness_type_2":null,
"illness_type_3":null,
@ -155,7 +153,6 @@
"wtcharge":"93.0",
"wtshortfall":null,
"refused":1,
"housingneeds":2,
"wchchrg":null,
"newprop":2,
"relat2":"P",

656
spec/fixtures/forms/2021_2022.json vendored

@ -390,6 +390,9 @@
"depends_on": [
{
"illness": 1
},
{
"illness": 100
}
]
}
@ -634,386 +637,366 @@
"label": true,
"i18n_template": "ecstat1"
},
{"key": "earnings",
{
"key": "earnings",
"label": true,
"i18n_template": "earnings"
}]
},
"questions": {
"net_income_value_check": {
"check_answer_label": "Net income soft validation",
"hidden_in_check_answers": true,
"header": "Are you sure this is correct?",
"type": "interruption_screen",
"answer_options": {
"0": {
"value": "Yes"
},
"1": {
"value": "No"
}
}
]
},
"questions": {
"net_income_value_check": {
"check_answer_label": "Net income soft validation",
"hidden_in_check_answers": true,
"header": "Are you sure this is correct?",
"type": "interruption_screen",
"answer_options": {
"0": {
"value": "Yes"
},
"1": {
"value": "No"
}
}
}
},
"net_income_uc_proportion": {
"questions": {
"benefits": {
"check_answer_label": "Benefits as a proportion of income",
"header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?",
"type": "radio",
"answer_options": {
"0": {
"value":"All"
},
"1": {
"value":"Some"
}
}
},
"net_income_uc_proportion": {
"questions": {
"benefits": {
"check_answer_label": "Benefits as a proportion of income",
"header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?",
"type": "radio",
"answer_options": {
"0": {
"value": "All"
},
"1": {
"value": "Some"
}
}
}
},
"housing_benefit": {
"questions": {
"hb": {
"check_answer_label": "Housing-related benefits received",
"header": "Is the tenant likely to be in receipt of any of these housing-related benefits?",
"type": "radio",
"answer_options": {
"0": {
"value": "Housing benefit"
},
"1": {
"value": "Tenant prefers not to say"
}
}
},
"housing_benefit": {
"questions": {
"hb": {
"check_answer_label": "Housing-related benefits received",
"header": "Is the tenant likely to be in receipt of any of these housing-related benefits?",
"type": "radio",
"answer_options": {
"0": {
"value": "Housing benefit"
},
"conditional_for": {
"conditional_question": [0]
"1": {
"value": "Tenant prefers not to say"
}
},
"conditional_question": {
"check_answer_label": "Conditional Question",
"header": "Question to test page conditions",
"type": "radio",
"answer_options": {
"0": {
"value": "Option A"
},
"1": {
"value": "Option B"
}
"conditional_for": {
"conditional_question": [0]
}
},
"conditional_question": {
"check_answer_label": "Conditional Question",
"header": "Question to test page conditions",
"type": "radio",
"answer_options": {
"0": {
"value": "Option A"
},
"1": {
"value": "Option B"
}
}
}
},
"dependent_page": {
"depends_on": [{ "incfreq": 1 }],
"questions": {
"dependent_question": {
"check_answer_label": "Dependent Question",
"header": "Question to test page routing",
"type": "radio",
"answer_options": {
"0": {
"value": "Option A"
},
"1": {
"value": "Option B"
}
}
},
"dependent_page": {
"depends_on": [{ "incfreq": 1 }],
"questions": {
"dependent_question": {
"check_answer_label": "Dependent Question",
"header": "Question to test page routing",
"type": "radio",
"answer_options": {
"0": {
"value": "Option A"
},
"1": {
"value": "Option B"
}
}
}
}
}
},
"rent_and_charges": {
"label": "Rent",
"pages": {
"rent": {
"questions": {
"period": {
"check_answer_label": "Rent Period",
"header": "Which period are rent and other charges due?",
"type": "radio",
"answer_options": {
"1": {
"value": "Weekly for 52 weeks"
},
"3": {
"value": "Every 4 weeks"
}
}
},
"rent_and_charges": {
"label": "Rent",
"pages": {
"rent": {
"questions": {
"period": {
"check_answer_label": "Rent Period",
"header": "Which period are rent and other charges due?",
"type": "radio",
"answer_options": {
"1": {
"value": "Weekly for 52 weeks"
},
"3": {
"value": "Every 4 weeks"
}
},
"brent": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4,
"fields-to-add": [
"brent",
"scharge",
"pscharge",
"supcharg"
],
"result-field": "tcharge"
},
"scharge": {
"check_answer_label": "Service Charge",
"header": "What is the service charge?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4,
"fields-to-add": [
"brent",
"scharge",
"pscharge",
"supcharg"
],
"result-field": "tcharge"
},
"pscharge": {
"check_answer_label": "Personal Service Charge",
"header": "What is the personal service charge?",
"hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4,
"fields-to-add": [
"brent",
"scharge",
"pscharge",
"supcharg"
],
"result-field": "tcharge"
},
"supcharg": {
"check_answer_label": "Support Charge",
"header": "What is the support charge?",
"hint_text": "This is to fund housing-related support services included in the tenancy agreement",
"type": "numeric",
"min": 0,
"max": 300,
"step": 1,
"width": 4,
"fields-to-add": [
"brent",
"scharge",
"pscharge",
"supcharg"
],
"result-field": "tcharge"
},
"tcharge": {
"check_answer_label": "Total Charge",
"header": "Total charge?",
"hint_text": "This is the total of rent and all charges",
"type": "numeric_output",
"min": 0,
"step": 1,
"width": 4,
"readonly": true,
"requires_js": true
}
},
"brent": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4,
"fields-to-add": ["brent", "scharge", "pscharge", "supcharg"],
"result-field": "tcharge"
},
"scharge": {
"check_answer_label": "Service Charge",
"header": "What is the service charge?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4,
"fields-to-add": ["brent", "scharge", "pscharge", "supcharg"],
"result-field": "tcharge"
},
"pscharge": {
"check_answer_label": "Personal Service Charge",
"header": "What is the personal service charge?",
"hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4,
"fields-to-add": ["brent", "scharge", "pscharge", "supcharg"],
"result-field": "tcharge"
},
"supcharg": {
"check_answer_label": "Support Charge",
"header": "What is the support charge?",
"hint_text": "This is to fund housing-related support services included in the tenancy agreement",
"type": "numeric",
"min": 0,
"max": 300,
"step": 1,
"width": 4,
"fields-to-add": ["brent", "scharge", "pscharge", "supcharg"],
"result-field": "tcharge"
},
"tcharge": {
"check_answer_label": "Total Charge",
"header": "Total charge?",
"hint_text": "This is the total of rent and all charges",
"type": "numeric_output",
"min": 0,
"step": 1,
"width": 4,
"readonly": true,
"requires_js": true
}
},
"weekly_net_income": {
"header": "",
"description": "",
"questions": {
"earnings": {
"check_answer_label": "Total household income",
"header": "How much income does the household have in total every week?",
"hint_text": "",
"type": "numeric",
"min": 0,
"step": "1",
"width": 5,
"prefix": "£",
"suffix": " every week"
}
}
},
"weekly_net_income": {
"header": "",
"description": "",
"questions": {
"earnings": {
"check_answer_label": "Total household income",
"header": "How much income does the household have in total every week?",
"hint_text": "",
"type": "numeric",
"min": 0,
"step": "1",
"width": 5,
"prefix": "£",
"suffix": " every week"
}
}
},
"care_home_charge": {
"questions": {
"offered": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4
}
},
"care_home_charge": {
"questions": {
"offered": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4
}
},
"depends_on": [{"period": 3}]
"depends_on": [{ "period": 3 }]
},
"care_home_charge_bi_weekly": {
"questions": {
"offered": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4
}
},
"care_home_charge_bi_weekly": {
"questions": {
"offered": {
"check_answer_label": "Basic Rent",
"header": "What is the basic rent?",
"hint_text": "Eligible for housing benefit or Universal Credit",
"type": "numeric",
"min": 0,
"step": 1,
"width": 4
}
},
"depends_on": [{"period": 2}]
}
"depends_on": [{ "period": 2 }]
}
}
}
},
"local_authority": {
"label": "Local authority",
"subsections": {
"local_authority": {
"label": "Local authority",
"pages": {
"time_lived_in_la": {
"questions": {
"layear": {
"check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?",
"header": "How long has the household continuously lived in the local authority area where the new letting is located?",
"type": "radio",
"answer_options": {
"0": {
"value": "Just moved to local authority area"
},
"1": {
"value": "Less than 1 year"
},
"2": {
"value": "1 year but under 2 years"
},
"3": {
"value": "2 years but under 3 years"
},
"4": {
"value": "3 years but under 4 years"
},
"5": {
"value": "4 years but under 5 years"
},
"6": {
"value": "5 years or more"
},
"divider": {
"value": true
},
"7": {
"value": "Don’t know"
}
}
},
"local_authority": {
"label": "Local authority",
"subsections": {
"local_authority": {
"label": "Local authority",
"pages": {
"time_lived_in_la": {
"questions": {
"layear": {
"check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?",
"header": "How long has the household continuously lived in the local authority area where the new letting is located?",
"type": "radio",
"answer_options": {
"0": {
"value": "Just moved to local authority area"
},
"hidden_in_check_answers": {
"depends_on": [
{ "layear": 0 },
{ "layear": 1 }
]
"1": {
"value": "Less than 1 year"
},
"2": {
"value": "1 year but under 2 years"
},
"3": {
"value": "2 years but under 3 years"
},
"4": {
"value": "3 years but under 4 years"
},
"5": {
"value": "4 years but under 5 years"
},
"6": {
"value": "5 years or more"
},
"divider": {
"value": true
},
"7": {
"value": "Don’t know"
}
},
"hidden_in_check_answers": {
"depends_on": [{ "layear": 0 }, { "layear": 1 }]
}
},
"depends_on": [{ "renewal": 0 }]
}
},
"time_on_la_waiting_list": {
"questions": {
"lawaitlist": {
"check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?",
"header": "How long has the household been on the local authority waiting list where the new letting is located?",
"type": "radio",
"answer_options": {
"0": {
"value": "Just moved to local authority area"
},
"1": {
"value": "Less than 1 year"
},
"2": {
"value": "1 year but under 2 years"
},
"3": {
"value": "2 years but under 3 years"
},
"4": {
"value": "3 years but under 4 years"
},
"5": {
"value": "4 years but under 5 years"
},
"6": {
"value": "5 years or more"
},
"divider": {
"value": true
},
"7": {
"value": "Don’t know"
}
"depends_on": [{ "renewal": 0 }]
},
"time_on_la_waiting_list": {
"questions": {
"lawaitlist": {
"check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?",
"header": "How long has the household been on the local authority waiting list where the new letting is located?",
"type": "radio",
"answer_options": {
"0": {
"value": "Just moved to local authority area"
},
"1": {
"value": "Less than 1 year"
},
"2": {
"value": "1 year but under 2 years"
},
"3": {
"value": "2 years but under 3 years"
},
"4": {
"value": "3 years but under 4 years"
},
"5": {
"value": "4 years but under 5 years"
},
"6": {
"value": "5 years or more"
},
"divider": {
"value": true
},
"7": {
"value": "Don’t know"
}
}
}
},
"other_postcode": {
"questions": {
"other_postcode": {
"check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation",
"header": "Postcode for the previous accommodation",
"hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed",
"type": "text",
"width": 5,
"conditional_for": { "fake_key": "fake_condition" }
},
"ppostcode_full": {
"check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation",
"header": "Postcode for the previous accommodation",
"hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed",
"type": "text",
"width": 5
}
}
},
"other_postcode": {
"questions": {
"other_postcode": {
"check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation",
"header": "Postcode for the previous accommodation",
"hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed",
"type": "text",
"width": 5,
"conditional_for": { "fake_key": "fake_condition" }
},
"ppostcode_full": {
"check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation",
"header": "Postcode for the previous accommodation",
"hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed",
"type": "text",
"width": 5
}
},
"property_major_repairs": {
"questions": {
"mrcdate": {
"check_answer_label": "What was the major repairs completion date?",
"header": "What was the major repairs completion date?",
"hint_text": "For example, 27 3 2021",
"type": "date"
}
}
},
"property_major_repairs": {
"questions": {
"mrcdate": {
"check_answer_label": "What was the major repairs completion date?",
"header": "What was the major repairs completion date?",
"hint_text": "For example, 27 3 2021",
"type": "date"
}
}
}
}
}
},
"submission": {
"label": "Submission",
"subsections": {
"declaration": {
"label": "Declaration",
"depends_on": [{
}
},
"submission": {
"label": "Submission",
"subsections": {
"declaration": {
"label": "Declaration",
"depends_on": [
{
"household_characteristics": "completed",
"household_needs": "completed",
"property_information": "completed"
}],
"pages": {
"declaration": {
"questions": {
"declaration": {
"check_answer_label": "",
"header": "Submit this lettings log ",
"type": "checkbox",
"answer_options": {
"declaration": {
"value": "The tenant has seen the Department for Levelling Up, Housing & Communities (DLUHC) privacy notice"
}
}
],
"pages": {
"declaration": {
"questions": {
"declaration": {
"check_answer_label": "",
"header": "Submit this lettings log ",
"type": "checkbox",
"answer_options": {
"declaration": {
"value": "The tenant has seen the Department for Levelling Up, Housing & Communities (DLUHC) privacy notice"
}
}
}
@ -1024,3 +1007,4 @@
}
}
}
}

12
spec/lib/tasks/data_export_spec.rb

@ -5,8 +5,8 @@ describe "rake core:data_export", type: task do
subject(:task) { Rake::Task["core:data_export"] }
let(:paas_instance) { "paas_export_instance" }
let(:storage_service) { instance_double(S3StorageService) }
let(:paas_config_service) { instance_double(PaasConfigurationService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) }
let(:export_service) { instance_double(Exports::CaseLogExportService) }
before do
@ -14,8 +14,8 @@ describe "rake core:data_export", type: task do
Rake::Task.define_task(:environment)
task.reenable
allow(S3StorageService).to receive(:new).and_return(storage_service)
allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(Storage::S3Service).to receive(:new).and_return(storage_service)
allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(Exports::CaseLogExportService).to receive(:new).and_return(export_service)
allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("EXPORT_PAAS_INSTANCE").and_return(paas_instance)
@ -23,7 +23,7 @@ describe "rake core:data_export", type: task do
context "when exporting case logs with no parameters" do
it "starts the XML export process" do
expect(S3StorageService).to receive(:new).with(paas_config_service, paas_instance)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, paas_instance)
expect(Exports::CaseLogExportService).to receive(:new).with(storage_service)
expect(export_service).to receive(:export_xml_case_logs)
@ -33,7 +33,7 @@ describe "rake core:data_export", type: task do
context "when exporting case logs with CSV format" do
it "starts the CSV export process" do
expect(S3StorageService).to receive(:new).with(paas_config_service, paas_instance)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, paas_instance)
expect(Exports::CaseLogExportService).to receive(:new).with(storage_service)
expect(export_service).to receive(:export_csv_case_logs)

22
spec/lib/tasks/data_import_spec.rb

@ -5,16 +5,16 @@ describe "rake core:data_import", type: :task do
subject(:task) { Rake::Task["core:data_import"] }
let(:instance_name) { "paas_import_instance" }
let(:storage_service) { instance_double(S3StorageService) }
let(:paas_config_service) { instance_double(PaasConfigurationService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) }
before do
Rake.application.rake_require("tasks/data_import")
Rake::Task.define_task(:environment)
task.reenable
allow(S3StorageService).to receive(:new).and_return(storage_service)
allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(Storage::S3Service).to receive(:new).and_return(storage_service)
allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("IMPORT_PAAS_INSTANCE").and_return(instance_name)
end
@ -29,7 +29,7 @@ describe "rake core:data_import", type: :task do
end
it "creates an organisation from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::OrganisationImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_organisations).with(fixture_path)
@ -47,7 +47,7 @@ describe "rake core:data_import", type: :task do
end
it "creates a user from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::UserImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_users).with(fixture_path)
@ -65,7 +65,7 @@ describe "rake core:data_import", type: :task do
end
it "creates an organisation from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::DataProtectionConfirmationImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_data_protection_confirmations).with(fixture_path)
@ -83,7 +83,7 @@ describe "rake core:data_import", type: :task do
end
it "creates an organisation la from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::OrganisationRentPeriodImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_organisation_rent_periods).with(fixture_path)
@ -101,7 +101,7 @@ describe "rake core:data_import", type: :task do
end
it "creates case logs from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::CaseLogsImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_logs).with(fixture_path)
@ -119,7 +119,7 @@ describe "rake core:data_import", type: :task do
end
it "creates a scheme from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::SchemeImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_schemes).with(fixture_path)
@ -137,7 +137,7 @@ describe "rake core:data_import", type: :task do
end
it "creates a scheme location from the given XML file" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::SchemeLocationImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_scheme_locations).with(fixture_path)

14
spec/lib/tasks/date_import_field_spec.rb

@ -5,16 +5,16 @@ describe "rake core:data_import_field", type: :task do
subject(:task) { Rake::Task["core:data_import_field"] }
let(:instance_name) { "paas_import_instance" }
let(:storage_service) { instance_double(S3StorageService) }
let(:paas_config_service) { instance_double(PaasConfigurationService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) }
before do
Rake.application.rake_require("tasks/data_import_field")
Rake::Task.define_task(:environment)
task.reenable
allow(S3StorageService).to receive(:new).and_return(storage_service)
allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(Storage::S3Service).to receive(:new).and_return(storage_service)
allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("IMPORT_PAAS_INSTANCE").and_return(instance_name)
end
@ -32,7 +32,7 @@ describe "rake core:data_import_field", type: :task do
let(:field) { "tenant_code" }
it "properly configures the storage service" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
task.invoke(field, fixture_path)
end
@ -46,7 +46,7 @@ describe "rake core:data_import_field", type: :task do
let(:field) { "lettings_allocation" }
it "properly configures the storage service" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
task.invoke(field, fixture_path)
end
@ -60,7 +60,7 @@ describe "rake core:data_import_field", type: :task do
let(:field) { "major_repairs" }
it "properly configures the storage service" do
expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name)
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
task.invoke(field, fixture_path)
end

12
spec/lib/tasks/full_import_spec.rb

@ -5,19 +5,19 @@ require "zip"
describe "rake core:full_import", type: :task do
subject(:task) { Rake::Task["core:full_import"] }
let(:s3_service) { instance_double(S3StorageService) }
let(:archive_service) { instance_double(ArchiveStorageService) }
let(:paas_config_service) { instance_double(PaasConfigurationService) }
let(:s3_service) { instance_double(Storage::S3Service) }
let(:archive_service) { instance_double(Storage::ArchiveService) }
let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) }
before do
Rake.application.rake_require("tasks/full_import")
Rake::Task.define_task(:environment)
task.reenable
allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(S3StorageService).to receive(:new).and_return(s3_service)
allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service)
allow(Storage::S3Service).to receive(:new).and_return(s3_service)
allow(s3_service).to receive(:get_file_io)
allow(ArchiveStorageService).to receive(:new).and_return(archive_service)
allow(Storage::ArchiveService).to receive(:new).and_return(archive_service)
end
context "when starting a full import" do

125
spec/models/case_log_spec.rb

@ -139,10 +139,6 @@ RSpec.describe CaseLog do
expect(validator).to receive(:validate_rsnvac)
end
it "validates accessibility requirements" do
expect(validator).to receive(:validate_accessibility_requirements)
end
it "validates referral" do
expect(validator).to receive(:validate_referral)
end
@ -1440,34 +1436,6 @@ RSpec.describe CaseLog do
end
end
context "when the data provider is filling in household needs" do
let!(:case_log) do
described_class.create({
managing_organisation: owning_organisation,
owning_organisation:,
created_by: created_by_user,
})
end
it "correctly derives and saves housing neeeds as 1" do
case_log.update!(housingneeds_a: 1)
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds from case_logs where id=#{case_log.id}").to_a[0]
expect(record_from_db["housingneeds"]).to eq(1)
end
it "correctly derives and saves housing neeeds as 2" do
case_log.update!(housingneeds_g: 1)
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds from case_logs where id=#{case_log.id}").to_a[0]
expect(record_from_db["housingneeds"]).to eq(2)
end
it "correctly derives and saves housing neeeds as 3" do
case_log.update!(housingneeds_h: 1)
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds from case_logs where id=#{case_log.id}").to_a[0]
expect(record_from_db["housingneeds"]).to eq(3)
end
end
context "when it is supported housing and a care home charge has been supplied" do
let!(:case_log) do
described_class.create({
@ -1753,6 +1721,99 @@ RSpec.describe CaseLog do
end
end
end
context "when saving accessibility needs" do
it "derives housingneeds_h as true if 'Don't know' is selected for housingneeds" do
case_log.update!({ housingneeds: 3 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_h"]).to eq(1)
expect(case_log["housingneeds_h"]).to eq(1)
end
it "derives housingneeds_g as true if 'No' is selected for housingneeds" do
case_log.update!({ housingneeds: 2 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_h]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_g"]).to eq(1)
expect(case_log["housingneeds_g"]).to eq(1)
end
it "derives housingneeds_a as true if 'Fully wheelchair accessible' is selected for housingneeds_type" do
case_log.update!({ housingneeds: 1, housingneeds_type: 0 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_a"]).to eq(1)
expect(case_log["housingneeds_a"]).to eq(1)
end
it "derives housingneeds_b as true if 'Wheelchair access to essential rooms' is selected for housingneeds_type" do
case_log.update!({ housingneeds: 1, housingneeds_type: 1 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_a housingneeds_c housingneeds_f housingneeds_g housingneeds_h]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_b"]).to eq(1)
expect(case_log["housingneeds_b"]).to eq(1)
end
it "derives housingneeds_c if 'Level access housing' is selected for housingneeds_type" do
case_log.update!({ housingneeds: 1, housingneeds_type: 2 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_f housingneeds_g housingneeds_h]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_c"]).to eq(1)
expect(case_log["housingneeds_c"]).to eq(1)
end
it "derives housingneeds_f if 'Yes' is selected for housingneeds_other" do
case_log.update!({ housingneeds: 1, housingneeds_other: 1 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_g housingneeds_h]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_f"]).to eq(1)
expect(case_log["housingneeds_f"]).to eq(1)
end
it "clears previously set housingneeds if 'No' is selected for housingneeds" do
case_log.update!({ housingneeds: 1, housingneeds_type: 2, housingneeds_other: 1 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
expect(record_from_db["housingneeds_c"]).to eq(1)
expect(case_log["housingneeds_c"]).to eq(1)
expect(record_from_db["housingneeds_f"]).to eq(1)
expect(case_log["housingneeds_f"]).to eq(1)
case_log.update!({ housingneeds: 2 })
record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0]
not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_h]
not_selected_housingneeds.each do |housingneed|
expect(record_from_db[housingneed]).to eq(0)
expect(case_log[housingneed]).to eq(0)
end
expect(record_from_db["housingneeds_g"]).to eq(1)
expect(case_log["housingneeds_g"]).to eq(1)
end
end
end
describe "optional fields" do

40
spec/models/validations/household_validations_spec.rb

@ -575,46 +575,6 @@ RSpec.describe Validations::HouseholdValidations do
end
end
describe "accessibility requirement validations" do
it "validates that mutually exclusive options can't be selected together" do
record.housingneeds_a = 1
record.housingneeds_b = 1
household_validator.validate_accessibility_requirements(record)
expect(record.errors["accessibility_requirements"])
.to include(match I18n.t("validations.household.housingneeds_a.one_or_two_choices"))
record.housingneeds_a = 0
record.housingneeds_b = 0
record.housingneeds_g = 1
record.housingneeds_f = 1
household_validator.validate_accessibility_requirements(record)
expect(record.errors["accessibility_requirements"])
.to include(match I18n.t("validations.household.housingneeds_a.one_or_two_choices"))
record.housingneeds_a = 1
record.housingneeds_g = 1
record.housingneeds_f = 1
household_validator.validate_accessibility_requirements(record)
expect(record.errors["accessibility_requirements"])
.to include(match I18n.t("validations.household.housingneeds_a.one_or_two_choices"))
end
it "validates that non-mutually exclusive options can be selected together" do
record.housingneeds_a = 1
record.housingneeds_f = 1
household_validator.validate_accessibility_requirements(record)
expect(record.errors["accessibility_requirements"]).to be_empty
record.housingneeds_a = 0
record.housingneeds_b = 1
record.housingneeds_f = 1
household_validator.validate_accessibility_requirements(record)
expect(record.errors["accessibility_requirements"]).to be_empty
record.housingneeds_b = 0
record.housingneeds_c = 1
record.housingneeds_f = 1
household_validator.validate_accessibility_requirements(record)
expect(record.errors["accessibility_requirements"]).to be_empty
end
end
describe "referral validations" do
context "when homelessness is assessed" do
it "can be internal transfer" do

128
spec/services/configuration/env_configuration_service_spec.rb

@ -0,0 +1,128 @@
require "rails_helper"
RSpec.describe Configuration::EnvConfigurationService do
subject(:config_service) { described_class.new(logger) }
let(:logger) { instance_double(ActiveSupport::LogSubscriber) }
context "when environment configurations are unavailable" do
before { allow(logger).to receive(:warn) }
it "returns the S3 configuration as not present" do
expect(config_service.s3_config_present?).to be(false)
end
it "returns the redis configuration as not present" do
expect(config_service.redis_config_present?).to be(false)
end
it "does not retrieve any S3 bucket configuration" do
expect(config_service.s3_buckets).to be_a(Hash)
expect(config_service.s3_buckets).to be_empty
end
it "does not retrieve any redis configuration" do
expect(config_service.redis_uris).to be_a(Hash)
expect(config_service.redis_uris).to be_empty
end
end
context "when environment configurations are present but invalid" do
let(:env_variable) { "random text" }
before do
allow(ENV).to receive(:[]).with("S3_CONFIG").and_return(env_variable)
allow(ENV).to receive(:[]).with("REDIS_CONFIG").and_return(env_variable)
allow(logger).to receive(:warn)
end
it "logs an error when checking if the S3 config is present" do
expect(logger).to receive(:warn).with("Could not parse S3_CONFIG!")
config_service.s3_config_present?
end
it "logs an error when checking if the Redis config is present" do
expect(logger).to receive(:warn).with("Could not parse REDIS_CONFIG!")
config_service.redis_config_present?
end
end
context "when environment configurations are present with S3 configured" do
let(:s3_config) do
<<~JSON
[
{
"instance_name": "bucket_1",
"credentials": {
"aws_access_key_id": "123",
"aws_secret_access_key": "456",
"aws_region": "eu-west-1",
"bucket_name": "my-bucket"
}
},
{
"instance_name": "bucket_2",
"credentials": {
"aws_access_key_id": "789",
"aws_secret_access_key": "012",
"aws_region": "eu-west-2",
"bucket_name": "my-bucket2"
}
}
]
JSON
end
before do
allow(ENV).to receive(:[]).with("REDIS_CONFIG")
allow(ENV).to receive(:[]).with("S3_CONFIG").and_return(s3_config)
end
it "returns the S3 configuration as present" do
expect(config_service.s3_config_present?).to be(true)
end
it "returns the redis configuration as not present" do
expect(config_service.redis_config_present?).to be(false)
end
it "does retrieve the S3 bucket configurations" do
s3_buckets = config_service.s3_buckets
expect(s3_buckets).not_to be_empty
expect(s3_buckets.count).to be(2)
expect(s3_buckets).to have_key(:bucket_1)
expect(s3_buckets).to have_key(:bucket_2)
end
end
context "when environment configurations are present with redis configured" do
let(:redis_config) do
<<-JSON
[{"instance_name": "redis_1", "credentials": {"uri": "redis_uri" }}]
JSON
end
before do
allow(ENV).to receive(:[]).with("S3_CONFIG")
allow(ENV).to receive(:[]).with("REDIS_CONFIG").and_return(redis_config)
end
it "returns the redis configuration as present" do
expect(config_service.redis_config_present?).to be(true)
end
it "returns the S3 configuration as not present" do
expect(config_service.s3_config_present?).to be(false)
end
it "does retrieve the redis configurations" do
redis_uris = config_service.redis_uris
expect(redis_uris).not_to be_empty
expect(redis_uris.count).to be(1)
expect(redis_uris).to have_key(:redis_1)
expect(redis_uris[:redis_1]).to eq("redis_uri")
end
end
end

120
spec/services/paas_configuration_service_spec.rb → spec/services/configuration/paas_configuration_service_spec.rb

@ -1,6 +1,6 @@
require "rails_helper"
RSpec.describe PaasConfigurationService do
RSpec.describe Configuration::PaasConfigurationService do
subject(:config_service) { described_class.new(logger) }
let(:logger) { instance_double(ActiveSupport::LogSubscriber) }
@ -8,14 +8,38 @@ RSpec.describe PaasConfigurationService do
context "when the paas configuration is unavailable" do
before { allow(logger).to receive(:warn) }
it "returns the configuration as not present" do
expect(config_service.config_present?).to be(false)
it "returns the S3 configuration as not present" do
expect(config_service.s3_config_present?).to be(false)
end
it "returns the redis configuration as not present" do
expect(config_service.redis_config_present?).to be(false)
end
it "does not retrieve any S3 bucket configuration" do
expect(config_service.s3_buckets).to be_a(Hash)
expect(config_service.s3_buckets).to be_empty
end
it "does not retrieve any redis configuration" do
expect(config_service.redis_uris).to be_a(Hash)
expect(config_service.redis_uris).to be_empty
end
end
context "when the paas configuration is present but empty" do
before do
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}")
end
it "returns the S3 configuration as not present" do
expect(config_service.s3_config_present?).to be(false)
end
it "returns the redis configuration as not present" do
expect(config_service.redis_config_present?).to be(false)
end
it "does not retrieve any S3 bucket configuration" do
expect(config_service.s3_buckets).to be_a(Hash)
expect(config_service.s3_buckets).to be_empty
@ -27,7 +51,7 @@ RSpec.describe PaasConfigurationService do
end
end
context "when configuration is present but invalid" do
context "when the paas configuration is present but invalid" do
let(:vcap_services) { "random text" }
before do
@ -35,16 +59,40 @@ RSpec.describe PaasConfigurationService do
allow(logger).to receive(:warn)
end
it "logs an error" do
it "logs an error when checking if the S3 config is present" do
expect(logger).to receive(:warn).with("Could not parse VCAP_SERVICES!")
config_service.s3_config_present?
end
it "logs an error when checking if the Redis config is present" do
expect(logger).to receive(:warn).with("Could not parse VCAP_SERVICES!")
config_service.redis_config_present?
end
end
context "when the paas configuration is present with S3 buckets" do
context "when the paas configuration is present with S3 configured" do
let(:vcap_services) do
<<-JSON
{"aws-s3-bucket": [{"instance_name": "bucket_1"},{"instance_name": "bucket_2"}]}
<<~JSON
{"aws-s3-bucket":
[{
"instance_name": "bucket_1",
"credentials": {
"aws_access_key_id": "123",
"aws_secret_access_key": "456",
"aws_region": "eu-west-1",
"bucket_name": "my-bucket"
}
},
{
"instance_name": "bucket_2",
"credentials": {
"aws_access_key_id": "789",
"aws_secret_access_key": "012",
"aws_region": "eu-west-2",
"bucket_name": "my-bucket2"
}
}]
}
JSON
end
@ -52,14 +100,14 @@ RSpec.describe PaasConfigurationService do
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services)
end
it "returns the configuration as present" do
expect(config_service.config_present?).to be(true)
end
it "returns the S3 configuration as present" do
expect(config_service.s3_config_present?).to be(true)
end
it "returns the redis configuration as not present" do
expect(config_service.redis_config_present?).to be(false)
end
it "does retrieve the S3 bucket configurations" do
s3_buckets = config_service.s3_buckets
@ -70,26 +118,7 @@ RSpec.describe PaasConfigurationService do
end
end
context "when the paas configuration is present without S3 buckets" do
before do
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}")
end
it "returns the configuration as present" do
expect(config_service.config_present?).to be(true)
end
it "returns the S3 configuration as not present" do
expect(config_service.s3_config_present?).to be(false)
end
it "does not retrieve any S3 bucket configuration" do
expect(config_service.s3_buckets).to be_a(Hash)
expect(config_service.s3_buckets).to be_empty
end
end
context "when the paas configuration is present with redis configurations" do
context "when the paas configuration is present with redis configured" do
let(:vcap_services) do
<<-JSON
{"redis": [{"instance_name": "redis_1", "credentials": {"uri": "redis_uri" }}]}
@ -100,14 +129,14 @@ RSpec.describe PaasConfigurationService do
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services)
end
it "returns the configuration as present" do
expect(config_service.config_present?).to be(true)
end
it "returns the redis configuration as present" do
expect(config_service.redis_config_present?).to be(true)
end
it "returns the S3 configuration as not present" do
expect(config_service.s3_config_present?).to be(false)
end
it "does retrieve the redis configurations" do
redis_uris = config_service.redis_uris
@ -117,23 +146,4 @@ RSpec.describe PaasConfigurationService do
expect(redis_uris[:redis_1]).to eq("redis_uri")
end
end
context "when the paas configuration is present without redis configuration" do
before do
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}")
end
it "returns the configuration as present" do
expect(config_service.config_present?).to be(true)
end
it "returns the redis configuration as not present" do
expect(config_service.redis_config_present?).to be(false)
end
it "does not retrieve any redis uris from configuration" do
expect(config_service.redis_uris).to be_a(Hash)
expect(config_service.redis_uris).to be_empty
end
end
end

18
spec/services/csv/case_log_csv_service_spec.rb

@ -105,12 +105,9 @@ RSpec.describe Csv::CaseLogCsvService do
leftreg
reservist
preg_occ
housingneeds_a
housingneeds_b
housingneeds_c
housingneeds_f
housingneeds_g
housingneeds_h
housingneeds
housingneeds_type
housingneeds_other
illness
illness_type_4
illness_type_5
@ -165,6 +162,12 @@ RSpec.describe Csv::CaseLogCsvService do
hbrentshortfall
tshortfall_known
tshortfall
housingneeds_a
housingneeds_b
housingneeds_c
housingneeds_f
housingneeds_g
housingneeds_h
property_owner_organisation
property_manager_organisation
sale_or_letting
@ -187,7 +190,6 @@ RSpec.describe Csv::CaseLogCsvService do
wtcharge
wtshortfall
refused
housingneeds
wchchrg
newprop
old_form_id
@ -198,8 +200,6 @@ RSpec.describe Csv::CaseLogCsvService do
hhtype
new_old
vacdays
housingneeds_type
housingneeds_other
unittype_sh
scheme_code
scheme_service_name

2
spec/services/exports/case_log_export_service_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Exports::CaseLogExportService do
subject(:export_service) { described_class.new(storage_service) }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log.xml", "r:UTF-8") }
let(:local_manifest_file) { File.open("spec/fixtures/exports/manifest.xml", "r:UTF-8") }

2
spec/services/imports/case_logs_field_import_service_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Imports::CaseLogsFieldImportService do
subject(:import_service) { described_class.new(storage_service, logger) }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") }

2
spec/services/imports/case_logs_import_service_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Imports::CaseLogsImportService do
subject(:case_log_service) { described_class.new(storage_service, logger) }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") }

2
spec/services/imports/data_protection_confirmation_import_service_spec.rb

@ -5,7 +5,7 @@ RSpec.describe Imports::DataProtectionConfirmationImportService do
let(:old_org_id) { "7c5bd5fb549c09a2c55d7cb90d7ba84927e64618" }
let(:old_id) { old_org_id }
let(:import_file) { File.open("#{fixture_directory}/#{old_id}.xml") }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
context "when importing data protection confirmations" do

2
spec/services/imports/organisation_import_service_spec.rb

@ -1,7 +1,7 @@
require "rails_helper"
RSpec.describe Imports::OrganisationImportService do
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(Rails::Rack::Logger) }
let(:folder_name) { "organisations" }
let(:filenames) { %w[my_folder/my_file1.xml my_folder/my_file2.xml] }

2
spec/services/imports/organisation_rent_period_import_service_spec.rb

@ -5,7 +5,7 @@ RSpec.describe Imports::OrganisationRentPeriodImportService do
let(:old_org_id) { "44026acc7ed5c29516b26f2a5deb639e5e37966d" }
let(:old_id) { "ebd22326d33e389e9f1bfd546979d2c05f9e68d6" }
let(:import_file) { File.open("#{fixture_directory}/#{old_id}.xml") }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
context "when importing organisation rent periods" do

2
spec/services/imports/scheme_import_service_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Imports::SchemeImportService do
subject(:scheme_service) { described_class.new(storage_service, logger) }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:fixture_directory) { "spec/fixtures/imports/mgmtgroups" }

2
spec/services/imports/scheme_location_import_service_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Imports::SchemeLocationImportService do
subject(:location_service) { described_class.new(storage_service, logger) }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:fixture_directory) { "spec/fixtures/imports/schemes" }

2
spec/services/imports/user_import_service_spec.rb

@ -5,7 +5,7 @@ RSpec.describe Imports::UserImportService do
let(:old_user_id) { "fc7625a02b24ae16162aa63ae7cb33feeec0c373" }
let(:old_org_id) { "7c5bd5fb549c09a2c55d7cb90d7ba84927e64618" }
let(:user_file) { File.open("#{fixture_directory}/#{old_user_id}.xml") }
let(:storage_service) { instance_double(S3StorageService) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:notify_client) { instance_double(Notifications::Client) }
let(:devise_notify_mailer) { DeviseNotifyMailer.new }

2
spec/services/archive_storage_service_spec.rb → spec/services/storage/archive_service_spec.rb

@ -1,6 +1,6 @@
require "rails_helper"
RSpec.describe ArchiveStorageService do
RSpec.describe Storage::ArchiveService do
subject(:archive_service) { described_class.new(archive_content) }
let(:compressed_folder) { "my_directory" }

28
spec/services/s3_storage_service_spec.rb → spec/services/storage/s3_service_spec.rb

@ -1,6 +1,6 @@
require "rails_helper"
RSpec.describe S3StorageService do
RSpec.describe Storage::S3Service do
let(:instance_name) { "instance_1" }
let(:bucket_name) { "bucket_1" }
let(:vcap_services) do
@ -20,18 +20,24 @@ RSpec.describe S3StorageService do
end
context "when we create a storage service with no PaaS Configuration present" do
subject(:storage_service) { described_class.new(PaasConfigurationService.new, "random_instance") }
subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, "random_instance") }
it "raises an exception" do
expect { storage_service }.to raise_error(RuntimeError, /No PaaS configuration present/)
expect { storage_service }.to raise_error(RuntimeError, "No S3 bucket is present in the PaaS configuration")
end
end
context "when we create a storage service with an unknown instance name" do
subject(:storage_service) { described_class.new(PaasConfigurationService.new, "random_instance") }
context "when we create a storage service and the S3 instance name is not found in the PaaS configuration" do
subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, "random_instance") }
let(:vcap_services) do
<<-JSON
{"aws-s3-bucket": []}
JSON
end
before do
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}")
allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services)
end
it "raises an exception" do
@ -40,7 +46,7 @@ RSpec.describe S3StorageService do
end
context "when we create a storage service with a valid instance name" do
subject(:storage_service) { described_class.new(PaasConfigurationService.new, instance_name) }
subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, instance_name) }
before do
allow(ENV).to receive(:[])
@ -48,11 +54,11 @@ RSpec.describe S3StorageService do
end
it "creates a Storage Configuration" do
expect(storage_service.configuration).to be_an(StorageConfiguration)
expect(storage_service.configuration).to be_an(Storage::StorageConfiguration)
end
it "sets the expected parameters in the configuration" do
expected_configuration = StorageConfiguration.new(
expected_configuration = Storage::StorageConfiguration.new(
{
aws_access_key_id: "key_id",
aws_region: "eu-west-2",
@ -65,7 +71,7 @@ RSpec.describe S3StorageService do
end
context "when we create a storage service and write a stubbed object" do
subject(:storage_service) { described_class.new(PaasConfigurationService.new, instance_name) }
subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, instance_name) }
let(:filename) { "my_file" }
let(:content) { "content" }
@ -100,7 +106,7 @@ RSpec.describe S3StorageService do
end
context "when we create a storage service" do
subject(:storage_service) { described_class.new(PaasConfigurationService.new, instance_name) }
subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, instance_name) }
let(:s3_client_stub) { Aws::S3::Client.new(stub_responses: true) }
Loading…
Cancel
Save