nayati 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +79 -0
  4. data/Rakefile +32 -0
  5. data/app/models/nayati/application_record.rb +5 -0
  6. data/app/models/nayati/master_operation.rb +46 -0
  7. data/app/models/nayati/master_workflow.rb +67 -0
  8. data/app/models/nayati/name_based_constantable.rb +30 -0
  9. data/app/models/nayati/operation.rb +29 -0
  10. data/app/models/nayati/operation_configuration.rb +73 -0
  11. data/app/models/nayati/operation_implementer_base.rb +21 -0
  12. data/app/models/nayati/workflow.rb +170 -0
  13. data/config/operations.yml +3 -0
  14. data/db/migrate/20200127144219_create_workflow.rb +16 -0
  15. data/db/migrate/20200127144220_create_operation.rb +19 -0
  16. data/lib/generators/nayati/install/install_generator.rb +30 -0
  17. data/lib/generators/nayati/install/templates/create_operation.rb +19 -0
  18. data/lib/generators/nayati/install/templates/create_workflow.rb +16 -0
  19. data/lib/generators/nayati/install/templates/operations.yml +3 -0
  20. data/lib/generators/nayati/operation/operation_generator.rb +46 -0
  21. data/lib/generators/nayati/operation/templates/operation_template.txt +20 -0
  22. data/lib/generators/nayati/workflow/templates/nayati_service_template.txt +20 -0
  23. data/lib/generators/nayati/workflow/workflow_generator.rb +39 -0
  24. data/lib/nayati.rb +5 -0
  25. data/lib/nayati/engine.rb +12 -0
  26. data/lib/nayati/version.rb +3 -0
  27. data/lib/nayati/workflow_results/base.rb +18 -0
  28. data/lib/nayati/workflow_runner.rb +34 -0
  29. data/spec/dummy/Rakefile +6 -0
  30. data/spec/dummy/app/models/application_record.rb +3 -0
  31. data/spec/dummy/bin/bundle +3 -0
  32. data/spec/dummy/bin/rails +4 -0
  33. data/spec/dummy/bin/rake +4 -0
  34. data/spec/dummy/bin/setup +36 -0
  35. data/spec/dummy/bin/update +31 -0
  36. data/spec/dummy/bin/yarn +11 -0
  37. data/spec/dummy/config.ru +5 -0
  38. data/spec/dummy/config/application.rb +19 -0
  39. data/spec/dummy/config/boot.rb +5 -0
  40. data/spec/dummy/config/cable.yml +10 -0
  41. data/spec/dummy/config/database.yml +24 -0
  42. data/spec/dummy/config/environment.rb +5 -0
  43. data/spec/dummy/config/environments/development.rb +61 -0
  44. data/spec/dummy/config/environments/production.rb +94 -0
  45. data/spec/dummy/config/environments/test.rb +46 -0
  46. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  47. data/spec/dummy/config/initializers/assets.rb +14 -0
  48. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  49. data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
  50. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  51. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  52. data/spec/dummy/config/initializers/inflections.rb +16 -0
  53. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  54. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  55. data/spec/dummy/config/locales/en.yml +33 -0
  56. data/spec/dummy/config/operations.yml +3 -0
  57. data/spec/dummy/config/puma.rb +34 -0
  58. data/spec/dummy/config/spring.rb +6 -0
  59. data/spec/dummy/config/storage.yml +34 -0
  60. data/spec/dummy/db/migrate/20200202111127_create_workflow.rb +16 -0
  61. data/spec/dummy/db/migrate/20200202111128_create_operation.rb +19 -0
  62. data/spec/dummy/db/schema.rb +36 -0
  63. data/spec/dummy/log/development.log +56 -0
  64. data/spec/dummy/package.json +5 -0
  65. data/spec/dummy/public/404.html +67 -0
  66. data/spec/dummy/public/422.html +67 -0
  67. data/spec/dummy/public/500.html +66 -0
  68. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  69. data/spec/dummy/public/apple-touch-icon.png +0 -0
  70. data/spec/dummy/public/favicon.ico +0 -0
  71. data/spec/factories/operations_factory.rb +6 -0
  72. data/spec/factories/workflow_factory.rb +7 -0
  73. data/spec/lib/decider/workflow_runner_spec.rb +59 -0
  74. data/spec/lib/decider_spec.rb +4 -0
  75. data/spec/models/decider/master_operation_spec.rb +26 -0
  76. data/spec/models/decider/master_workflow_spec.rb +28 -0
  77. data/spec/models/decider/operation_spec.rb +48 -0
  78. data/spec/models/decider/workflow_spec.rb +159 -0
  79. data/spec/rails_helper.rb +57 -0
  80. data/spec/spec_helper.rb +120 -0
  81. metadata +259 -0
