trailblazer-endpoint 0.0.3 → 0.0.8
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.
- checksums.yaml +4 -4
 - data/.gitignore +16 -0
 - data/Appraisals +5 -0
 - data/CHANGES.md +27 -0
 - data/README.md +40 -5
 - data/Rakefile +7 -1
 - data/gemfiles/rails_app.gemfile +12 -0
 - data/lib/trailblazer/endpoint.rb +50 -14
 - data/lib/trailblazer/endpoint/adapter.rb +30 -121
 - data/lib/trailblazer/endpoint/builder.rb +1 -1
 - data/lib/trailblazer/endpoint/controller.rb +217 -1
 - data/lib/trailblazer/endpoint/dsl.rb +8 -3
 - data/lib/trailblazer/endpoint/options.rb +16 -69
 - data/lib/trailblazer/endpoint/protocol.rb +7 -11
 - data/lib/trailblazer/endpoint/protocol/cipher.rb +27 -0
 - data/lib/trailblazer/endpoint/protocol/controller.rb +102 -0
 - data/lib/trailblazer/endpoint/protocol/find_process_model.rb +15 -0
 - data/lib/trailblazer/endpoint/version.rb +1 -1
 - data/test/adapter/api_test.rb +6 -11
 - data/test/adapter/web_test.rb +2 -5
 - data/test/config_test.rb +25 -0
 - data/test/docs/controller_test.rb +220 -73
 - data/test/endpoint_test.rb +1 -1
 - data/test/rails-app/.gitignore +8 -2
 - data/test/rails-app/.ruby-version +1 -0
 - data/test/rails-app/Gemfile +21 -9
 - data/test/rails-app/Gemfile.lock +174 -118
 - data/test/rails-app/app/concepts/app/api/v1/representer/errors.rb +16 -0
 - data/test/rails-app/app/concepts/auth/jwt.rb +35 -0
 - data/test/rails-app/app/concepts/auth/operation/authenticate.rb +32 -0
 - data/test/rails-app/app/concepts/auth/operation/policy.rb +9 -0
 - data/test/rails-app/app/concepts/song/cell/create.rb +4 -0
 - data/test/rails-app/app/concepts/song/cell/new.rb +4 -0
 - data/test/rails-app/app/concepts/song/operation/create.rb +17 -0
 - data/test/rails-app/app/concepts/song/operation/show.rb +10 -0
 - data/test/rails-app/app/concepts/song/representer.rb +5 -0
 - data/test/rails-app/app/concepts/song/view/create.erb +1 -0
 - data/test/rails-app/app/concepts/song/view/new.erb +1 -0
 - data/test/rails-app/app/controllers/api/v1/songs_controller.rb +41 -0
 - data/test/rails-app/app/controllers/application_controller.rb +8 -1
 - data/test/rails-app/app/controllers/application_controller/api.rb +107 -0
 - data/test/rails-app/app/controllers/application_controller/web.rb +46 -0
 - data/test/rails-app/app/controllers/auth_controller.rb +44 -0
 - data/test/rails-app/app/controllers/home_controller.rb +5 -0
 - data/test/rails-app/app/controllers/songs_controller.rb +254 -13
 - data/test/rails-app/app/models/song.rb +6 -0
 - data/test/rails-app/app/models/user.rb +7 -0
 - data/test/rails-app/bin/bundle +114 -0
 - data/test/rails-app/bin/rails +4 -0
 - data/test/rails-app/bin/rake +4 -0
 - data/test/rails-app/bin/setup +33 -0
 - data/test/rails-app/config/application.rb +26 -3
 - data/test/rails-app/config/credentials.yml.enc +1 -0
 - data/test/rails-app/config/database.yml +2 -2
 - data/test/rails-app/config/environments/development.rb +7 -17
 - data/test/rails-app/config/environments/production.rb +28 -23
 - data/test/rails-app/config/environments/test.rb +10 -12
 - data/test/rails-app/config/initializers/application_controller_renderer.rb +6 -4
 - data/test/rails-app/config/initializers/cors.rb +16 -0
 - data/test/rails-app/config/initializers/trailblazer.rb +2 -0
 - data/test/rails-app/config/locales/en.yml +11 -1
 - data/test/rails-app/config/master.key +1 -0
 - data/test/rails-app/config/routes.rb +27 -4
 - data/test/rails-app/db/schema.rb +15 -0
 - data/test/rails-app/test/controllers/api_songs_controller_test.rb +87 -0
 - data/test/rails-app/test/controllers/songs_controller_test.rb +152 -145
 - data/test/rails-app/test/test_helper.rb +7 -1
 - data/test/test_helper.rb +0 -2
 - data/trailblazer-endpoint.gemspec +2 -1
 - metadata +69 -24
 - data/test/rails-app/config/initializers/cookies_serializer.rb +0 -5
 - data/test/rails-app/config/initializers/new_framework_defaults.rb +0 -24
 - data/test/rails-app/config/initializers/session_store.rb +0 -3
 - data/test/rails-app/config/secrets.yml +0 -22
 - data/test/rails-app/test/helpers/.keep +0 -0
 - data/test/rails-app/test/integration/.keep +0 -0
 - data/test/rails-app/test/mailers/.keep +0 -0
 - data/test/rails-app/vendor/assets/javascripts/.keep +0 -0
 - data/test/rails-app/vendor/assets/stylesheets/.keep +0 -0
 
