From 8338b62e3216bb60748a29a164b4f7df01c47942 Mon Sep 17 00:00:00 2001 From: Vanessa Fotso Date: Wed, 14 Dec 2022 23:21:43 -0500 Subject: [PATCH] core logic test for export strategies Signed-off-by: Vanessa Fotso --- app/helpers/export_helper.rb | 3 +- spec/factories/components.rb | 24 ++++ spec/factories/projects.rb | 7 + .../factories/security_requirements_guides.rb | 13 ++ spec/factories/sequences.rb | 3 + spec/helpers/export_helper_spec.rb | 126 ++++++++++++++++++ 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 spec/factories/components.rb create mode 100644 spec/factories/projects.rb create mode 100644 spec/factories/security_requirements_guides.rb create mode 100644 spec/helpers/export_helper_spec.rb diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb index 5b425c44..bbbdfa09 100644 --- a/app/helpers/export_helper.rb +++ b/app/helpers/export_helper.rb @@ -15,7 +15,8 @@ def export_excel(project) srg_rule: %i[disa_rule_descriptions rule_descriptions checks] }] ).each do |component| - worksheet = workbook.add_worksheet("#{component[:name]} V#{component[:version]}R#{component[:release]}") + worksheet_name = "#{component[:name]}-V#{component[:version]}R#{component[:release]}-#{component[:id]}" + worksheet = workbook.add_worksheet(worksheet_name) worksheet.auto_width = true worksheet.append_row(ExportConstants::DISA_EXPORT_HEADERS) last_row_num = 0 diff --git a/spec/factories/components.rb b/spec/factories/components.rb new file mode 100644 index 00000000..eeea9741 --- /dev/null +++ b/spec/factories/components.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :component do + project { create(:project) } + based_on { create(:security_requirements_guide) } + + prefix { 'ABCD-00' } + name { FFaker::Name.name } + admin_name { generate(:name) } + admin_email { generate(:email) } + advanced_fields { false } + version { generate(:version) } + release { generate(:release) } + title { 'Fake title' } + description { 'Fake description' } + + trait :released_component do + released { true } + end + + factory :released_component, traits: [:released_component] + end +end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb new file mode 100644 index 00000000..db83c190 --- /dev/null +++ b/spec/factories/projects.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :project do + name { generate(:name) } + end +end diff --git a/spec/factories/security_requirements_guides.rb b/spec/factories/security_requirements_guides.rb new file mode 100644 index 00000000..d141f7a9 --- /dev/null +++ b/spec/factories/security_requirements_guides.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +XML_FILE = File.read('./spec/fixtures/files/U_Web_Server_V2R3_Manual-xccdf.xml') + +FactoryBot.define do + factory :security_requirements_guide do + srg_id { FFaker::Name.name.underscore } + title { FFaker::Name.name } + version { "V#{rand(0..9)}R#{rand(0..9)}" } + xml { XML_FILE } + release_date { Time.zone.today } + end +end diff --git a/spec/factories/sequences.rb b/spec/factories/sequences.rb index e469f9a5..feea5974 100644 --- a/spec/factories/sequences.rb +++ b/spec/factories/sequences.rb @@ -4,4 +4,7 @@ sequence(:name) { |n| "John Doe#{n}" } sequence(:email) { |n| "user#{n}@example.org" } sequence(:password) { |n| "12345678#{n}" } + sequence(:version) { |n| n } + sequence(:release) { |n| n } + sequence(:rule_id) { |n| n.to_s.rjust(6, '0') } end diff --git a/spec/helpers/export_helper_spec.rb b/spec/helpers/export_helper_spec.rb new file mode 100644 index 00000000..74bfee02 --- /dev/null +++ b/spec/helpers/export_helper_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ExportHelper, type: :helper do + include ExportHelper + + before(:all) do + @component = FactoryBot.create(:component) + @released_component = FactoryBot.create(:released_component) + @project = @component.project + @project_with_realeased_comp = @released_component.project + end + + describe '#export_excel' do + before(:all) do + @workbook = export_excel(@project) + @workbook_release = export_excel(@project_with_realeased_comp) + + [@workbook, @workbook_release].each_with_index do |item, index| + file_name = '' + if index == 0 + file_name = "./#{@project.name}.xlsx" + File.binwrite(file_name, item.read_string) + @xlsx = Roo::Spreadsheet.open(file_name) + else + file_name = "./#{@project_with_realeased_comp.name}.xlsx" + File.binwrite(file_name, item.read_string) + @xlsx_release = Roo::Spreadsheet.open(file_name) + end + File.delete(file_name) + end + end + + context 'in all scenarios' do + it 'creates an excel format of a given project' do + expect(@workbook).to be_present + expect(@workbook.filename).to end_with 'xlsx' + end + end + + context 'when project has released component' do + it 'creates an excel file with the # of sheets == # of released components' do + expect(@xlsx_release.sheets.size).to eq @project_with_realeased_comp.components.where(released: true).size + end + + it 'creates an excel file with correct format for worksheet name' do + sheet_name = "#{@released_component.name}-V#{@released_component.version}" + sheet_name += "R#{@released_component.release}-#{@released_component.id}" + expect(@xlsx_release.sheets).to include(sheet_name) + end + end + + context 'when project has no released component' do + it 'creates an empty spreadsheet' do + expect(@xlsx.sheets.size).to eq 1 + expect(@xlsx.sheets.first).to eq 'Sheet1' + end + end + end + + describe '#export_xccdf' do + before(:all) do + @file_name = "./#{@project.name}.zip" + File.binwrite(@file_name, export_xccdf(@project).string) + @zip = Zip::File.open(@file_name) + end + + after(:all) do + File.delete(@file_name) + end + + it 'creates a zip file containing all components of a project in xccdf format' do + expect(@zip.size).to eq @project.components.size + # check the content of each file is valid xml + errors = [] + @zip.each do |xml| + xml.get_input_stream { |io| errors << Nokogiri::XML(io.read).errors } + end + expect(errors).to all(be_empty) + end + + it 'creates a zip file containing xccdf files with correct name format' do + expected_names = @project.components.map do |comp| + version = comp.version ? "V#{comp.version}" : '' + release = comp.release ? "R#{comp.release}" : '' + title = (comp.title || "#{comp.name} STIG Readiness Guide") + "U_#{title.tr(' ', '_')}_#{version}#{release}-xccdf.xml" + end + expect(@zip.map(&:name).sort).to eq expected_names.sort + end + end + + describe '#export_inspec_project' do + before(:all) do + @file_name = "./#{@project.name}.zip" + File.binwrite(@file_name, export_inspec_project(@project).string) + @zip = Zip::File.open(@file_name) + end + + after(:all) do + File.delete(@file_name) + end + + it 'creates a zip file containing all components of a project in YAML format' do + expect(@zip.size).to eq @project.components.size + # ensure files are valid yaml + @zip.each do |yml| + content = nil + yml.get_input_stream { |io| content = io.read } + expect { YAML.parse(content) }.to_not raise_error + end + end + + it 'creates a zip file containing yaml files with correct name format' do + expected_names = @project.components.map do |comp| + version = comp.version ? "V#{comp.version}" : '' + release = comp.release ? "R#{comp.release}" : '' + + "#{comp.name.tr(' ', '-')}-#{version}#{release}-stig-baseline/inspec.yml" + end + + expect(@zip.map(&:name).sort).to eq expected_names.sort + end + end +end