spec/unit/yaks/runner_spec.rb in yaks-0.9.0 vs spec/unit/yaks/runner_spec.rb in yaks-0.10.0

- old
+ new

@@ -6,24 +6,30 @@ let(:object) { Object.new } let(:config) { Yaks.new } let(:options) { {} } shared_examples 'high-level runner test' do - let(:options) { {env: {foo: "from_env"}} } + let(:object) { 7 } + + let(:options) { + { + env: {foo: "from_env"}, + hooks: [[:after, :step2, :upcase, ->(x, _env) { x.upcase }]] + } + } + let(:runner) { Class.new(described_class) do def steps [ [:step1, proc { |x| x + 35 }], [:step2, proc { |x, env| "#{env[:foo]}[#{x} #{x}]" }] ] end end.new(object: object, config: config, options: options) } - let(:object) { 7 } - it 'should go through all the steps' do - expect(runner.call).to eql "from_env[42 42]" + expect(runner.call).to eql "FROM_ENV[42 42]" end end describe '#call' do include_examples 'high-level runner test' @@ -31,17 +37,88 @@ describe '#process' do include_examples 'high-level runner test' end + describe '#format' do + let(:object) { + Yaks::Resource.new(attributes: {ronny: :jonny}) + } + + let(:options) { + { + env: { + 'api.key_prefix' => 'pre_' + }, + hooks: [ + [:before, + :format, + :add_kristel, + ->(resource, _env) { + resource.merge_attributes(kristel: :christa) + }, + ], + [:after, + :primitivize, + :add_prefix, + ->(hsh, env) { + hsh.each_with_object({}) do |(k, v), h| + h[env['api.key_prefix'] + k] = v + end + } + ] + ] + } + } + + it 'should run the formatter and primitivizer plus hooks' do + expect(runner.format).to eql("pre_kristel" => "christa", "pre_ronny" => "jonny") + end + end + + describe '#read' do + let(:object) { + '{"pre_ronny": "jonny"}' + } + + let(:options) { + { + env: { + 'api.key_prefix' => 'pre_' + }, + hooks: [ + [:after, + :read, + :add_kristel, + ->(resource, _env) { + resource.merge_attributes(kristel: 'christa') + }, + ], + [:before, + :parse, + :strip_prefix, + ->(json, env) { + json.gsub(env['api.key_prefix'], '') + } + ] + ] + } + } + + it 'should run the parser and reader plus hooks' do + expect(runner.read) + .to eql Yaks::Resource.new(attributes: {ronny: "jonny", kristel: "christa"}) + end + end + describe '#context' do it 'should contain the policy, env, and an empty mapper_stack' do expect(runner.context).to eql(policy: config.policy, env: {}, mapper_stack: []) end context 'with an item mapper' do - let(:options) { { item_mapper: :foo } } + let(:options) { {item_mapper: :foo} } it 'should contain the item_mapper' do expect(runner.context).to eql(policy: config.policy, env: {}, mapper_stack: [], item_mapper: :foo) end end @@ -53,39 +130,39 @@ default_format :collection_json end end let(:rack_env) { - { 'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json' } + {'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json'} } it 'should fall back to the default when no HTTP_ACCEPT key is present' do - runner = described_class.new(object: nil, config: config, options: { env: {} }) + runner = described_class.new(object: nil, config: config, options: {env: {}}) expect(runner.format_class).to equal Yaks::Format::CollectionJson end it 'should detect format based on accept header' do - rack_env = { 'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json' } - runner = described_class.new(object: nil, config: config, options: { env: rack_env }) + rack_env = {'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json'} + runner = described_class.new(object: nil, config: config, options: {env: rack_env}) expect(runner.format_class).to equal Yaks::Format::JsonAPI end it 'should know to pick the best match' do - rack_env = { 'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json;q=0.7' } - runner = described_class.new(object: nil, config: config, options: { env: rack_env }) + rack_env = {'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json;q=0.7'} + runner = described_class.new(object: nil, config: config, options: {env: rack_env}) expect(runner.format_class).to equal Yaks::Format::Hal end it 'should pick the one given in the options if no header matches' do - rack_env = { 'HTTP_ACCEPT' => 'text/xml, application/json' } - runner = described_class.new(object: nil, config: config, options: { format: :hal, env: rack_env }) + rack_env = {'HTTP_ACCEPT' => 'text/xml, application/json'} + runner = described_class.new(object: nil, config: config, options: {format: :hal, env: rack_env}) expect(runner.format_class).to equal Yaks::Format::Hal end it 'should fall back to the default when no mime type is recognized' do - rack_env = { 'HTTP_ACCEPT' => 'text/xml, application/json' } - runner = described_class.new(object: nil, config: config, options: { env: rack_env }) + rack_env = {'HTTP_ACCEPT' => 'text/xml, application/json'} + runner = described_class.new(object: nil, config: config, options: {env: rack_env}) expect(runner.format_class).to equal Yaks::Format::CollectionJson end end describe '#format_name' do @@ -97,11 +174,11 @@ context 'with a default format specified' do let(:config) { Yaks.new { default_format :collection_json } } context 'with a format in the options' do - let(:options) { { format: :json_api } } + let(:options) { {format: :json_api} } it 'should give preference to that one' do expect(runner.format_name).to eql :json_api end end @@ -115,11 +192,11 @@ describe '#formatter' do let(:config) { Yaks.new do default_format :json_api - format_options :json_api, {format_option: [:foo]} + format_options :json_api, format_option: [:foo] end } let(:formatter) { runner.formatter } @@ -133,11 +210,11 @@ end end describe '#env' do describe 'when env is set in the options' do - let(:options) { { env: 123 } } + let(:options) { {env: 123} } it 'returns the env passed in' do expect(runner.env).to be 123 end end @@ -150,11 +227,11 @@ end describe '#mapper' do context 'with an explicit mapper in the options' do let(:mapper_class) { Class.new(Yaks::Mapper) } - let(:options) { { mapper: mapper_class } } + let(:options) { {mapper: mapper_class} } it 'should take the mapper from options' do expect(runner.mapper).to be_a mapper_class end end @@ -186,16 +263,16 @@ expect(runner.serializer.call('42', {})).to eql 'serialized 42' end end it 'should fall back to the policy' do - expect(runner.serializer.call([1,2,3], {})).to eql "[\n 1,\n 2,\n 3\n]" + expect(runner.serializer.call([1, 2, 3], {})).to eql "[\n 1,\n 2,\n 3\n]" end end describe '#steps' do - let(:options) {{ mapper: Yaks::Mapper }} + let(:options) {{mapper: Yaks::Mapper}} it 'should have all four steps' do expect(runner.steps).to eql [ [ :map, runner.mapper ], [ :format, runner.formatter ], @@ -233,11 +310,11 @@ it 'should contain the hooks from the config' do expect(runner.hooks).to eql [[:after, :map, :this_happens_after_map, nil]] end context 'with extra blocks in the options' do - let(:options) { { hooks: [[:foo]] } } + let(:options) { {hooks: [[:foo]]} } it 'should combine the hooks' do expect(runner.hooks).to eql [[:after, :map, :this_happens_after_map, nil], [:foo]] end end @@ -245,32 +322,39 @@ describe '#map' do let(:mapper_class) do Struct.new(:options) do include Yaks::FP::Callable - def call(obj, env) "mapped[#{obj}]" end + def call(obj, _env) + "mapped[#{obj}]" + end end end - let(:options) { { mapper: mapper_class } } + let(:options) { + { + mapper: mapper_class, + env: {'api.prefix' => 'pre_'} + } + } + let(:object) { "foo" } it 'should only run the mapper' do expect(runner.map).to eql "mapped[foo]" end context 'with a hook on the :map step' do let(:config) do Yaks.new do around(:map) do |res, env, &block| - "around[#{block.call(res, env)}]" + "#{env['api.prefix']}around[#{block.call(res, env)}]" end end end - it 'should invoke the hook as well' do - expect(runner.map).to eql "around[mapped[foo]]" + it 'should invoke the hook and pass in the env' do + expect(runner.map).to eql "pre_around[mapped[foo]]" end end end - end