| 
         @@ -16,8 +16,18 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
            #
         
     | 
| 
       17 
17 
     | 
    
         
             
            # This would use the information in config/locales/es.yml.
         
     | 
| 
       18 
18 
     | 
    
         
             
            #
         
     | 
| 
      
 19 
     | 
    
         
            +
            # The following keys must be escaped otherwise they will not be retrieved by
         
     | 
| 
      
 20 
     | 
    
         
            +
            # the default I18n backend:
         
     | 
| 
      
 21 
     | 
    
         
            +
            #
         
     | 
| 
      
 22 
     | 
    
         
            +
            # true, false, on, off, yes, no
         
     | 
| 
      
 23 
     | 
    
         
            +
            #
         
     | 
| 
      
 24 
     | 
    
         
            +
            # Instead, surround them with single quotes.
         
     | 
| 
      
 25 
     | 
    
         
            +
            #
         
     | 
| 
      
 26 
     | 
    
         
            +
            # en:
         
     | 
| 
      
 27 
     | 
    
         
            +
            #   'true': 'foo'
         
     | 
| 
      
 28 
     | 
    
         
            +
            #
         
     | 
| 
       19 
29 
     | 
    
         
             
            # To learn more, please read the Rails Internationalization guide
         
     | 
| 
       20 
     | 
    
         
            -
            # available at  
     | 
| 
      
 30 
     | 
    
         
            +
            # available at https://guides.rubyonrails.org/i18n.html.
         
     | 
| 
       21 
31 
     | 
    
         | 
| 
       22 
32 
     | 
    
         
             
            en:
         
     | 
| 
       23 
33 
     | 
    
         
             
              hello: "Hello world"
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            fee3e51bb20a824ec13dc5912f3548f2
         
     | 
| 
         @@ -1,6 +1,29 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Rails.application.routes.draw do
         
     | 
| 
       2 
     | 
    
         
            -
              # For details on the DSL available within this file, see  
     | 
| 
       3 
     | 
    
         
            -
               
     | 
| 
       4 
     | 
    
         
            -
              post " 
     | 
| 
       5 
     | 
    
         
            -
              post " 
     | 
| 
      
 2 
     | 
    
         
            +
              # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
         
     | 
| 
      
 3 
     | 
    
         
            +
              post "/songs/create_with_options", to: "songs_controller/create_with_options#create"
         
     | 
| 
      
 4 
     | 
    
         
            +
              post "/songs/create_or", to: "songs_controller/create_or#create"
         
     | 
| 
      
 5 
     | 
    
         
            +
              post "/songs/endpoint_ctx", to: "songs_controller/create_endpoint_ctx#create"
         
     | 
| 
      
 6 
     | 
    
         
            +
              post "/songs/create_with_or", to: "songs#create"
         
     | 
| 
      
 7 
     | 
    
         
            +
              post "/songs", to: "songs#create_without_block"
         
     | 
| 
      
 8 
     | 
    
         
            +
              post "/songs/create_with_protocol_failure", to: "songs_controller/create_with_protocol_failure#create_with_protocol_failure"
         
     | 
| 
      
 9 
     | 
    
         
            +
              post "/songs/create_with_options_for_domain_ctx", to: "songs_controller/create_with_options_for_domain_ctx#create"
         
     | 
