datashift_journey 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +391 -0
  4. data/Rakefile +26 -0
  5. data/app/assets/stylesheets/datashift_journey/partials/_state_jumper_toolbar.scss.erb +27 -0
  6. data/app/controllers/concerns/datashift_journey/error_renderer.rb +9 -0
  7. data/app/controllers/concerns/datashift_journey/review_renderer.rb +21 -0
  8. data/app/controllers/concerns/datashift_journey/token_based_access.rb +23 -0
  9. data/app/controllers/concerns/datashift_journey/validate_state.rb +59 -0
  10. data/app/controllers/datashift_journey/abandon_enrollments_controller.rb +14 -0
  11. data/app/controllers/datashift_journey/abandonments_controller.rb +17 -0
  12. data/app/controllers/datashift_journey/api/v1/states_controller.rb +49 -0
  13. data/app/controllers/datashift_journey/application_controller.rb +53 -0
  14. data/app/controllers/datashift_journey/errors_controller.rb +24 -0
  15. data/app/controllers/datashift_journey/journey_ends_controller.rb +19 -0
  16. data/app/controllers/datashift_journey/journey_plans_controller.rb +166 -0
  17. data/app/controllers/datashift_journey/page_states_controller.rb +49 -0
  18. data/app/controllers/datashift_journey/reviews_controller.rb +32 -0
  19. data/app/controllers/datashift_journey/state_jumper_controller.rb +51 -0
  20. data/app/factories/datashift_journey/form_object_factory.rb +68 -0
  21. data/app/forms/datashift_journey/collector/base_collector_form.rb +60 -0
  22. data/app/forms/datashift_journey/concerns/form_mixin.rb +64 -0
  23. data/app/forms/datashift_journey/null_form.rb +20 -0
  24. data/app/helpers/datashift_journey/application_helper.rb +50 -0
  25. data/app/helpers/datashift_journey/back_link_helper.rb +9 -0
  26. data/app/models/datashift_journey/collector/data_node.rb +18 -0
  27. data/app/models/datashift_journey/collector/form_definition.rb +35 -0
  28. data/app/models/datashift_journey/collector/form_field.rb +61 -0
  29. data/app/models/datashift_journey/journey_review.rb +65 -0
  30. data/app/models/datashift_journey/review_data_section.rb +32 -0
  31. data/app/serializers/datashift_journey/collector/page_state_serializer.rb +9 -0
  32. data/app/serializers/state_machines/state/state_serializer.rb +5 -0
  33. data/app/views/datashift_journey/collector/_generic_form.html.erb +14 -0
  34. data/app/views/datashift_journey/errors/401.html.erb +13 -0
  35. data/app/views/datashift_journey/errors/403.html.erb +13 -0
  36. data/app/views/datashift_journey/errors/404.html.erb +13 -0
  37. data/app/views/datashift_journey/errors/422.html.erb +11 -0
  38. data/app/views/datashift_journey/errors/500.html.erb +13 -0
  39. data/app/views/datashift_journey/errors/503.html.erb +11 -0
  40. data/app/views/datashift_journey/errors/invalid_authenticity_token.html.erb +14 -0
  41. data/app/views/datashift_journey/journey_ends/new.html.erb +5 -0
  42. data/app/views/datashift_journey/journey_ends/show.html.erb +5 -0
  43. data/app/views/datashift_journey/journey_plans/_form.html.erb +14 -0
  44. data/app/views/datashift_journey/journey_plans/_render_fields.html.erb +24 -0
  45. data/app/views/datashift_journey/journey_plans/edit.html.erb +6 -0
  46. data/app/views/datashift_journey/journey_plans/new.html.erb +6 -0
  47. data/app/views/datashift_journey/shared/_default_actions.html.erb +6 -0
  48. data/app/views/datashift_journey/shared/_errors.html.erb +19 -0
  49. data/app/views/datashift_journey/shared/_submit_action.html.erb +5 -0
  50. data/app/views/datashift_journey/state_jumper/_toolbar.html.erb +16 -0
  51. data/config/brakeman.ignore +42 -0
  52. data/config/i18n-tasks.yml +103 -0
  53. data/config/initializers/exceptions_app.rb +3 -0
  54. data/config/initializers/mime_types.rb +1 -0
  55. data/config/initializers/rswag-api.rb +14 -0
  56. data/config/initializers/rswag-ui.rb +9 -0
  57. data/config/locales/en.yml +39 -0
  58. data/config/routes.rb +44 -0
  59. data/lib/datashift_journey/collector/field_snippet.rb +12 -0
  60. data/lib/datashift_journey/collector/page_state_snippet.rb +12 -0
  61. data/lib/datashift_journey/collector/snippet.rb +14 -0
  62. data/lib/datashift_journey/configuration.rb +103 -0
  63. data/lib/datashift_journey/engine.rb +38 -0
  64. data/lib/datashift_journey/exceptions.rb +26 -0
  65. data/lib/datashift_journey/helpers/back_link.rb +58 -0
  66. data/lib/datashift_journey/journey/machine_builder.rb +59 -0
  67. data/lib/datashift_journey/prepare_data_for_review.rb +219 -0
  68. data/lib/datashift_journey/reference_generator.rb +51 -0
  69. data/lib/datashift_journey/state_machines/branch_sequence_map.rb +35 -0
  70. data/lib/datashift_journey/state_machines/extensions.rb +40 -0
  71. data/lib/datashift_journey/state_machines/planner.rb +206 -0
  72. data/lib/datashift_journey/state_machines/sequence.rb +86 -0
  73. data/lib/datashift_journey/state_machines/state_machine_core_ext.rb +72 -0
  74. data/lib/datashift_journey/version.rb +3 -0
  75. data/lib/datashift_journey.rb +57 -0
  76. data/lib/generators/datashift_journey/collector/collector_generator.rb +43 -0
  77. data/lib/generators/datashift_journey/collector/install_collector_generator.rb +61 -0
  78. data/lib/generators/datashift_journey/collector/install_mongo_collector_generator.rb +44 -0
  79. data/lib/generators/datashift_journey/collector/templates/collector_concern.rb.tt +34 -0
  80. data/lib/generators/datashift_journey/collector/templates/collector_migration.rb.tt +46 -0
  81. data/lib/generators/datashift_journey/forms_generator.rb +45 -0
  82. data/lib/generators/datashift_journey/generate_common.rb +33 -0
  83. data/lib/generators/datashift_journey/setup/USAGE +12 -0
  84. data/lib/generators/datashift_journey/setup/setup_generator.rb +44 -0
  85. data/lib/generators/datashift_journey/setup/templates/initializer.rb.tt +17 -0
  86. data/lib/generators/datashift_journey/setup/templates/model_concern.rb.tt +37 -0
  87. data/lib/generators/datashift_journey/templates/base_form.rb.tt +7 -0
  88. data/lib/generators/datashift_journey/templates/collector_form.rb.tt +18 -0
  89. data/lib/generators/datashift_journey/templates/collector_view.rb.tt +15 -0
  90. data/lib/generators/datashift_journey/templates/journey_plan_form.rb.tt +23 -0
  91. data/lib/generators/datashift_journey/templates/journey_plan_view.rb.tt +15 -0
  92. data/lib/generators/datashift_journey/views_generator.rb +35 -0
  93. data/lib/tasks/state_machine.thor +48 -0
  94. data/spec/datashift_journey/complex_journey_spec.rb +132 -0
  95. data/spec/datashift_journey/machine_builder_spec.rb +268 -0
  96. data/spec/datashift_journey/planner_spec.rb +129 -0
  97. data/spec/datashift_journey/sequence_spec.rb +20 -0
  98. data/spec/dummy/Rakefile +6 -0
  99. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  100. data/spec/dummy/app/assets/stylesheets/application.css +16 -0
  101. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  102. data/spec/dummy/app/forms/base_form.rb +8 -0
  103. data/spec/dummy/app/forms/business_details_form.rb +17 -0
  104. data/spec/dummy/app/forms/business_type_form.rb +17 -0
  105. data/spec/dummy/app/forms/contact_details_form.rb +17 -0
  106. data/spec/dummy/app/forms/enter_reg_number_form.rb +17 -0
  107. data/spec/dummy/app/forms/new_or_renew_form.rb +17 -0
  108. data/spec/dummy/app/forms/postal_address_form.rb +17 -0
  109. data/spec/dummy/app/forms/question1_form.rb +9 -0
  110. data/spec/dummy/app/forms/question2_form.rb +12 -0
  111. data/spec/dummy/app/forms/sole_trader_name_form.rb +17 -0
  112. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  113. data/spec/dummy/app/models/payment.rb +5 -0
  114. data/spec/dummy/app/services/datashift_journey/models/collector_journey.rb +51 -0
  115. data/spec/dummy/app/views/_question1.html.erb +13 -0
  116. data/spec/dummy/app/views/_question2.html.erb +9 -0
  117. data/spec/dummy/app/views/layouts/alternative.html.erb +14 -0
  118. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  119. data/spec/dummy/app/views/pages/home.html.erb +6 -0
  120. data/spec/dummy/app/views/pages/start.html.erb +5 -0
  121. data/spec/dummy/bin/bundle +3 -0
  122. data/spec/dummy/bin/rails +4 -0
  123. data/spec/dummy/bin/rake +4 -0
  124. data/spec/dummy/bin/setup +29 -0
  125. data/spec/dummy/config/application.rb +39 -0
  126. data/spec/dummy/config/boot.rb +5 -0
  127. data/spec/dummy/config/database.yml +22 -0
  128. data/spec/dummy/config/environment.rb +5 -0
  129. data/spec/dummy/config/environments/development.rb +47 -0
  130. data/spec/dummy/config/environments/production.rb +79 -0
  131. data/spec/dummy/config/environments/test.rb +47 -0
  132. data/spec/dummy/config/initializers/assets.rb +11 -0
  133. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  134. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  135. data/spec/dummy/config/initializers/datashift_journey.rb +6 -0
  136. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  137. data/spec/dummy/config/initializers/inflections.rb +16 -0
  138. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  139. data/spec/dummy/config/initializers/session_store.rb +3 -0
  140. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  141. data/spec/dummy/config/locales/en.yml +27 -0
  142. data/spec/dummy/config/routes.rb +28 -0
  143. data/spec/dummy/config/secrets.yml +22 -0
  144. data/spec/dummy/config.ru +4 -0
  145. data/spec/dummy/db/migrate/20160101091218_create_dummy_checkout.rb +43 -0
  146. data/spec/dummy/db/migrate/20161221100703_datashift_journey_create_collector.rb +56 -0
  147. data/spec/dummy/db/schema.rb +142 -0
  148. data/spec/dummy/lib/version.rb +1 -0
  149. data/spec/factories/collector_factory.rb +16 -0
  150. data/spec/factories/collector_snippet_factory.rb +9 -0
  151. data/spec/factories/collector_state_page_factory.rb +12 -0
  152. data/spec/factories/data_node_factory.rb +9 -0
  153. data/spec/factories/form_factory.rb +6 -0
  154. data/spec/features/basic_navigation_spec.rb +125 -0
  155. data/spec/helpers/application_helper_spec.rb +40 -0
  156. data/spec/integration/collector/page_state_spec.rb +45 -0
  157. data/spec/models/collector/collector_spec.rb +100 -0
  158. data/spec/models/collector/page_state_spec.rb +30 -0
  159. data/spec/rails_helper.rb +73 -0
  160. data/spec/requests/collector/api/v1/page_state_spec.rb +85 -0
  161. data/spec/requests/collector/api/v1/states_spec.rb +28 -0
  162. data/spec/spec_helper.rb +63 -0
  163. data/spec/support/asserts.rb +27 -0
  164. data/spec/support/mailer_macros.rb +25 -0
  165. data/spec/support/page_objects/base_page_object.rb +77 -0
  166. data/spec/swagger_helper.rb +25 -0
  167. metadata +425 -0
