From e8d450ac6350e00c1f2c4a9f590db54a6b0aa644 Mon Sep 17 00:00:00 2001 From: Nick Sutterer Date: Thu, 27 Jun 2024 16:56:00 +0200 Subject: [PATCH] add the generated tests. --- .../docs/autogenerated/operation_each_test.rb | 7 +- .../operation_model_find_test.rb | 679 ++++++++++++++++++ .../autogenerated/operation_model_test.rb | 36 +- 3 files changed, 715 insertions(+), 7 deletions(-) create mode 100644 test/docs/autogenerated/operation_model_find_test.rb diff --git a/test/docs/autogenerated/operation_each_test.rb b/test/docs/autogenerated/operation_each_test.rb index 33b5adc..4a4c211 100644 --- a/test/docs/autogenerated/operation_each_test.rb +++ b/test/docs/autogenerated/operation_each_test.rb @@ -1,5 +1,6 @@ +# THIS FILE IS AUTOGENERATED FROM trailblazer-macro/test/docs/each_test.rb require "test_helper" -module Autogenerated + # step Macro::Each(:report_templates, key: :report_template) { # step Subprocess(ReportTemplate::Update), input: :input_report_template @@ -54,10 +55,11 @@ class Cover < Trailblazer::Operation def composers_for_each(ctx, model:, **) model.composers end - + #:iterated-value def notify_composers(ctx, index:, item:, **) ctx[:value] = [index, item.full_name] end + #:iterated-value end #~meths def model(ctx, params:, **) @@ -584,4 +586,3 @@ def model(ctx, params:, **) end end -end \ No newline at end of file diff --git a/test/docs/autogenerated/operation_model_find_test.rb b/test/docs/autogenerated/operation_model_find_test.rb new file mode 100644 index 0000000..3a63c17 --- /dev/null +++ b/test/docs/autogenerated/operation_model_find_test.rb @@ -0,0 +1,679 @@ +# THIS FILE IS AUTOGENERATED FROM trailblazer-macro/test/docs/model_find_test.rb +require "test_helper" + +# step Model::Find(Song, find_method: :find_by, column_key: :id, params_key: :id) +# step Model::Find(Song, query: ->(ctx, params:, **) { where(id: params[:id_list]) }) +# # syntax sugaring +# step Model::Find(Song, find_by: :id) +# step Model::Find(Song, :find) +# step Model::Find(query: ->(ctx, params:, **) { Song.where(id: params[:id_list]) }) + +class DocsModelFindTest < Minitest::Spec + Song = Struct.new(:id) do + def self.find_by(id:) + return if id.nil? + new(id) + end + end +end + +# Explicit options +# +# step Model::Find(Song, find_method: :find_method) +# +class Unit_ExplicitOptionsTest < Minitest::Spec + Song = Class.new(DocsModelFindTest::Song) do + def self.find_method(id:) + return if id.nil? + new(id) + end + end + + #:find_method + module Song::Operation + class Update < Trailblazer::Operation + # explicit style: + step Model::Find(Song, find_method: :find_method) # if it's _really_ Song.find_method(...) + + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:find_method end + + #~ctx_to_result + it do + #:find_method-invoke + result = Song::Operation::Update.(params: {id: "1"}, seq: []) + result[:model] #=> # + #:find_method-invoke end + + assert_equal result[:model].inspect, %{#} + end + + it do + result = Song::Operation::Update.(params: {short_id: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end + #~ctx_to_result end +end + +# NOTE: unit test +# +# step Model::Find(Song, find_method: :find_by, column_key: :slug, params_key: :params_slug) +# +class ExplicitColumnKeyAndParamsKeyTest < Minitest::Spec + Song = Class.new(DocsModelFindTest::Song) do + def self.find_by(slug:) + return if slug.nil? + new(slug) + end + end + + module Song::Operation + class Update < Trailblazer::Operation + # explicit style: + step Model::Find(Song, find_method: :find_by, column_key: :slug, params_key: :params_slug) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + + it do + result = Song::Operation::Update.(params: {params_slug: "1"}, seq: []) + ctx[:model] #=> # + + assert_equal result[:model].inspect, %{#} + end + + it "fails" do + result = Song::Operation::Update.(params: {params_slug: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end +end + +# +# step Model::Find(Song, query: ...) +# +class FindByQueryTest < Minitest::Spec + Song = Class.new(DocsModelFindTest::Song) do + def self.where(id:, user:) + return [] if id.nil? + [new([id, user])] + end + end + + #:query + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find( + Song, + query: ->(ctx, id:, current_user:, **) { where(id: id, user: current_user).first } + ) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:query end + + it do + current_user = Module + + result = Song::Operation::Update.(params: {id: "1"}, current_user: current_user, seq: []) + ctx[:model] #=> # + + assert_equal result[:model].inspect, %(#) + end + + it "fails" do + result = Song::Operation::Update.(params: {id: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end +end + +# +# step Model::Find(Song, query: ..., params_key: :slug) +# +class FindByQueryWithParamsKeyTest < Minitest::Spec + Song = Class.new(FindByQueryTest::Song) + + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, + query: ->(ctx, id:, current_user:, **) { where(id: id, user: current_user).first }, + params_key: :slug + ) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + + it do + current_user = Module + + result = Song::Operation::Update.(params: {slug: "1"}, current_user: current_user, seq: []) + ctx[:model] #=> # + + assert_equal result[:model].inspect, %(#) + end + + it "fails" do + result = Song::Operation::Update.(params: {slug: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end +end + +# +# step Model::Find(Song, query: ..., ) do ... end +# +# FIXME: allow Model::Find() do ... end as well as { ... } +class FindByQueryWithParamsBlockTest < Minitest::Spec + Song = Class.new(FindByQueryTest::Song) + + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, query: ->(ctx, id:, current_user:, **) { where(id: id, user: current_user).first }) { |ctx, params:, **| + params[:slug_from_params] + } + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + + it do + current_user = Module + + result = Song::Operation::Update.(params: {slug_from_params: "1"}, current_user: current_user, seq: []) + ctx[:model] #=> # + + assert_equal result[:model].inspect, %(#) + end + + it "fails" do + result = Song::Operation::Update.(params: {slug: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end +end + +# Shorthand +# +# step Model::Find(Song, find_by: :id) +# +class DocsModelFindByColumnTest < Minitest::Spec + Song = Class.new(DocsModelFindTest::Song) + + #:find_by_id + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, find_by: :id) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:find_by_id end + + #~ctx_to_result + it do + #:find_by_id-invoke + result = Song::Operation::Update.(params: {id: "1"}, seq: []) + result[:model] #=> # + #:find_by_id-invoke end + + assert_equal result[:model].inspect, %{#} + end + + it do + result = Song::Operation::Update.(params: {short_id: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end + #~ctx_to_result end + +# TODO: put this test somewhere else + it "doesn't leak anything but {:model} to the outer world" do + result = Song::Operation::Update.(params: {id: "1"}, seq: []) + + assert_equal result.keys.inspect, %([:params, :seq, :model]) + end +end + +# Shorthand +# +# step Model::Find(Song, find_by: :short_id) +# +class DocsModelFindByDifferentColumnTest < Minitest::Spec + Song = Struct.new(:short_id) do + def self.find_by(short_id:) + return if short_id.nil? + new(short_id) + end + end + + #:find_by_column + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, find_by: :short_id) # Song.find_by(short_id: params[:short_id]) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:find_by_column end + + #~ctx_to_result + it do + #:find_by_column-invoke + result = Song::Operation::Update.(params: {short_id: "1f396"}, seq: []) + result[:model] #=> # + #:find_by_column-invoke end + + assert_equal result[:model].inspect, %{#} + end + + it do + result = Song::Operation::Update.(params: {short_id: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end + #~ctx_to_result end +end + +# Shorthand with options +# +# step Model::Find(Song, find_by: :id, params_key: :slug) +# +class DocsModelFindByDifferentParamsKeyTest < Minitest::Spec + Song = Class.new(DocsModelFindTest::Song) + + #:params_key + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, find_by: :id, params_key: :slug) # Song.find_by(id: params[:slug]) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:params_key end + + #~ctx_to_result + it do + #:params_key-invoke + result = Song::Operation::Update.(params: {slug: "1f396"}, seq: []) + result[:model] #=> # + #:params_key-invoke end + + assert_equal result[:model].inspect, %{#} + end + + it do + result = Song::Operation::Update.(params: {slug: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end + #~ctx_to_result end +end + +# Shorthand with different finder method +# +# step Model::Find(Song, find_with: :id) +# +class DocsModelFindWithTest < Minitest::Spec + Song = Struct.new(:id) do + def self.find_with(id:) + return if id.nil? + new(id) + end + end + + #:find_with + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, find_with: :id) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:find_with end + + #~ctx_to_result + it do + #:find_with-invoke + result = Song::Operation::Update.(params: {id: 2}, seq: []) + result[:model] #=> # + #:find_with-invoke end + + assert_equal result[:model].inspect, %{#} + end + + it do + result = Song::Operation::Update.(params: {id: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end + #~ctx_to_result end +end + +# Shorthand with params_key block +# +# step Model::Find(Song, find_by: :id) { } +# +class DocsModelIdFromProcTest < Minitest::Spec + Song = Struct.new(:id) do + def self.find_by(id:) + return if id.nil? + new(id) + end + end + + #:id_from + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, find_by: :id) { |ctx, params:, **| + params[:song] && params[:song][:id] + } + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:id_from end + + #~ctx_to_result + it do + #:id_from-invoke + result = Song::Operation::Update.(params: {song: {id: "1f396"}}, seq: []) + result[:model] #=> # + #:id_from-invoke end + + assert_equal result[:model].inspect, %{#} + assert_equal result[:seq].inspect, %([:validate, :save]) + end + + it do + result = Song::Operation::Update.(params: {}, seq: []) + + assert_equal result[:model].inspect, %{nil} + assert_equal result[:seq].inspect, %([]) + end + #~ctx_to_result end +end + +# Positional +# +# step Model::Find(Song, :find) +# +class DocsModelFindPositionaTest < Minitest::Spec + Song = Struct.new(:id) do + def self.find(id) + return if id.nil? + new(id) + end + end + + #:find + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, :find) # Song.find(id) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:find end + + #~ctx_to_result + it do + #:find-ok + result = Song::Operation::Update.({params: {id: 1}, seq: []}) + result[:model] #=> # + #:find-ok end + + assert_equal result[:model].inspect, %{#} + end + #~ctx_to_result end +end + +# Positional with params_key block +# +# step Model::Find(Song, :find) { ... } +# +class DocsModelFindPositionalWithParamsBlockTest < Minitest::Spec + Song = Class.new(DocsModelFindPositionaTest::Song) + + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, :find) { |ctx, params:, **| params[:params_slug] } + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + + #~ctx_to_result + it do + result = Song::Operation::Update.({params: {params_slug: 1}, seq: []}) + result[:model] #=> # + + assert_equal result[:model].inspect, %{#} + end + #~ctx_to_result end + + it "fails" do + result = Song::Operation::Update.(params: {params_slug: nil}, seq: []) + assert_equal result[:model].inspect, %{nil} + end +end + +# Positional with #[] +# +# step Model::Find(Song, :[]) +# +class DocsModelAccessorTest < Minitest::Spec + Song = Struct.new(:id, :title) do + def self.[](id) + id.nil? ? nil : new(id+99) + end + end + + #:show + module Song::Operation + class Update < Trailblazer::Operation + step Model::Find(Song, :[]) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:show end + + #~ctx_to_result + it do + #:show-ok + result = Trailblazer::Developer.wtf?(Song::Operation::Update, [{params: {id: 1}, seq: []}]) + result[:model] #=> # + #:show-ok end + + assert_equal result[:model].inspect, %{#} + end + #~ctx_to_result end +end + +# class DocsModelBlockTest < Minitest::Spec +# Song = Class.new(DocsModelIdFromProcTest::Song) + +# #:block +# module Song::Operation +# class Update < Trailblazer::Operation +# step Model() do |ctx, params:, **| + +# end +# step :validate +# step :save +# #~meths +# include T.def_steps(:validate, :save) +# #~meths end +# end +# end +# #:block end + +# #~ctx_to_result +# it do +# #:block-invoke +# result = Song::Operation::Update.(params: {song: {id: "1f396"}}, seq: []) +# result[:model] #=> # +# #:block-invoke end + +# assert_equal result[:model].inspect, %{#} +# assert_equal result[:seq].inspect, %([:validate, :save]) +# end + +# it do +# result = Song::Operation::Update.(params: {}, seq: []) + +# assert_equal result[:model].inspect, %{nil} +# assert_equal result[:seq].inspect, %([]) +# end +# #~ctx_to_result end +# end + +# new +# +# +# +class DocsModelNewTest < Minitest::Spec + Song = Class.new(DocsModelFindTest::Song) + + #:new + module Song::Operation + class Create < Trailblazer::Operation + step Model::Build(Song, :new) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:new end + + #~ctx_to_result + it do + #:new-invoke + result = Song::Operation::Create.(params: {}, seq: []) + result[:model] #=> # + #:new-invoke end + + assert_equal result[:model].inspect, %{#} + end + #~ctx_to_result end +end + +# build +# +# +# +class DocsModelBuildTest < Minitest::Spec + Song = Struct.new(:id) + Song.singleton_class.alias_method :build, :new + + #:build + module Song::Operation + class Create < Trailblazer::Operation + step Model::Build(Song, :build) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + #:build end + + #~ctx_to_result + it do + #:build-invoke + result = Song::Operation::Create.(params: {}, seq: []) + result[:model] #=> # + #:build-invoke end + + assert_equal result[:model].inspect, %{#} + end + #~ctx_to_result end +end + +# Explicit terminus +# +# step Model::Find(Song, find_by: :id, not_found_terminus: true) +# +class ModelFind404TerminusTest < Minitest::Spec + Song = Struct.new(:id) do + def self.find_by(id:) + return if id.nil? + return if id == 2 + new(id) + end + end + + #:not-found + class Song + module Activity + class Update < Trailblazer::Operation + step Model::Find(Song, find_by: :id, not_found_terminus: true) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + end + #:not-found end + + it "terminates on {not_found} for missing ID in {params}" do + assert_invoke Song::Operation::Update, params: {id: 1}, + seq: "[:validate, :save]", expected_ctx_variables: {model: Song.find_by(id: 1)} + assert_invoke Song::Operation::Update, params: {id: nil}, terminus: :not_found + + # no {params} at all. + assert_invoke Song::Operation::Update, terminus: :not_found + + # no model matching ID. + # NOTE: we assign {model: nil} - do we want that? + assert_invoke Song::Operation::Update, params: {id: 2}, terminus: :not_found, expected_ctx_variables: {model: nil} + + #:not-found-invoke + result = Trailblazer::Operation::TaskWrap.invoke(Song::Operation::Update, [{params: {id: nil}},{}]) + result.success? # => false + #:not-found-invoke end + end +end diff --git a/test/docs/autogenerated/operation_model_test.rb b/test/docs/autogenerated/operation_model_test.rb index 08c7a9c..ef71865 100644 --- a/test/docs/autogenerated/operation_model_test.rb +++ b/test/docs/autogenerated/operation_model_test.rb @@ -1,5 +1,6 @@ +# THIS FILE IS AUTOGENERATED FROM trailblazer-macro/test/docs/model_test.rb require "test_helper" -module Autogenerated + class DocsModelTest < Minitest::Spec Song = Struct.new(:id, :title) do def self.find_by(args) @@ -77,7 +78,6 @@ class Update < Trailblazer::Operation result.success? # => false #:update-fail end - assert_equal result[:model].inspect, %{nil} assert_equal result.event.to_h[:semantic], :failure end @@ -233,9 +233,9 @@ class Create < Trailblazer::Operation result = Create.(my_id: 1) #:in-call end =end + end end end -end class Model404TerminusTest < Minitest::Spec Song = Class.new(DocsModelTest::Song) @@ -263,4 +263,32 @@ class Update < Trailblazer::Operation #:not_found end end end -end \ No newline at end of file + +class Model404TerminusTest < Minitest::Spec + Song = Class.new(DocsModelTest::Song) + #:update-with-not-found-end + class Song + module Activity + class Update < Trailblazer::Operation + step Model(Song, :find_by, not_found_terminus: true) + step :validate + step :save + #~meths + include T.def_steps(:validate, :save) + #~meths end + end + end + end + #:update-with-not-found-end end + + it do + assert_invoke Song::Operation::Update, params: {id: 1}, + seq: "[:validate, :save]", expected_ctx_variables: {model: Song.find_by(id: 1)} + assert_invoke Song::Operation::Update, params: {id: nil}, terminus: :not_found + + #:not_found + result = Trailblazer::Operation::TaskWrap.invoke(Song::Operation::Update, [{params: {id: nil}},{}]) + result.success? # => false + #:not_found end + end +end