| 
      
 10 
     | 
    
         
            +
              post "/auth/sign_in", to: "auth#sign_in"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              post "/v1/songs", to: "api/v1/songs#create"
         
     | 
| 
      
 13 
     | 
    
         
            +
              get "/v1/songs/:id", to: "api/v1/songs#show"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              get "/v1/songs_with_options/:id", to: "api/v1/songs_controller/with_options#show"
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              get "/", to: "home#dashboard"
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              post "/songs/serialize", to: "songs_controller/serialize#create"
         
     | 
| 
      
 20 
     | 
    
         
            +
              post "/songs/copy_from_domain_ctx", to: "songs_controller/create1#create"
         
     | 
| 
      
 21 
     | 
    
         
            +
              post "/songs/serialize1", to: "songs_controller/serialize1#create"
         
     | 
| 
      
 22 
     | 
    
         
            +
              post "/songs/serialize2", to: "songs_controller/serialize2#create"
         
     | 
| 
      
 23 
     | 
    
         
            +
              post "/songs/serialize3", to: "songs_controller/serialize3#create"
         
     | 
| 
      
 24 
     | 
    
         
            +
              post "/songs/serialize4", to: "songs_controller/serialize4#create"
         
     | 
| 
      
 25 
     | 
    
         
            +
              post "/songs/serialize5", to: "songs_controller/serialize5#create"
         
     | 
| 
      
 26 
     | 
    
         
            +
              post "/songs/serialize6", to: "songs_controller/serialize6#create"
         
     | 
| 
      
 27 
     | 
    
         
            +
              post "/songs/serialize7", to: "songs_controller/serialize7#create"
         
     | 
| 
      
 28 
     | 
    
         
            +
              post "/songs/serialize72", to: "songs_controller/serialize7#new"
         
     | 
| 
       6 
29 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 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 
     | 
    
         
            +
            # This file is the source Rails uses to define your schema when running `rails
         
     | 
| 
      
 6 
     | 
    
         
            +
            # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
         
     | 
| 
      
 7 
     | 
    
         
            +
            # be faster and is potentially less error prone than running all of your
         
     | 
| 
      
 8 
     | 
    
         
            +
            # migrations from scratch. Old migrations may fail to apply correctly if those
         
     | 
| 
      
 9 
     | 
    
         
            +
            # migrations use external dependencies or application code.
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            # It's strongly recommended that you check this file into your version control system.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ActiveRecord::Schema.define(version: 0) do
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,87 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "test_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class ApiSongsControllerTest < ActionDispatch::IntegrationTest
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def jwt(user_id)
         
     | 
| 
      
 6 
     | 
    
         
            +
                Auth::Jwt.generate('user_id', user_id, {}
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # 'email': options['current_user'].email
         
     | 
| 
      
 8 
     | 
    
         
            +
                )
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def post_json(endpoint, params_hash, api_token = nil, headers={})
         
     | 
| 
      
 12 
     | 
    
         
            +
                post endpoint, params: params_hash.to_json, headers: request_headers(api_token).merge(headers)
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
              def get_json(endpoint, params = nil, api_token = nil)
         
     | 
| 
      
 15 
     | 
    
         
            +
                get endpoint, params: params, headers: request_headers(api_token)
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def request_headers(api_token = nil)
         
     | 
| 
      
 19 
     | 
    
         
            +
                headers = {
         
     | 
| 
      
 20 
     | 
    
         
            +
                  'Content-Type' => 'application/json'
         
     | 
| 
      
 21 
     | 
    
         
            +
                }
         
     | 
| 
      
 22 
     | 
    
         
            +
                unless api_token.nil?
         
     | 
| 
      
 23 
     | 
    
         
            +
                  headers.merge!(authorization_header(api_token))
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
                headers
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
              def authorization_header(api_token)
         
     | 
| 
      
 28 
     | 
    
         
            +
                { 'Authorization' => "Bearer #{api_token}"}
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              test "API interface" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                yogi_jwt = jwt(1)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              # default {success}
         
     | 
| 
      
 36 
     | 
    
         
            +
                #:success
         
     | 
| 
      
 37 
     | 
    
         
            +
                post_json "/v1/songs", {id: 1}, yogi_jwt
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 40 
     | 
    
         
            +
                assert_equal "{\"id\":1}", response.body
         
     | 
| 
      
 41 
     | 
    
         
            +
                #:success end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                # no proper input/params
         
     | 
