From 3e0333c7547ad0c11bbe52ae8a4de4dba64ae10d Mon Sep 17 00:00:00 2001 From: Alex Evanczuk Date: Fri, 1 Jul 2022 14:42:43 -0400 Subject: [PATCH] Export package protections rspec support (#13) * move package protections rspec support into exported part of code * fix ERB loading when getting rubocop * bump version * fix thing * fix use of select --- Gemfile.lock | 2 +- .../rspec}/application_fixture_helper.rb | 0 lib/package_protections/rspec/matchers.rb | 99 ++++++++++++++++ lib/package_protections/rspec/support.rb | 17 +++ package_protections.gemspec | 2 +- spec/package_protections_spec.rb | 106 ------------------ spec/spec_helper.rb | 3 +- 7 files changed, 119 insertions(+), 110 deletions(-) rename {spec/support => lib/package_protections/rspec}/application_fixture_helper.rb (100%) create mode 100644 lib/package_protections/rspec/matchers.rb create mode 100644 lib/package_protections/rspec/support.rb diff --git a/Gemfile.lock b/Gemfile.lock index 7c5d0b9..40eda67 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - package_protections (1.1.1) + package_protections (1.2.0) activesupport parse_packwerk rubocop diff --git a/spec/support/application_fixture_helper.rb b/lib/package_protections/rspec/application_fixture_helper.rb similarity index 100% rename from spec/support/application_fixture_helper.rb rename to lib/package_protections/rspec/application_fixture_helper.rb diff --git a/lib/package_protections/rspec/matchers.rb b/lib/package_protections/rspec/matchers.rb new file mode 100644 index 0000000..f7b2dff --- /dev/null +++ b/lib/package_protections/rspec/matchers.rb @@ -0,0 +1,99 @@ +def offense( + package_name, message, file, violation_type +) + + package = ParsePackwerk.all.find { |p| p.name == package_name } + PackageProtections::Offense.new( + package: package, + message: message, + file: file, + violation_type: violation_type + ) +end + +def serialize_offenses_diff(actual_offenses, expected_offense) + color_by_match = ->(actual, expected) { actual == expected ? Rainbow(actual).green : "#{Rainbow(actual).red} (expected: #{expected})" } + + actual_offenses.map do |offense| + # We color each field red or green depending on if the attributes match our expected + <<~SERIALIZED_OFFENSE + File: #{color_by_match.call(offense.file, expected_offense.file)} + Message: #{color_by_match.call(offense.message, expected_offense.message)} + Violation Type: #{color_by_match.call(offense.violation_type, expected_offense.violation_type)} + Package: #{color_by_match.call(offense.package.name, expected_offense.package.name)} + SERIALIZED_OFFENSE + end +end + +def serialize_offenses(actual_offenses) + actual_offenses.map do |offense| + <<~SERIALIZED_OFFENSE + File: #{offense.file} + Message: #{offense.message} + Violation Type: #{offense.violation_type} + Package: #{offense.package.name} + SERIALIZED_OFFENSE + end +end + +RSpec::Matchers.define(:include_offense) do |expected_offense| + match do |actual_offenses| + @actual_offenses = actual_offenses + @expected_offense = expected_offense + if ENV['DEBUG'] + PackageProtections.print_offenses(actual_offenses) + end + @matching_offense = actual_offenses.find do |actual_offense| + actual_offense.file == expected_offense.file && + actual_offense.message == expected_offense.message && + actual_offense.violation_type == expected_offense.violation_type && + actual_offense.package.name == expected_offense.package.name + end + !@matching_offense.nil? + end + + description do + "to have an offense with type `#{expected_offense.type}` tied to package `#{expected_offense.package_name}` with message `#{expected_offense.message}` and instances `#{expected_offense.submessages.join(', ')}`" + end + + failure_message do + <<~MSG + Could not find offense! Here are the found offenses: + #{serialize_offenses_diff(@actual_offenses, expected_offense).join("\n\n")} + MSG + end +end + +RSpec::Matchers.define(:contain_exactly) do |number_of_offenses| + match do |actual_offenses| + @actual_offenses = actual_offenses || [] + @offenses = [] + @actual_offenses.each do |offense| + @offenses << offense + end + @offenses.size == number_of_offenses + end + + chain :offense, :number_of_offenses + chain :offenses, :number_of_offenses + + description do + 'to contain offenses' + end + + failure_message_when_negated do + "Found the following offenses:\n#{@offenses.map { |r| "#{r.package_name}: #{r.message}" }}" + end + + failure_message do + if @offenses.empty? + "Found #{@offenses.size} instead." + else + <<~MSG + Found #{@offenses.size} instead. + + #{serialize_offenses(@offenses).join("\n")} + MSG + end + end +end diff --git a/lib/package_protections/rspec/support.rb b/lib/package_protections/rspec/support.rb new file mode 100644 index 0000000..a8d9c84 --- /dev/null +++ b/lib/package_protections/rspec/support.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Require this file to load code that supports testing using RSpec. + +require_relative 'application_fixture_helper' +require_relative 'matchers' + +def get_resulting_rubocop + write_file('config/default.yml', <<~YML.strip) + <%= PackageProtections.rubocop_yml %> + YML + YAML.safe_load(ERB.new(File.read('config/default.yml')).result(binding)) +end + +RSpec.configure do |config| + config.include ApplicationFixtureHelper +end diff --git a/package_protections.gemspec b/package_protections.gemspec index 6f4955b..32c708a 100644 --- a/package_protections.gemspec +++ b/package_protections.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = 'package_protections' - spec.version = '1.1.1' + spec.version = '1.2.0' spec.authors = ['Gusto Engineers'] spec.email = ['stephan.hagemann@gusto.com'] spec.summary = 'Package protections for Rails apps' diff --git a/spec/package_protections_spec.rb b/spec/package_protections_spec.rb index 954fc39..fc2bdac 100644 --- a/spec/package_protections_spec.rb +++ b/spec/package_protections_spec.rb @@ -13,93 +13,6 @@ allow(Bundler).to receive(:root).and_return(Pathname.new('.')) end - RSpec::Matchers.define(:include_offense) do |expected_offense| - match do |actual_offenses| - @actual_offenses = actual_offenses - @expected_offense = expected_offense - if ENV['DEBUG'] - PackageProtections.print_offenses(actual_offenses) - end - @matching_offense = actual_offenses.find do |actual_offense| - actual_offense.file == expected_offense.file && - actual_offense.message == expected_offense.message && - actual_offense.violation_type == expected_offense.violation_type && - actual_offense.package.name == expected_offense.package.name - end - !@matching_offense.nil? - end - - description do - "to have an offense with type `#{expected_offense.type}` tied to package `#{expected_offense.package_name}` with message `#{expected_offense.message}` and instances `#{expected_offense.submessages.join(', ')}`" - end - - failure_message do - <<~MSG - Could not find offense! Here are the found offenses: - #{serialize_offenses_diff(@actual_offenses, expected_offense).join("\n\n")} - MSG - end - end - - RSpec::Matchers.define(:contain_exactly) do |number_of_offenses| - match do |actual_offenses| - @actual_offenses = actual_offenses || [] - @offenses = [] - @actual_offenses.select do |offense| - @offenses << offense - end - @offenses.size == number_of_offenses - end - - chain :offense, :number_of_offenses - chain :offenses, :number_of_offenses - - description do - 'to contain offenses' - end - - failure_message_when_negated do - "Found the following offenses:\n#{@offenses.map { |r| "#{r.package_name}: #{r.message}" }}" - end - - failure_message do - if @offenses.empty? - "Found #{@offenses.size} instead." - else - <<~MSG - Found #{@offenses.size} instead. - - #{serialize_offenses(@offenses).join("\n")} - MSG - end - end - end - - def serialize_offenses_diff(actual_offenses, expected_offense) - color_by_match = ->(actual, expected) { actual == expected ? Rainbow(actual).green : "#{Rainbow(actual).red} (expected: #{expected})" } - - actual_offenses.map do |offense| - # We color each field red or green depending on if the attributes match our expected - <<~SERIALIZED_OFFENSE - File: #{color_by_match.call(offense.file, expected_offense.file)} - Message: #{color_by_match.call(offense.message, expected_offense.message)} - Violation Type: #{color_by_match.call(offense.violation_type, expected_offense.violation_type)} - Package: #{color_by_match.call(offense.package.name, expected_offense.package.name)} - SERIALIZED_OFFENSE - end - end - - def serialize_offenses(actual_offenses) - actual_offenses.map do |offense| - <<~SERIALIZED_OFFENSE - File: #{offense.file} - Message: #{offense.message} - Violation Type: #{offense.violation_type} - Package: #{offense.package.name} - SERIALIZED_OFFENSE - end - end - def get_packages ParsePackwerk.all end @@ -112,25 +25,6 @@ def get_new_violations end end - def get_resulting_rubocop - write_file('config/default.yml', <<~YML.strip) - <%= PackageProtections.rubocop_yml %> - YML - YAML.safe_load(ERB.new(YAML.load_file('config/default.yml')).result(binding)) - end - - def offense( - package_name, message, file, violation_type - ) - package = get_packages.find { |p| p.name == package_name } - PackageProtections::Offense.new( - package: package, - message: message, - file: file, - violation_type: violation_type - ) - end - describe 'get_offenses' do describe 'general behavior' do it 'raises on incorrect protection configuration keys' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1be5855..1976cbb 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,8 +1,7 @@ require 'pry' require 'package_protections' require 'rubocop/rspec/support' - -require_relative 'support/application_fixture_helper' +require 'package_protections/rspec/support' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure