Make some specs pass

This commit is contained in:
2025-10-04 11:57:16 -05:00
parent c2fe8675bb
commit 177281adc0
18 changed files with 171 additions and 157 deletions
+2 -1
View File
@@ -11,7 +11,7 @@ end
gemspec gemspec
gem "rails", "~> 5.1" gem "rails", "~> 8.0"
group :development, :test do group :development, :test do
gem 'bootsnap', require: false gem 'bootsnap', require: false
@@ -28,6 +28,7 @@ group :development, :test do
gem 'puma' gem 'puma'
gem 'paperclip', '~> 5.3' gem 'paperclip', '~> 5.3'
gem 'dunlop-ember', gitlab: 'benja-2/dunlop-ember', branch: 'master' gem 'dunlop-ember', gitlab: 'benja-2/dunlop-ember', branch: 'master'
gem 'record_collection' #, github: 'bterkuile/record_collection', branch: 'master'
#gem 'carrierwave' #gem 'carrierwave'
#gem 'fog-aws' #gem 'fog-aws'
+1 -1
View File
@@ -6,7 +6,7 @@ module Dunlop::Loggable
end end
def with_nested_logger_and_catch_failed(scope=nil, options={}) def with_nested_logger_and_catch_failed(scope=nil, options={})
scope ||= caller[0][/`.*'/][1..-2] scope ||= caller[0][/'.*'/][1..-2]
options[:exception_notifier] = true unless options.has_key?(:exception_notifier) options[:exception_notifier] = true unless options.has_key?(:exception_notifier)
backtrace = nil backtrace = nil
::Dunlop::NestedLogger.scope('empty sandbox', benchmark: false) do ::Dunlop::NestedLogger.scope('empty sandbox', benchmark: false) do
+94 -92
View File
@@ -1,124 +1,126 @@
module Dunlop::OverdueHandling module Dunlop
@registry = {} module OverdueHandling
@final_states = %w[overdue completed rejected] @registry = {}
@final_states = %w[overdue completed rejected]
def self.registry def self.registry
@registry @registry
end end
def self.final_states def self.final_states
@final_states @final_states
end end
def self.final_states=(states) def self.final_states=(states)
@final_states = states @final_states = states
end end
def self.define(&block) def self.define(&block)
@registry = {} # empty the registry @registry = {} # empty the registry
definition_proxy = DefinitionProxy.new definition_proxy = DefinitionProxy.new
definition_proxy.instance_eval(&block) definition_proxy.instance_eval(&block)
end end
def self.handle_overdue! def self.handle_overdue!
registry.each do |workflow_step_name, config| registry.each do |workflow_step_name, config|
base_scope = WorkflowInstance.all #where.not(state: final_states) base_scope = WorkflowInstance.all #where.not(state: final_states)
base_scope = base_scope.where(sti_type: config.scenarios.map{|s| "WorkflowInstance::#{s.to_s.classify}"}) if config.scenarios.any? base_scope = base_scope.where(sti_type: config.scenarios.map{|s| "WorkflowInstance::#{s.to_s.classify}"}) if config.scenarios.any?
base_scope = base_scope.joins(workflow_step_name).where.not("#{workflow_step_name.to_s.pluralize}.state" => final_states) #.includes(workflow_step_name) base_scope = base_scope.joins(workflow_step_name).where.not("#{workflow_step_name.to_s.pluralize}.state" => final_states) #.includes(workflow_step_name)
if config.from.is_nested? if config.from.is_nested?
base_scope = base_scope.joins(config.from.key) if config.from.key != workflow_step_name base_scope = base_scope.joins(config.from.key) if config.from.key != workflow_step_name
end end
base_scope = base_scope.where("#{config.date_target_class.table_name}.#{config.date_target_column} <= ?", Date.current - config.time) base_scope = base_scope.where("#{config.date_target_class.table_name}.#{config.date_target_column} <= ?", Date.current - config.time)
base_scope.find_each do |workflow_instance| base_scope.find_each do |workflow_instance|
next unless workflow_step = workflow_instance.public_send(workflow_step_name) next unless workflow_step = workflow_instance.public_send(workflow_step_name)
workflow_step.is_overdue! workflow_step.is_overdue!
end
end end
end end
end
class DefinitionProxy class DefinitionProxy
def when_workflow_step(workflow_step, options = {}, &block) def when_workflow_step(workflow_step, options = {}, &block)
raise "Workflow step #{workflow_step} does not exist" unless WorkflowInstance.possible_workflow_step_names.include?(workflow_step) raise "Workflow step #{workflow_step} does not exist" unless WorkflowInstance.possible_workflow_step_names.include?(workflow_step)
workflow_step_proxy = WorkflowStepProxy.new(workflow_step, options) workflow_step_proxy = WorkflowStepProxy.new(workflow_step, options)
workflow_step_proxy.instance_eval(&block) if block workflow_step_proxy.instance_eval(&block) if block
workflow_step_proxy.register_callbacks! workflow_step_proxy.register_callbacks!
::Dunlop::OverdueHandling.registry[workflow_step] = workflow_step_proxy ::Dunlop::OverdueHandling.registry[workflow_step] = workflow_step_proxy
end
def the_final_states_are(states)
::Dunlop::OverdueHandling.final_states = states
end
end end
def the_final_states_are(states) class WorkflowStepProxy
::Dunlop::OverdueHandling.final_states = states attr_reader :workflow_step, :options, :overdue_target_class
end def initialize(workflow_step, options)
end @workflow_step, @options = workflow_step, options
@overdue_target_class = workflow_step.to_s.classify.constantize
end
class WorkflowStepProxy def date_target_class
attr_reader :workflow_step, :options, :overdue_target_class @date_target_class ||= from.is_nested? ? from.key.to_s.classify.constantize : WorkflowInstance
def initialize(workflow_step, options) end
@workflow_step, @options = workflow_step, options
@overdue_target_class = workflow_step.to_s.classify.constantize
end
def date_target_class def date_target_column
@date_target_class ||= from.is_nested? ? from.key.to_s.classify.constantize : WorkflowInstance @date_target_column ||= from.field
end end
def date_target_column def scenarios
@date_target_column ||= from.field options[:scenarios] || []
end end
def scenarios def from
options[:scenarios] || [] WorkflowStepBaseDate.new(workflow_step, options[:from])
end end
def from def time
WorkflowStepBaseDate.new(workflow_step, options[:from]) options[:is]
end end
def time #TODO: find a simple way to do this!!!
options[:is] def register_callbacks!
end date_target_classes = [date_target_class] #TODO: only implement on specific scenarios if given as argument
date_column = date_target_column
#TODO: find a simple way to do this!!! workflow_step_name = workflow_step # make local scope for after_save definition
def register_callbacks! overdue_time = time
date_target_classes = [date_target_class] #TODO: only implement on specific scenarios if given as argument date_target_classes.each do |target_class|
date_column = date_target_column target_class.after_save do |record|
workflow_step_name = workflow_step # make local scope for after_save definition if saved_changes[date_column]
overdue_time = time target_record = record.workflow_instance.public_send(workflow_step_name)
date_target_classes.each do |target_class| if date = record.public_send(date_column)
target_class.after_save do |record| if date <= Date.current - overdue_time
if saved_changes[date_column] target_record.is_overdue! if target_record.pending? or target_record.processing?
target_record = record.workflow_instance.public_send(workflow_step_name) else
if date = record.public_send(date_column) target_record.process! if target_record.overdue?
if date <= Date.current - overdue_time end
target_record.is_overdue! if target_record.pending? or target_record.processing?
else else
target_record.process! if target_record.overdue? target_record.process! if target_record.overdue?
end end
else
target_record.process! if target_record.overdue?
end end
end end
end end
end end
end end
end
class WorkflowStepBaseDate class WorkflowStepBaseDate
attr_reader :workflow_step, :config attr_reader :workflow_step, :config
def initialize(workflow_step, config) def initialize(workflow_step, config)
@workflow_step, @config = workflow_step, config @workflow_step, @config = workflow_step, config
end end
def is_nested? def is_nested?
config.is_a?(Hash) config.is_a?(Hash)
end end
def key def key
is_nested? ? config.keys.first : config is_nested? ? config.keys.first : config
end end
def field def field
is_nested? ? config.values.first : config is_nested? ? config.values.first : config
end
end end
end end
end end
+1
View File
@@ -3,6 +3,7 @@
ENGINE_ROOT = File.expand_path('../..', __FILE__) ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/dunlop/engine', __FILE__) ENGINE_PATH = File.expand_path('../../lib/dunlop/engine', __FILE__)
APP_PATH = File.expand_path("../spec/dummy/config/application", __dir__)
# Set up gems listed in the Gemfile. # Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+2 -1
View File
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
s.add_dependency "rails", ">= 4.2.6" s.add_dependency "rails", ">= 4.2.6"
s.add_dependency 'slim-rails' s.add_dependency 'slim-rails'
#s.add_dependency 'record_collection', '>= 0.10.4' #s.add_dependency 'record_collection', '>= 0.10.4' # Only in Gemfile to make not requried
s.add_dependency 'request_store' s.add_dependency 'request_store'
s.add_dependency 'ransack' s.add_dependency 'ransack'
s.add_dependency 'responders' s.add_dependency 'responders'
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
s.add_dependency 'facets' s.add_dependency 'facets'
s.add_dependency 'memoist' s.add_dependency 'memoist'
s.add_dependency 'cancancan' s.add_dependency 'cancancan'
s.add_dependency 'csv'
# assets # assets
#s.add_dependency 'momentjs-rails' #s.add_dependency 'momentjs-rails'
@@ -36,8 +36,8 @@ class Dunlop::Install::BaseGenerator < Rails::Generators::Base
config.application_name = "#{Rails.application.class.name.deconstantize}" config.application_name = "#{Rails.application.class.name.deconstantize}"
config.git_version = Rails.env config.git_version = Rails.env
config.git_version = File.read('REVISION').strip if File.exists?('REVISION') config.git_version = File.read('REVISION').strip if File.exist?('REVISION')
config.git_version = File.read('OFFLINE_REVISION').strip if File.exists?('OFFLINE_REVISION') config.git_version = File.read('OFFLINE_REVISION').strip if File.exist?('OFFLINE_REVISION')
RUBY RUBY
end end
+3
View File
@@ -0,0 +1,3 @@
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
@@ -1,8 +1,8 @@
class OwnerInitialization < ApplicationRecord class OwnerInitialization < ApplicationRecord
include WorkflowStepModel include WorkflowStepModel
serialize :window_from, DayTimeMinutes serialize :window_from, coder: DayTimeMinutes
serialize :window_to, DayTimeMinutes serialize :window_to, coder: DayTimeMinutes
activate_dunlop! activate_dunlop!
end end
+2 -2
View File
@@ -22,8 +22,8 @@ module Dummy
config.application_name = 'Dunlop' config.application_name = 'Dunlop'
config.git_version = nil config.git_version = nil
config.git_version = File.read('REVISION').strip if File.exists?('REVISION') config.git_version = File.read('REVISION').strip if File.exist?('REVISION')
config.git_version = File.read('OFFLINE_REVISION').strip if File.exists?('OFFLINE_REVISION') config.git_version = File.read('OFFLINE_REVISION').strip if File.exist?('OFFLINE_REVISION')
config.file_storage_path = Rails.root.join('files') # source file storage config.file_storage_path = Rails.root.join('files') # source file storage
config.working_path = '/tmp' # source file processing directory config.working_path = '/tmp' # source file processing directory
@@ -1,3 +1,5 @@
Dunlop::OverdueHandling.define do Rails.application.config.after_initialize do
when_workflow_step :contractor_initialization, is: 2.days, from: {owner_initialization: :plan_date} Dunlop::OverdueHandling.define do
when_workflow_step :contractor_initialization, is: 2.days, from: {owner_initialization: :plan_date}
end
end end
@@ -1,3 +1,5 @@
Dunlop::Workflow.configure do |config| Rails.application.config.after_initialize do
config.max_number_of_records_in_display_badge = 72 Dunlop::Workflow.configure do |config|
config.max_number_of_records_in_display_badge = 72
end
end end
@@ -1,28 +1,30 @@
Dunlop::WorkflowStepsInBatchFinished.define do Rails.application.config.after_initialize do
the_final_states_are %w[rejected completed] Dunlop::WorkflowStepsInBatchFinished.define do
the_final_states_are %w[rejected completed]
on_finishing_of :owner_initialization do on_finishing_of :owner_initialization do
description "Send notification mail to Owner" do |workflow_instance_batch| description "Send notification mail to Owner" do |workflow_instance_batch|
OwnerMailer.owner_initialization_finished(workflow_instance_batch, self).deliver_later OwnerMailer.owner_initialization_finished(workflow_instance_batch, self).deliver_later
end
end end
#on_finishing_of :contractor_service_window1_execution do
# description <<-DESCRIPTION
# Check ${attributes.owner_service_window2_preparation.migration_file_for_bvt_ready}
# for ${models.owner_service_window2_preparation} workflow steps in the batch
# DESCRIPTION
# action do |workflow_instance_batch|
# workflow_steps_in_batch_scope(:owner_service_window2_preparation).update_all migration_file_for_bvt_ready: true
# end
# description "Send an email to Core Delivery informing them of batch completion" do |workflow_instance_batch|
# KpnCoreDeliveryMailer.contractor_service_window1_handled_for_batch(workflow_instance_batch.id).deliver_later
# end
# description "Send an email to Schuuring informing them of batch completion" do |workflow_instance_batch|
# SchuuringMailer.workflow_instance_batch_workflow_step_finished(self.class.name, workflow_instance_batch.id).deliver_later
# end
#end
end end
#on_finishing_of :contractor_service_window1_execution do
# description <<-DESCRIPTION
# Check ${attributes.owner_service_window2_preparation.migration_file_for_bvt_ready}
# for ${models.owner_service_window2_preparation} workflow steps in the batch
# DESCRIPTION
# action do |workflow_instance_batch|
# workflow_steps_in_batch_scope(:owner_service_window2_preparation).update_all migration_file_for_bvt_ready: true
# end
# description "Send an email to Core Delivery informing them of batch completion" do |workflow_instance_batch|
# KpnCoreDeliveryMailer.contractor_service_window1_handled_for_batch(workflow_instance_batch.id).deliver_later
# end
# description "Send an email to Schuuring informing them of batch completion" do |workflow_instance_batch|
# SchuuringMailer.workflow_instance_batch_workflow_step_finished(self.class.name, workflow_instance_batch.id).deliver_later
# end
#end
end end
+1 -1
View File
@@ -3,7 +3,7 @@ FactoryBot.define do
original_file { Tempfile.new("target_file_factory") } original_file { Tempfile.new("target_file_factory") }
trait :failed do trait :failed do
after(:build) { |record| record.log_entries.build(body: 'ERROR - some reason to fail') } after(:build) { |record| record.log_entries.build(body: 'ERROR - some reason to fail') }
state 'failed' state { 'failed' }
end end
end end
+5 -5
View File
@@ -6,14 +6,14 @@ FactoryBot.define do
factory :user do factory :user do
email email
password 'password' password { 'password' }
role_names %w[read-class-WorkflowInstance] role_names { %w[read-class-WorkflowInstance] }
end end
factory :admin, class: User do factory :admin, class: User do
email 'admin@example.com' email { 'admin@example.com' }
password 'password' password { 'password' }
admin true admin { true }
end end
end end
+8 -8
View File
@@ -1,29 +1,29 @@
FactoryBot.define do FactoryBot.define do
factory :workflow_instance do factory :workflow_instance do
after(:build){|instance| instance.setup_workflow_steps } after(:build){|instance| instance.setup_workflow_steps }
state "unplanned" # default for Vula state { "unplanned" } # default for Vula
trait :uncategorized do trait :uncategorized do
state 'uncategorized' state { 'uncategorized' }
end end
trait :unplanned do trait :unplanned do
state 'unplanned' state { 'unplanned' }
end end
trait :planned do trait :planned do
state 'planned' state { 'planned' }
end end
trait :active do trait :active do
state 'active' state { 'active' }
after :build do |instance| after :build do |instance|
instance.workflow_steps.first.state = 'processing' instance.workflow_steps.first.state = 'processing'
end end
end end
trait :overdue do trait :overdue do
state 'overdue' state { 'overdue' }
after :build do |instance| after :build do |instance|
instance.owner_initialization.plan_date = 1.year.ago instance.owner_initialization.plan_date = 1.year.ago
instance.contractor_initialization.state = 'overdue' instance.contractor_initialization.state = 'overdue'
@@ -31,14 +31,14 @@ FactoryBot.define do
end end
trait :all_completed do trait :all_completed do
state 'all_completed' state { 'all_completed' }
after :build do |instance| after :build do |instance|
instance.workflow_steps.each{|workflow_step| workflow_step.state = 'completed' } instance.workflow_steps.each{|workflow_step| workflow_step.state = 'completed' }
end end
end end
trait :any_rejected do trait :any_rejected do
state 'any_rejected' state { 'any_rejected' }
after :build do |instance| after :build do |instance|
instance.workflow_steps.first.state = 'rejected' instance.workflow_steps.first.state = 'rejected'
end end
@@ -1,6 +1,6 @@
require 'rails_helper' require 'rails_helper'
describe Dunlop::ExecutionBatch do describe ::ExecutionBatch do
let(:time) { '1981-03-09T13:33:04Z'.to_time } let(:time) { '1981-03-09T13:33:04Z'.to_time }
let(:model) { ExecutionBatch::MyBatch } let(:model) { ExecutionBatch::MyBatch }
before { Timecop.freeze time } before { Timecop.freeze time }
+1 -1
View File
@@ -43,7 +43,7 @@ RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 1
RSpec.configure do |config| RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = Dunlop::Engine.root.join("spec/fixtures") config.fixture_paths = [Dunlop::Engine.root.join("spec/fixtures")]
config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] } config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
+12 -12
View File
@@ -20,10 +20,10 @@ RSpec.describe Dunlop::FileZip do
context "mime-type: application/zip" do context "mime-type: application/zip" do
it "unzips the file to the provided filename" do it "unzips the file to the provided filename" do
expect(File.exists?(destination_filename)).to be_falsey expect(File.exist?(destination_filename)).to be_falsey
subject.unzip(zipped_filename, destination_filename) subject.unzip(zipped_filename, destination_filename)
expect(File.exists?(destination_filename)).to be_truthy expect(File.exist?(destination_filename)).to be_truthy
expect(File.exists?(zipped_filename)).to be_truthy expect(File.exist?(zipped_filename)).to be_truthy
expect(File.read(destination_filename)).to eq File.read(unzipped_filename) expect(File.read(destination_filename)).to eq File.read(unzipped_filename)
end end
@@ -34,10 +34,10 @@ RSpec.describe Dunlop::FileZip do
context "mime-type: application/x-gzip" do context "mime-type: application/x-gzip" do
it "unzips the file to the provided filename" do it "unzips the file to the provided filename" do
expect(File.exists?(destination_filename)).to be_falsey expect(File.exist?(destination_filename)).to be_falsey
subject.unzip(gzipped_filename, destination_filename) subject.unzip(gzipped_filename, destination_filename)
expect(File.exists?(destination_filename)).to be_truthy expect(File.exist?(destination_filename)).to be_truthy
expect(File.exists?(gzipped_filename)).to be_truthy expect(File.exist?(gzipped_filename)).to be_truthy
expect(File.read(destination_filename)).to eq File.read(unzipped_filename) expect(File.read(destination_filename)).to eq File.read(unzipped_filename)
end end
@@ -46,10 +46,10 @@ RSpec.describe Dunlop::FileZip do
context "mime-type: text/plain" do context "mime-type: text/plain" do
it "copies the file to the provided filename" do it "copies the file to the provided filename" do
expect(File.exists?(destination_filename)).to be_falsey expect(File.exist?(destination_filename)).to be_falsey
subject.unzip(unzipped_filename, destination_filename) subject.unzip(unzipped_filename, destination_filename)
expect(File.exists?(destination_filename)).to be_truthy expect(File.exist?(destination_filename)).to be_truthy
expect(File.exists?(unzipped_filename)).to be_truthy expect(File.exist?(unzipped_filename)).to be_truthy
expect(File.read(destination_filename)).to eq File.read(unzipped_filename) expect(File.read(destination_filename)).to eq File.read(unzipped_filename)
end end
@@ -69,10 +69,10 @@ RSpec.describe Dunlop::FileZip do
end end
it "gzips the file to the provided filename" do it "gzips the file to the provided filename" do
expect(File.exists?(gzipped_filename)).to be_falsey expect(File.exist?(gzipped_filename)).to be_falsey
subject.gzip(unzipped_filename, gzipped_filename) subject.gzip(unzipped_filename, gzipped_filename)
expect(File.exists?(gzipped_filename)).to be_truthy expect(File.exist?(gzipped_filename)).to be_truthy
expect(File.exists?(unzipped_filename)).to be_truthy expect(File.exist?(unzipped_filename)).to be_truthy
expect(File.size(unzipped_filename)).to eq 305 expect(File.size(unzipped_filename)).to eq 305
expect(File.size(gzipped_filename)).to eq 153 expect(File.size(gzipped_filename)).to eq 153