@@ -0,0 +1,6 @@
1
+ %w[
2
+ .ruby-version
3
+ .rbenv-vars
4
+ tmp/restart.txt
5
+ tmp/caching-dev.txt
6
+ ].each { |path| Spring.watch(path) }
@@ -0,0 +1,34 @@
1
+ test:
2
+ service: Disk
3
+ root: <%= Rails.root.join("tmp/storage") %>
4
+
5
+ local:
6
+ service: Disk
7
+ root: <%= Rails.root.join("storage") %>
8
+
9
+ # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
10
+ # amazon:
11
+ # service: S3
12
+ # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
13
+ # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
14
+ # region: us-east-1
15
+ # bucket: your_own_bucket
16
+
17
+ # Remember not to checkin your GCS keyfile to a repository
18
+ # google:
19
+ # service: GCS
20
+ # project: your_project
21
+ # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
22
+ # bucket: your_own_bucket
23
+
24
+ # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
25
+ # microsoft:
26
+ # service: AzureStorage
27
+ # storage_account_name: your_account_name
28
+ # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
29
+ # container: your_container_name
30
+
31
+ # mirror:
32
+ # service: Mirror
33
+ # primary: local
34
+ # mirrors: [ amazon, google, microsoft ]
@@ -0,0 +1,16 @@
1
+ class CreateWorkflow < ActiveRecord::Migration[5.0]
2
+ def self.up
3
+ create_table :nayati_workflows do |t|
4
+ t.string :name
5
+ t.integer :initial_operation_id
6
+ t.string :identifier
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :nayati_workflows, :identifier
11
+ end
12
+
13
+ def self.down
14
+ drop_table :nayati_workflows
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ class CreateOperation < ActiveRecord::Migration[5.0]
2
+ def self.up
3
+ create_table :nayati_operations do |t|
4
+ t.string :name
5
+ t.integer :after_success_operation_id
6
+ t.integer :after_failure_operation_id
7
+ t.integer :workflow_id
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :nayati_operations, :workflow_id
12
+ add_index :nayati_operations, :after_failure_operation_id
13
+ add_index :nayati_operations, :after_success_operation_id
14
+ end
15
+
16
+ def self.down
17
+ drop_table :workflows
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 2020_02_02_111128) do
14
+
15
+ create_table "nayati_operations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
16
+ t.string "name"
17
+ t.integer "after_success_operation_id"
18
+ t.integer "after_failure_operation_id"
19
+ t.integer "workflow_id"
20
+ t.datetime "created_at", null: false
21
+ t.datetime "updated_at", null: false
22
+ t.index ["after_failure_operation_id"], name: "index_nayati_operations_on_after_failure_operation_id"
23
+ t.index ["after_success_operation_id"], name: "index_nayati_operations_on_after_success_operation_id"
24
+ t.index ["workflow_id"], name: "index_nayati_operations_on_workflow_id"
25
+ end
26
+
27
+ create_table "nayati_workflows", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
28
+ t.string "name"
29
+ t.integer "initial_operation_id"
30
+ t.string "identifier"
31
+ t.datetime "created_at", null: false
32
+ t.datetime "updated_at", null: false
33
+ t.index ["identifier"], name: "index_nayati_workflows_on_identifier"
34
+ end
35
+
36
+ end
@@ -0,0 +1,56 @@
1
+  (18.0ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
2
+ ↳ bin/rails:4
3
+  (17.7ms) CREATE DATABASE `nayati_development` DEFAULT CHARACTER SET `utf8`
4
+ ↳ bin/rails:4
5
+  (1.4ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
6
+ ↳ bin/rails:4
7
+  (3.8ms) CREATE DATABASE `nayati_test` DEFAULT CHARACTER SET `utf8`
8
+ ↳ bin/rails:4
9
+  (2.4ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
10
+ ↳ bin/rails:4
11
+  (84.7ms) CREATE TABLE `schema_migrations` (`version` varchar(255) NOT NULL PRIMARY KEY)
12
+ ↳ bin/rails:4
13
+  (37.2ms) CREATE TABLE `ar_internal_metadata` (`key` varchar(255) NOT NULL PRIMARY KEY, `value` varchar(255), `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL)
14
+ ↳ bin/rails:4
15
+  (4.2ms) SELECT GET_LOCK('395797386095851950', 0)
16
+ ↳ bin/rails:4
17
+  (2.0ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
18
+ ↳ bin/rails:4
19
+ Migrating to CreateWorkflow (20200202111127)
20
+  (29.7ms) CREATE TABLE `nayati_workflows` (`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255), `initial_operation_id` int, `identifier` varchar(255), `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL) ENGINE=InnoDB
21
+ ↳ db/migrate/20200202111127_create_workflow.rb:3
22
+  (48.8ms) CREATE INDEX `index_nayati_workflows_on_identifier` ON `nayati_workflows` (`identifier`) 
23
+ ↳ db/migrate/20200202111127_create_workflow.rb:10
24
+  (2.2ms) BEGIN
25
+ ↳ bin/rails:4
26
+ ActiveRecord::SchemaMigration Create (4.6ms) INSERT INTO `schema_migrations` (`version`) VALUES ('20200202111127')
27
+ ↳ bin/rails:4
28
+  (1.4ms) COMMIT
29
+ ↳ bin/rails:4
30
+ Migrating to CreateOperation (20200202111128)
31
+  (32.4ms) CREATE TABLE `nayati_operations` (`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` varchar(255), `after_success_operation_id` int, `after_failure_operation_id` int, `workflow_id` int, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL) ENGINE=InnoDB
32
+ ↳ db/migrate/20200202111128_create_operation.rb:3
33
+  (30.5ms) CREATE INDEX `index_nayati_operations_on_workflow_id` ON `nayati_operations` (`workflow_id`) 
34
+ ↳ db/migrate/20200202111128_create_operation.rb:11
35
+  (30.5ms) CREATE INDEX `index_nayati_operations_on_after_failure_operation_id` ON `nayati_operations` (`after_failure_operation_id`) 
36
+ ↳ db/migrate/20200202111128_create_operation.rb:12
37
+  (20.8ms) CREATE INDEX `index_nayati_operations_on_after_success_operation_id` ON `nayati_operations` (`after_success_operation_id`) 
38
+ ↳ db/migrate/20200202111128_create_operation.rb:13
39
+  (0.2ms) BEGIN
40
+ ↳ bin/rails:4
41
+ ActiveRecord::SchemaMigration Create (0.4ms) INSERT INTO `schema_migrations` (`version`) VALUES ('20200202111128')
42
+ ↳ bin/rails:4
43
+  (0.9ms) COMMIT
44
+ ↳ bin/rails:4
45
+ ActiveRecord::InternalMetadata Load (1.6ms) SELECT `ar_internal_metadata`.* FROM `ar_internal_metadata` WHERE `ar_internal_metadata`.`key` = 'environment' LIMIT 1
46
+ ↳ bin/rails:4
47
+  (0.2ms) BEGIN
48
+ ↳ bin/rails:4
49
+ ActiveRecord::InternalMetadata Create (2.5ms) INSERT INTO `ar_internal_metadata` (`key`, `value`, `created_at`, `updated_at`) VALUES ('environment', 'development', '2020-02-02 11:11:45', '2020-02-02 11:11:45')
50
+ ↳ bin/rails:4
51
+  (1.6ms) COMMIT
52
+ ↳ bin/rails:4
53
+  (0.4ms) SELECT RELEASE_LOCK('395797386095851950')
54
+ ↳ bin/rails:4
55
+  (0.3ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
56
+ ↳ bin/rails:4
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "dummy",
3
+ "private": true,
4
+ "dependencies": {}
5
+ }
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ .rails-default-error-page {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ .rails-default-error-page div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ .rails-default-error-page div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ .rails-default-error-page h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ .rails-default-error-page div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body class="rails-default-error-page">
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
File without changes
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :nayati_operation, class: Nayati::Operation do
3
+ association :workflow, :factory => :nayati_workflow
4
+ name 'some_operation'
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :nayati_workflow, class: Nayati::Workflow do
3
+ name 'Doing something'
4
+ initial_operation_name 'Initial Operation'
5
+ identifier 'some identifier'
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ require_relative '../../../lib/nayati/workflow_runner'
2
+ require_relative '../../../lib/nayati/workflow_results/base'
3
+ module Nayati
4
+ RSpec.describe WorkflowRunner do
5
+ # initial_operation
6
+ # / \
7
+ # (succ) (fail)
8
+ # / \
9
+ # op1 op2
10
+ # /\ /\
11
+ # / \ / \
12
+ # (s). (f) (s). (f)
13
+ # / \ / \
14
+ # op3 op4 op5 op6
15
+
16
+ describe '#run' do
17
+ let(:result_obj) { double }
18
+ let(:context) { double }
19
+ let(:abandoning_operation_implementer) { double(to_abandon?: true, perform_abandonment: true) }
20
+ let(:failing_operation_implementer) { double(to_fail?: true, to_abandon?: false, perform_failure: true) }
21
+ let(:succeeding_operation_implementer) { double(to_fail?: false, to_abandon?: false, perform: true) }
22
+ let(:workflow) { double(initial_operation: initial_operation, result_obj: result_obj) }
23
+ let(:initial_operation) { double(after_success_operation: op1, after_failure_operation: op2, present?: true, name: 'initial_operation') }
24
+ let(:op1) { double(after_success_operation: op3, after_failure_operation: op4, name: 'op1') }
25
+ let(:op2) { double(after_success_operation: op5, after_failure_operation: op6, name: 'op2') }
26
+ let(:op3) { double(after_success_operation: nil, after_failure_operation: nil, name: 'op3') }
27
+ let(:op4) { double(after_success_operation: nil, after_failure_operation: nil, name: 'op4') }
28
+ let(:op5) { double(after_success_operation: nil, after_failure_operation: nil, name: 'op5') }
29
+ let(:op6) { double(after_success_operation: nil, after_failure_operation: nil, name: 'op6') }
30
+ subject { WorkflowRunner.new(workflow, context).run }
31
+
32
+ context 'One of the operation abandons' do
33
+ it 'Runs the operations as per success and failure until one of the operation abandons and runs perform abandonment method on abandoning operation' do
34
+ allow(initial_operation).to receive(:build_implementer).with(context, result_obj) { succeeding_operation_implementer }
35
+ allow(op1).to receive(:build_implementer).with(context, result_obj) { abandoning_operation_implementer }
36
+ expect(succeeding_operation_implementer).to receive(:perform)
37
+ expect(op1).not_to receive(:perform)
38
+ expect(op3).not_to receive(:build_implementer)
39
+ expect(op4).not_to receive(:build_implementer)
40
+ expect(abandoning_operation_implementer).to receive(:perform_abandonment)
41
+
42
+ subject
43
+ end
44
+ end
45
+
46
+ context 'None of the operation abandons' do
47
+ it 'Runs operations as per after failure and after success operations' do
48
+ allow(initial_operation).to receive(:build_implementer).with(context, result_obj) { failing_operation_implementer }
49
+ expect(op2).to receive(:build_implementer).with(context, result_obj) { succeeding_operation_implementer }
50
+ expect(op5).to receive(:build_implementer).with(context, result_obj) { succeeding_operation_implementer }
51
+
52
+ expect(failing_operation_implementer).to receive(:perform_failure).exactly(1).times
53
+ expect(succeeding_operation_implementer).to receive(:perform).exactly(2).times
54
+ subject
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end