| 
      
 44 
     | 
    
         
            +
                post_json "/v1/songs", {}, yogi_jwt
         
     | 
| 
      
 45 
     | 
    
         
            +
              # default {failure}
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_response 422
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_equal "{\"errors\":{\"message\":\"The submitted data is invalid.\"}}", response.body
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              # 401
         
     | 
| 
      
 50 
     | 
    
         
            +
                #:not_authenticated
         
     | 
| 
      
 51 
     | 
    
         
            +
                post_json "/v1/songs", {} # no token
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert_response 401
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert_equal "{\"errors\":{\"message\":\"Authentication credentials were not provided or are invalid.\"}}", response.body
         
     | 
| 
      
 54 
     | 
    
         
            +
                #:not_authenticated end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
              # 403
         
     | 
| 
      
 57 
     | 
    
         
            +
                post_json "/v1/songs", {id: 1, policy: false}, yogi_jwt
         
     | 
| 
      
 58 
     | 
    
         
            +
                assert_response 403
         
     | 
| 
      
 59 
     | 
    
         
            +
                assert_equal "{\"errors\":{\"message\":\"Action not allowed due to a policy setting.\"}}", response.body
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              # 200 / GET
         
     | 
| 
      
 62 
     | 
    
         
            +
                get_json "/v1/songs/1", {}, yogi_jwt
         
     | 
| 
      
 63 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 64 
     | 
    
         
            +
                assert_equal "{\"id\":\"1\"}", response.body
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              # 404
         
     | 
| 
      
 67 
     | 
    
         
            +
                get_json "/v1/songs/0", {}, yogi_jwt
         
     | 
| 
      
 68 
     | 
    
         
            +
                assert_response 404
         
     | 
| 
      
 69 
     | 
    
         
            +
                assert_equal "{\"errors\":{}}", response.body
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              # TODO: CHANGE/customize block
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              test "allows overriding {:success_block} and friends" do
         
     | 
| 
      
 75 
     | 
    
         
            +
                yogi_jwt = jwt(1)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              # Not authenticated, 401, overridden {:protocol_failure_block} kicks in
         
     | 
| 
      
 78 
     | 
    
         
            +
                get_json "/v1/songs_with_options/1"
         
     | 
| 
      
 79 
     | 
    
         
            +
                assert_response 402
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              # All good, default block
         
     | 
| 
      
 82 
     | 
    
         
            +
                get_json "/v1/songs_with_options/1", yogi_jwt
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
            end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            # TODO: test 404 with NotFound config
         
     | 
| 
         @@ -1,156 +1,163 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "test_helper"
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
       5 
     | 
    
         
            -
            end # FIXME
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            Song = Struct.new(:id, :title, :length) do
         
     | 
| 
       9 
     | 
    
         
            -
              def self.find_by(id:1); id=="0" ? nil : new(id, "A Song") end
         
     | 
| 
       10 
     | 
    
         
            -
            end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
            require "trailblazer"
         
     | 
| 
       13 
     | 
    
         
            -
            require "trailblazer/operation/model"
         
     | 
| 
       14 
     | 
    
         
            -
            # require "reform/form/active_model/validations"
         
     | 
| 
       15 
     | 
    
         
            -
            require "trailblazer/operation/contract"
         
     | 
| 
       16 
     | 
    
         
            -
            require "trailblazer/operation/representer"
         
     | 
| 
       17 
     | 
    
         
            -
            require "trailblazer/operation/guard"
         
     | 
| 
       18 
     | 
    
         
            -
            require "trailblazer/endpoint"
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
            require "representable/json"
         
     | 
| 
       22 
     | 
    
         
            -
            class Serializer < Representable::Decorator
         
     | 
| 
       23 
     | 
    
         
            -
              include Representable::JSON
         
     | 
| 
       24 
     | 
    
         
            -
              property :id
         
     | 
| 
       25 
     | 
    
         
            -
              property :title
         
     | 
| 
       26 
     | 
    
         
            -
              property :length
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
              class Errors < Representable::Decorator
         
     | 
| 
       29 
     | 
    
         
            -
                include Representable::JSON
         
     | 
| 
       30 
     | 
    
         
            -
                property :messages
         
     | 
| 
       31 
     | 
    
         
            -
              end
         
     | 
| 
       32 
     | 
    
         
            -
            end
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
            class Deserializer < Representable::Decorator
         
     | 