@@ -0,0 +1,85 @@
1
+ require 'rails_helper'
2
+
3
+ module DatashiftJourney
4
+
5
+ describe 'Collector::PageState API' do
6
+
7
+ RSpec.configure do |config|
8
+ config.render_views = true
9
+ end
10
+
11
+ context "API" do
12
+
13
+ let(:expected_page_states) { 3 }
14
+
15
+ before :each do
16
+ create_list(:collector_page_state, 3)
17
+ end
18
+
19
+ it 'sends a list of page states' do
20
+
21
+ get '/api/v1/page_states'
22
+
23
+ json = parse(response)
24
+
25
+ # test for the 200 status-code
26
+ expect(response).to be_success
27
+
28
+ # check to make sure the right amount of messages are returned
29
+ expect(json['data'].length).to eq(expected_page_states)
30
+ end
31
+
32
+ it 'creates a new page state and responds with JSON body containing expected PageState' do
33
+ expect {
34
+ post '/api/v1/page_states', params: { page_state: { form_name: 'BrandNewPage' } }
35
+ }.to change(Collector::PageState, :count).by(1)
36
+
37
+ # test for the 200 status-code
38
+ expect(response).to be_success
39
+
40
+ jdata = parse_attribs(response)
41
+
42
+ expect(jdata).to have_key 'form-name'
43
+ expect(jdata['form-name']).to eq 'BrandNewPage'
44
+ end
45
+
46
+ it 'rejects badly defined page state and responds with Unprocesable entity' do
47
+ expect {
48
+ post '/api/v1/page_states', params: { page_state: {} }
49
+ }.to_not change(Collector::PageState, :count)
50
+
51
+ expect(response.status).to eq(422)
52
+
53
+ json = parse(response)
54
+
55
+ expect(json).to have_key 'errors'
56
+
57
+ e = json['errors'][0]
58
+ expect(e).to have_key "source"
59
+ expect(e).to have_key "detail"
60
+ expect(e['detail']).to eq "can't be blank"
61
+ end
62
+
63
+ it "should get a valid page state" do
64
+ page_state = Collector::PageState.first
65
+ get "/api/v1/page_states/#{page_state.id}"
66
+ expect(response).to be_success
67
+ jdata = parse response
68
+
69
+ expect( page_state.id.to_s).to eq jdata['data']['id']
70
+ expect( page_state.form_name).to eq jdata['data']['attributes']['form-name']
71
+
72
+ #see Rails.application.routes.default_url_options = {
73
+ expect( page_state_url(page_state, { host: "localhost", port: 3000 }) ).to eq jdata['data']['links']['self']
74
+ end
75
+
76
+ it "Should get JSON:API error block when requesting page state data with invalid ID" do
77
+ get '/api/v1/page_states/zzz'
78
+ expect(response.status).to eq(404)
79
+ jdata = parse response
80
+ expect( "Wrong ID provided").to eq jdata['errors'][0]['detail']
81
+ expect( '/data/attributes/id').to eq jdata['errors'][0]['source']['pointer']
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails_helper'
2
+
3
+ module DatashiftJourney
4
+
5
+ describe 'States API' do
6
+
7
+ RSpec.configure do |config|
8
+ config.render_views = true
9
+ end
10
+
11
+ context "list" do
12
+
13
+ it 'sends a list of states of current JourneyPlan model' do
14
+
15
+ get '/api/v1/states'
16
+
17
+ json = parse(response)
18
+
19
+ dump_json response
20
+
21
+ # test for the 200 status-code
22
+ expect(response).to be_success
23
+ expect(json['data']).to have_key 'states'
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,63 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+
3
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
4
+
5
+ require "simplecov"
6
+
7
+ SimpleCov.start do
8
+ add_filter "spec/factories"
9
+ add_filter "spec/dummy"
10
+ add_filter "app"
11
+ end
12
+
13
+ require 'rspec/rails'
14
+ require 'factory_girl_rails'
15
+ require 'capybara/rails'
16
+ require 'capybara/rspec'
17
+ require 'shoulda-matchers'
18
+ require "shoulda/matchers"
19
+
20
+ Rails.backtrace_cleaner.remove_silencers!
21
+
22
+ # Load our Engine
23
+ require File.expand_path("../../lib/datashift_journey", __FILE__)
24
+
25
+ RSpec.configure do |config|
26
+
27
+ config.mock_with :rspec
28
+ config.use_transactional_fixtures = true
29
+ config.infer_base_class_for_anonymous_controllers = false
30
+
31
+ config.include FactoryGirl::Syntax::Methods
32
+
33
+ config.filter_run :focus
34
+ config.run_all_when_everything_filtered = true
35
+
36
+ def parse(response)
37
+ JSON.parse(response.body)
38
+ end
39
+
40
+ def parse_attribs(response)
41
+ JSON.parse(response.body)['data']['attributes']
42
+ end
43
+
44
+ def dump_json(response)
45
+ puts response.body
46
+ end
47
+
48
+ end
49
+
50
+ # Decorate model with helper methods required for BRANCHING in Test journey plans
51
+
52
+ DatashiftJourney::Collector::Collector.class_eval do
53
+ def construction_demolition_value
54
+ 'yes'
55
+ end
56
+
57
+ def registration_type_value
58
+ # carrier_dealer_sequence:
59
+ 'carrier_dealer'
60
+ # broker_dealer_sequence: 'broker_dealer',
61
+ # carrier_broker_dealer_sequence: 'carrier_broker_dealer')
62
+ end
63
+ end
@@ -0,0 +1,27 @@
1
+ RSpec.configure do |_config|
2
+ # Set of standard checks
3
+ #
4
+ # Is our current state == expected_state
5
+ #
6
+ def expect_state_matches(journey, expected_state, message = nil)
7
+ expect(journey.state_name).to eq(expected_state), message
8
+ expect(journey.state).to eq(expected_state.to_s), message
9
+ expect(journey.state?(expected_state)).to eq(true), message
10
+ end
11
+
12
+ # Set of standard checks
13
+ #
14
+ # Is our current state == expected_state
15
+ # We can transition to back
16
+ # We can transition to next
17
+ # Fire next
18
+ #
19
+ def expect_state_canback_cannext_and_next!(journey, expected_state, message = nil)
20
+ expect_state_matches(journey, expected_state, message)
21
+
22
+ expect(journey.can_back?).to eq(true), 'Expected can_back? to be true'
23
+ expect(journey.can_next?).to eq(true), 'Expected can_next? to be true'
24
+
25
+ journey.next!
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ module MailerMacros
2
+
3
+ def last_email
4
+ ActionMailer::Base.deliveries.last
5
+ end
6
+
7
+ def last_email_text
8
+ ActionMailer::Base.deliveries.last.body.raw_source
9
+ end
10
+
11
+ # for multi-part e-mails, first need to select the correct part
12
+
13
+ def last_multipart_raw(index)
14
+ ActionMailer::Base.deliveries.last.parts[index].body.raw_source
15
+ end
16
+
17
+ def reset_email
18
+ ActionMailer::Base.deliveries = []
19
+ end
20
+ end
21
+
22
+ RSpec.configure do |config|
23
+ config.include(MailerMacros)
24
+ config.before(:each) { reset_email }
25
+ end
@@ -0,0 +1,77 @@
1
+ require 'capybara/dsl'
2
+
3
+ class BasePageObject
4
+
5
+ RSpec.configure do |_config|
6
+ # this suggested form dont seems to work for latest version of Rails/rspec
7
+ # config.include Rails.application.routes.url_helpers
8
+ # but simply using standard module inclusion does the trick
9
+ include Rails.application.routes.url_helpers
10
+
11
+ Rails.application.routes.default_url_options = { host: 'www.example.com' }
12
+ end
13
+
14
+ include RSpec::Matchers
15
+ include Capybara::DSL
16
+
17
+ # In RSpec the Engine routing proxy method may not be available,
18
+ # Use this helper to prefix Engine paths in your specs :dsj_url_helper.page_state_path
19
+ #
20
+ def dsj_url_helper
21
+ DatashiftJourney::Engine.routes.url_helpers
22
+ end
23
+
24
+ # Default - relies on PageObject utilising the 'state' method
25
+ # so we can create correct journey_plan object and jump straight to right page
26
+ def visit_page
27
+ begin
28
+ @journey_plan ||= DatashiftJourney.journey_plan_class.new
29
+ rescue => e
30
+ puts 'WARNING -RSPEC Setup Issue - No create_related_journey_plan - '\
31
+ "did you call 'state :<state>' in your PageObject ?"
32
+ puts 'See PageObjectHelpers for more details'
33
+ raise e
34
+ end
35
+
36
+ Rails.logger.debug("RSPEC : VISITING state [#{journey_plan.state}] with #{journey_plan.inspect}")
37
+
38
+ visit dsj_url_helper.journey_plan_state_path(journey_plan.state, journey_plan)
39
+
40
+ self
41
+ end
42
+
43
+ def visit_state(state)
44
+ visit dsj_url_helper.journey_plan_state_path(state, journey_plan)
45
+ end
46
+
47
+ def submit
48
+ click_button('Continue')
49
+ end
50
+
51
+ def click_back_link
52
+ click_link(I18n.t('back'))
53
+ end
54
+
55
+ # Default advance - fill out page and click submit
56
+ # fill_page - expect derived to define this - this should not call Submit
57
+ #
58
+ def advance_page
59
+ visit_page unless current_path && has_text?(self.class.on_page_text)
60
+ fill_page
61
+ submit
62
+ find_journey_plan
63
+ end
64
+
65
+ def dump
66
+ print page.html
67
+ end
68
+
69
+ # requires test has : js: true
70
+ # rubocop:disable Debugger
71
+ def screenshot(timestamp = '%H%M%S%L')
72
+ file = "/tmp/rspec_po_#{Time.zone.now.strftime(timestamp)}.png"
73
+ save_screenshot(file, full: true)
74
+ puts "RSPEC created screenshot of current page #{file}"
75
+ end
76
+
77
+ end
@@ -0,0 +1,25 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.configure do |config|
4
+ # Specify a root folder where Swagger JSON files are generated
5
+ # NOTE: If you're using the rswag-api to serve API descriptions, you'll need
6
+ # to ensure that it's confiugred to server Swagger from the same folder
7
+ config.swagger_root = File.join(DatashiftJourney::Engine.root, 'spec', 'swagger')
8
+
9
+ # Define one or more Swagger documents and provide global metadata for each one
10
+ # When you run the 'rswag:specs:to_swagger' rake task, the complete Swagger will
11
+ # be generated at the provided relative path under swagger_root
12
+ # By default, the operations defined in spec files are added to the first
13
+ # document below. You can override this behavior by adding a swagger_doc tag to the
14
+ # the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
15
+ config.swagger_docs = {
16
+ 'v1/swagger.json' => {
17
+ swagger: '2.0',
18
+ info: {
19
+ title: 'API V1',
20
+ version: 'v1'
21
+ },
22
+ paths: {}
23
+ }
24
+ }
25
+ end