| 
       35 
     | 
    
         
            -
              include Representable::JSON
         
     | 
| 
       36 
     | 
    
         
            -
              property :title
         
     | 
| 
       37 
     | 
    
         
            -
            end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
            class Create < Trailblazer::Operation
         
     | 
| 
       41 
     | 
    
         
            -
              include Policy::Guard
         
     | 
| 
       42 
     | 
    
         
            -
              policy ->(*) { self["user.current"] == ::Module }
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
              extend Representer::DSL
         
     | 
| 
       45 
     | 
    
         
            -
              representer :serializer, Serializer
         
     | 
| 
       46 
     | 
    
         
            -
              representer :deserializer, Deserializer
         
     | 
| 
       47 
     | 
    
         
            -
              representer :errors, Serializer::Errors
         
     | 
| 
       48 
     | 
    
         
            -
              # self["representer.serializer.class"] = Representer
         
     | 
| 
       49 
     | 
    
         
            -
              # self["representer.deserializer.class"] = Deserializer
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
              include Model
         
     | 
| 
       52 
     | 
    
         
            -
              model Song, :create
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
              include Contract::Step
         
     | 
| 
       55 
     | 
    
         
            -
              include Representer::Deserializer::JSON
         
     | 
| 
       56 
     | 
    
         
            -
              # contract do
         
     | 
| 
       57 
     | 
    
         
            -
              #   property :title
         
     | 
| 
       58 
     | 
    
         
            -
              #   property :length
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
              #   include Reform::Form::ActiveModel::Validations
         
     | 
| 
       61 
     | 
    
         
            -
              #   validates :title, presence: true
         
     | 
| 
       62 
     | 
    
         
            -
              # end
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
              # FIXME: use trb-rails and reform
         
     | 
| 
       65 
     | 
    
         
            -
              class FakeContract
         
     | 
| 
       66 
     | 
    
         
            -
                def initialize(model,*); @model = model end
         
     | 
| 
       67 
     | 
    
         
            -
                def call(params)
         
     | 
| 
       68 
     | 
    
         
            -
                  if params[:title]
         
     | 
| 
       69 
     | 
    
         
            -
                    @title, @length = params[:title],params[:length]
         
     | 
| 
       70 
     | 
    
         
            -
                    return Trailblazer::Operation::Result.new(true, {})
         
     | 
| 
       71 
     | 
    
         
            -
                  end
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                  return Struct.new(:errors, :success?).new(Struct.new(:messages).new({"title": ["must be set"]}), false)
         
     | 
| 
       74 
     | 
    
         
            -
                end
         
     | 
| 
       75 
     | 
    
         
            -
                def sync; @model.title = @title; @model.length = @length; end
         
     | 
| 
       76 
     | 
    
         
            -
              end
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
              contract FakeContract
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
              def process(params)
         
     | 
| 
       81 
     | 
    
         
            -
                validate(params) do |f|
         
     | 
| 
       82 
     | 
    
         
            -
                  self["contract"].sync
         
     | 
| 
       83 
     | 
    
         
            -
                  self["model"].id = 9
         
     | 
| 
       84 
     | 
    
         
            -
                end
         
     | 
| 
       85 
     | 
    
         
            -
              end
         
     | 
| 
       86 
     | 
    
         
            -
            end
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
            class Update < Create
         
     | 
| 
       89 
     | 
    
         
            -
              action :find_by
         
     | 
| 
       90 
     | 
    
         
            -
            end
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
            # TODO: test present.
         
     | 
| 
       93 
     | 
    
         
            -
            class Show < Trailblazer::Operation
         
     | 
| 
       94 
     | 
    
         
            -
              include Policy::Guard
         
     | 
| 
       95 
     | 
    
         
            -
              policy ->(*) { self["user.current"] == ::Module }
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
              extend Representer::DSL
         
     | 
| 
       98 
     | 
    
         
            -
              representer :serializer, Serializer
         
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
              include Model
         
     | 
| 
       101 
     | 
    
         
            -
              model Song, :find_by
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
              self.> ->(input, options) { options["present"] = true }, before: "operation.result"
         
     | 
| 
       104 
     | 
    
         
            -
            end
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
            class SongsControllerTest < ActionController::TestCase
         
     | 
| 
       107 
     | 
    
         
            -
              # 404
         
     | 
| 
       108 
     | 
    
         
            -
              test "update 404" do
         
     | 
| 
       109 
     | 
    
         
            -
                post :update, params: { id: 0 }
         
     | 
| 
       110 
     | 
    
         
            -
                assert_equal 404, response.status
         
     | 
| 
       111 
     | 
    
         
            -
              end
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            class SongsControllerTest < ActionDispatch::IntegrationTest
         
     | 
| 
      
 4 
     | 
    
         
            +
              test "all possible outcomes with {Create}" do
         
     | 
| 
       113 
5 
     | 
    
         
             
              # 401
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                 
     | 
| 
       116 
     | 
    
         
            -
                assert_equal  
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
                 
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                 
     | 
| 
      
 6 
     | 
    
         
            +
                post "/songs", params: {}
         
     | 
| 
      
 7 
     | 
    
         
            +
                assert_response 401
         
     | 
| 
      
 8 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # sign in
         
     | 
| 
      
 11 
     | 
    
         
            +
                post "/auth/sign_in", params: {username: "yogi@trb.to", password: "secret"}
         
     | 
| 
      
 12 
     | 
    
         
            +
                assert_equal 1, session[:user_id]
         
     | 
| 
      
 13 
     | 
    
         
            +
                # follow_redirect!
         
     | 
| 
      
 14 
     | 
    
         
            +
                assert_equal 1, session[:user_id]
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                post "/songs", params: {id: 1}
         
     | 
| 
      
 17 
     | 
    
         
            +
              # default {success} block doesn't do anything
         
     | 
| 
      
 18 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 19 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                post "/songs", params: {}
         
     | 
| 
      
 22 
     | 
    
         
            +
              # default {failure} block doesn't do anything
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_response 422
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # 403
         
     | 
| 
      
 27 
     | 
    
         
            +
                post "/songs", params: {policy: false}
         
     | 
| 
      
 28 
     | 
    
         
            +
                assert_response 403
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                post "/songs/create_with_options", params: {id: 1}
         
     | 
| 
      
 32 
     | 
    
         
            +
              # {success} block renders model
         
     | 
| 
      
 33 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert_equal "<div>#<struct Song id=\"1\">#<struct User id=2, email=\"seuros@trb.to\"></div>\n", response.body
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                post "/songs/create_with_options", params: {}
         
     | 
| 
      
 37 
     | 
    
         
            +
              # default {failure} block doesn't do anything
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_response 422
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                post "/songs/create_with_or", params: {id: 1}
         
     | 
| 
      
 42 
     | 
    
         
            +
              # {success} block renders model
         
     | 
| 
      
 43 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 44 
     | 
    
         
            +
                assert_equal "<div>#<struct Song id=\"1\">#<struct User id=1, email=\"yogi@trb.to\"></div>\n", response.body
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                post "/songs/create_with_or", params: {}
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 48 
     | 
    
         
            +
                assert_equal %{<div>#<struct errors=nil></div>\n}, response.body
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              # Or { render status: 422 }
         
     | 
| 
      
 51 
     | 
    
         
            +
                post "/songs/create_or", params: {}
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert_response 422
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert_equal %{null}, response.body
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              # {:endpoint_ctx} is available in blocks
         
     | 
| 
      
 56 
     | 
    
         
            +
                post "/songs/endpoint_ctx", params: {id: 1}
         
     | 
| 
      
 57 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 58 
     | 
    
         
            +
                assert_equal "Created", response.body
         
     | 
| 
      
 59 
     | 
    
         
            +
                # assert_equal "[\"domain_ctx\",\"session\",\"controller\",\"config_source\",\"current_user\",\"domain_activity_return_signal\"]", response.body
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # {:options_for_domain_ctx} overrides domain_ctx
         
     | 
| 
      
 62 
     | 
    
         
            +
                post "/songs/create_with_options_for_domain_ctx", params: {id: 1} # params get overridden
         
     | 
| 
      
 63 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 64 
     | 
    
         
            +
                assert_equal "<div>#<struct Song id=999></div>\n", response.body
         
     | 
| 
       125 
65 
     | 
    
         
             
              end
         
     | 
| 
       126 
66 
     | 
    
         | 
| 
       127 
     | 
    
         
            -
               
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
                 
     | 
| 
       130 
     | 
    
         
            -
                assert_equal  
     | 
| 
       131 
     | 
    
         
            -
                assert_equal %{}, response.body
         
     | 
| 
       132 
     | 
    
         
            -
                assert_equal "/songs/9", response.header["Location"]
         
     | 
| 
      
 67 
     | 
    
         
            +
              test "override protocol_failure" do
         
     | 
| 
      
 68 
     | 
    
         
            +
                post "/songs/create_with_protocol_failure", params: {}
         
     | 
| 
      
 69 
     | 
    
         
            +
                assert_response 500
         
     | 
| 
      
 70 
     | 
    
         
            +
                assert_equal "wrong login, app crashed", response.body
         
     | 
| 
       133 
71 
     | 
    
         
             
              end
         
     | 
| 
       134 
72 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
               
     | 
| 
       136 
     | 
    
         
            -
               
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
      
 73 
     | 
    
         
            +
              test "serializing/deserializing/find_process_model_from_resume_data" do
         
     | 
| 
      
 74 
     | 
    
         
            +
              # # 401
         
     | 
| 
      
 75 
     | 
    
         
            +
              #   post "/songs/serialize/"
         
     | 
| 
      
 76 
     | 
    
         
            +
              #   assert_response 401
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              # sign in
         
     | 
| 
      
 79 
     | 
    
         
            +
                post "/auth/sign_in", params: {username: "yogi@trb.to", password: "secret"}
         
     | 
| 
      
 80 
     | 
    
         
            +
                assert_equal 1, session[:user_id]
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              # When {:encrypted_resume_data} is {nil} the entire deserialize cycle is skipped.
         
     | 
| 
      
 84 
     | 
    
         
            +
              # Nothing gets serialized.
         
     | 
| 
      
 85 
     | 
    
         
            +
              # This is considered an error since we're expecting resume data.
         
     | 
| 
      
 86 
     | 
    
         
            +
                post "/songs/serialize1/", params: {} # encrypted_resume_data: nil
         
     | 
| 
      
 87 
     | 
    
         
            +
                assert_response 500
         
     | 
| 
      
 88 
     | 
    
         
            +
                assert_equal "xxx", response.body # DISCUSS: is this an application or a protocol error?
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
              # Nothing deserialized, but {:remember} serialized
         
     | 
| 
      
 91 
     | 
    
         
            +
              # "confirm_delete form"
         
     | 
| 
      
 92 
     | 
    
         
            +
                post "/songs/serialize2/", params: {} # {:remember} serialized
         
     | 
| 
      
 93 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 94 
     | 
    
         
            +
                encrypted_string = "0109C4E535EDA2CCE8CD69E50C179F5950CC4A2A898504F951C995B6BCEAFE1DFAB02894854B96B9D11C23E25DB5FB03"
         
     | 
| 
      
 95 
     | 
    
         
            +
                assert_equal "false/nil/#{encrypted_string}", response.body
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              # {:remember} deserialized
         
     | 
| 
      
 98 
     | 
    
         
            +
              # "submit confirm_delete"
         
     | 
| 
      
 99 
     | 
    
         
            +
              # We're expecting serialized data and don't serialize anything.
         
     | 
| 
      
 100 
     | 
    
         
            +
                post "/songs/serialize3/", params: {encrypted_resume_data: encrypted_string} # {:remember} serialized
         
     | 
| 
      
 101 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 102 
     | 
    
         
            +
                assert_equal "false/{\"remember\"=>\"#<OpenStruct id=1>\", \"id\"=>9}/", response.body
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
              # retrieve process_model via id in {:resume_data}
         
     | 
| 
      
 105 
     | 
    
         
            +
              # we can see {endpoint_ctx[:process_model_id]}
         
     | 
| 
      
 106 
     | 
    
         
            +
              # We're expecting serialized data and don't serialize anything.
         
     | 
| 
      
 107 
     | 
    
         
            +
                post "/songs/serialize4/", params: {encrypted_resume_data: encrypted_string}
         
     | 
| 
      
 108 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 109 
     | 
    
         
            +
                assert_equal "9/{\"remember\"=>\"#<OpenStruct id=1>\", \"id\"=>9}/", response.body
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
              # retrieve process_model via {:resume_data}'s serialized id.
         
     | 
| 
      
 112 
     | 
    
         
            +
              # We're expecting serialized data and don't serialize anything.
         
     | 
| 
      
 113 
     | 
    
         
            +
                post "/songs/serialize5/", params: {encrypted_resume_data: encrypted_string}
         
     | 
| 
      
 114 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 115 
     | 
    
         
            +
                assert_equal "#<struct Song id=9>/{\"remember\"=>\"#<OpenStruct id=1>\", \"id\"=>9}/", response.body
         
     | 
| 
      
 116 
     | 
    
         
            +
                # model not found
         
     | 
| 
      
 117 
     | 
    
         
            +
                post "/songs/serialize5/", params: {encrypted_resume_data: "36C61CCE30E6CFDE637DF0DA9257CC49"}
         
     | 
| 
      
 118 
     | 
    
         
            +
                assert_response 404
         
     | 
| 
      
 119 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
              # find model without serialize from params, no serialized stuff passed
         
     | 
| 
      
 122 
     | 
    
         
            +
              # DISCUSS: this could be a different test
         
     | 
| 
      
 123 
     | 
    
         
            +
                post "/songs/serialize6/", params: {id: 1}
         
     | 
| 
      
 124 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 125 
     | 
    
         
            +
                assert_equal "#<struct Song id=\"1\">/#<struct Song id=\"1\">/", response.body
         
     | 
| 
      
 126 
     | 
    
         
            +
                # model not found
         
     | 
| 
      
 127 
     | 
    
         
            +
                post "/songs/serialize6/", params: {id: nil}
         
     | 
| 
      
 128 
     | 
    
         
            +
                assert_response 404
         
     | 
| 
      
 129 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              # {find_process_model: true} set on controller level, for all endpoints.
         
     | 
| 
      
 132 
     | 
    
         
            +
                post "/songs/serialize7/", params: {id: 1}
         
     | 
| 
      
 133 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 134 
     | 
    
         
            +
                assert_equal "#<struct Song id=\"1\">/#<struct Song id=\"1\">/", response.body
         
     | 
| 
      
 135 
     | 
    
         
            +
              # {find_process_model: false} overrides controller setting
         
     | 
| 
      
 136 
     | 
    
         
            +
                post "/songs/serialize72/", params: {id: 1}
         
     | 
| 
      
 137 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 138 
     | 
    
         
            +
                assert_equal "false/false/", response.body
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            # {#insert_copy_from_domain_ctx!} provides {:process_model}
         
     | 
| 
      
 142 
     | 
    
         
            +
                post "/songs/copy_from_domain_ctx", params: {id: 1}
         
     | 
| 
      
 143 
     | 
    
         
            +
                assert_response 200
         
     | 
| 
      
 144 
     | 
    
         
            +
                assert_equal %{#<struct Song id="1">}, response.body
         
     | 
| 
       140 
145 
     | 
    
         
             
              end
         
     | 
| 
       141 
146 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
               
     | 
| 
       143 
     | 
    
         
            -
               
     | 
| 
       144 
     | 
    
         
            -
                post  
     | 
| 
       145 
     | 
    
         
            -
                 
     | 
| 
       146 
     | 
    
         
            -
                assert_equal  
     | 
| 
       147 
     | 
    
         
            -
                 
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
                 
     | 
| 
       153 
     | 
    
         
            -
                assert_equal  
     | 
| 
       154 
     | 
    
         
            -
                 
     | 
| 
      
 147 
     | 
    
         
            +
              test "sign_in" do
         
     | 
| 
      
 148 
     | 
    
         
            +
              # wrong credentials
         
     | 
| 
      
 149 
     | 
    
         
            +
                post "/auth/sign_in", params: {}
         
     | 
| 
      
 150 
     | 
    
         
            +
                assert_response 401
         
     | 
| 
      
 151 
     | 
    
         
            +
                assert_equal "", response.body
         
     | 
| 
      
 152 
     | 
    
         
            +
                assert_nil session[:user_id]
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
              # valid signin
         
     | 
| 
      
 155 
     | 
    
         
            +
                post "/auth/sign_in", params: {username: "yogi@trb.to", password: "secret"}
         
     | 
| 
      
 156 
     | 
    
         
            +
                assert_response 302
         
     | 
| 
      
 157 
     | 
    
         
            +
                # assert_equal "", response.body
         
     | 
| 
      
 158 
     | 
    
         
            +
                assert_equal 1, session[:user_id]
         
     | 
| 
      
 159 
     | 
    
         
            +
                assert_redirected_to "/"
         
     | 
| 
       155 
160 
     | 
    
         
             
              end
         
     | 
| 
       156 
161 
     | 
    
         
             
            end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            # TODO: test 404 with NotFound config
         
     |