diff --git a/test/integration/context_test b/test/integration/context_test deleted file mode 100644 index 85f1b1f..0000000 --- a/test/integration/context_test +++ /dev/null @@ -1,608 +0,0 @@ -# frozen_string_literal: true - -require 'test_helper' - -class HundredCentes - def to_liquid - 100 - end -end - -class CentsDrop < Liquid::Drop - def amount - HundredCentes.new - end - - def non_zero? - true - end -end - -class ContextSensitiveDrop < Liquid::Drop - def test - @context['test'] - end -end - -class Category < Liquid::Drop - attr_accessor :name - - def initialize(name) - @name = name - end - - def to_liquid - CategoryDrop.new(self) - end -end - -class CategoryDrop - attr_accessor :category, :context - def initialize(category) - @category = category - end -end - -class CounterDrop < Liquid::Drop - def count - @count ||= 0 - @count += 1 - end -end - -class ArrayLike - def fetch(index) - end - - def [](index) - @counts ||= [] - @counts[index] ||= 0 - @counts[index] += 1 - end - - def to_liquid - self - end -end - -class ContextTest < Minitest::Test - include Liquid - - def setup - @context = Liquid::Context.new - end - - def test_variables - @context['string'] = 'string' - assert_equal('string', @context['string']) - - @context['num'] = 5 - assert_equal(5, @context['num']) - - @context['time'] = Time.parse('2006-06-06 12:00:00') - assert_equal(Time.parse('2006-06-06 12:00:00'), @context['time']) - - @context['date'] = Date.today - assert_equal(Date.today, @context['date']) - - now = Time.now - @context['datetime'] = now - assert_equal(now, @context['datetime']) - - @context['bool'] = true - assert_equal(true, @context['bool']) - - @context['bool'] = false - assert_equal(false, @context['bool']) - - @context['nil'] = nil - assert_nil(@context['nil']) - assert_nil(@context['nil']) - end - - def test_variables_not_existing - assert_nil(@context['does_not_exist']) - end - - def test_scoping - @context.push - @context.pop - - assert_raises(Liquid::ContextError) do - @context.pop - end - - assert_raises(Liquid::ContextError) do - @context.push - @context.pop - @context.pop - end - end - - def test_length_query - @context['numbers'] = [1, 2, 3, 4] - - assert_equal(4, @context['numbers.size']) - - @context['numbers'] = { 1 => 1, 2 => 2, 3 => 3, 4 => 4 } - - assert_equal(4, @context['numbers.size']) - - @context['numbers'] = { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 'size' => 1000 } - - assert_equal(1000, @context['numbers.size']) - end - - def test_hyphenated_variable - @context['oh-my'] = 'godz' - assert_equal('godz', @context['oh-my']) - end - - def test_add_filter - filter = Module.new do - def hi(output) - output + ' hi!' - end - end - - context = Context.new - context.add_filters(filter) - assert_equal('hi? hi!', context.invoke(:hi, 'hi?')) - - context = Context.new - assert_equal('hi?', context.invoke(:hi, 'hi?')) - - context.add_filters(filter) - assert_equal('hi? hi!', context.invoke(:hi, 'hi?')) - end - - def test_only_intended_filters_make_it_there - filter = Module.new do - def hi(output) - output + ' hi!' - end - end - - context = Context.new - assert_equal("Wookie", context.invoke("hi", "Wookie")) - - context.add_filters(filter) - assert_equal("Wookie hi!", context.invoke("hi", "Wookie")) - end - - def test_add_item_in_outer_scope - @context['test'] = 'test' - @context.push - assert_equal('test', @context['test']) - @context.pop - assert_equal('test', @context['test']) - end - - def test_add_item_in_inner_scope - @context.push - @context['test'] = 'test' - assert_equal('test', @context['test']) - @context.pop - assert_nil(@context['test']) - end - - def test_hierachical_data - @context['hash'] = { "name" => 'tobi' } - assert_equal('tobi', @context['hash.name']) - assert_equal('tobi', @context['hash["name"]']) - end - - def test_keywords - assert_equal(true, @context['true']) - assert_equal(false, @context['false']) - end - - def test_digits - assert_equal(100, @context['100']) - assert_equal(100.00, @context['100.00']) - end - - def test_strings - assert_equal("hello!", @context['"hello!"']) - assert_equal("hello!", @context["'hello!'"]) - end - - def test_merge - @context.merge("test" => "test") - assert_equal('test', @context['test']) - @context.merge("test" => "newvalue", "foo" => "bar") - assert_equal('newvalue', @context['test']) - assert_equal('bar', @context['foo']) - end - - def test_array_notation - @context['test'] = [1, 2, 3, 4, 5] - - assert_equal(1, @context['test[0]']) - assert_equal(2, @context['test[1]']) - assert_equal(3, @context['test[2]']) - assert_equal(4, @context['test[3]']) - assert_equal(5, @context['test[4]']) - end - - def test_recoursive_array_notation - @context['test'] = { 'test' => [1, 2, 3, 4, 5] } - - assert_equal(1, @context['test.test[0]']) - - @context['test'] = [{ 'test' => 'worked' }] - - assert_equal('worked', @context['test[0].test']) - end - - def test_hash_to_array_transition - @context['colors'] = { - 'Blue' => ['003366', '336699', '6699CC', '99CCFF'], - 'Green' => ['003300', '336633', '669966', '99CC99'], - 'Yellow' => ['CC9900', 'FFCC00', 'FFFF99', 'FFFFCC'], - 'Red' => ['660000', '993333', 'CC6666', 'FF9999'], - } - - assert_equal('003366', @context['colors.Blue[0]']) - assert_equal('FF9999', @context['colors.Red[3]']) - end - - def test_try_first - @context['test'] = [1, 2, 3, 4, 5] - - assert_equal(1, @context['test.first']) - assert_equal(5, @context['test.last']) - - @context['test'] = { 'test' => [1, 2, 3, 4, 5] } - - assert_equal(1, @context['test.test.first']) - assert_equal(5, @context['test.test.last']) - - @context['test'] = [1] - assert_equal(1, @context['test.first']) - assert_equal(1, @context['test.last']) - end - - def test_access_hashes_with_hash_notation - @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] } - @context['product'] = { 'variants' => [{ 'title' => 'draft151cm' }, { 'title' => 'element151cm' }] } - - assert_equal(5, @context['products["count"]']) - assert_equal('deepsnow', @context['products["tags"][0]']) - assert_equal('deepsnow', @context['products["tags"].first']) - assert_equal('draft151cm', @context['product["variants"][0]["title"]']) - assert_equal('element151cm', @context['product["variants"][1]["title"]']) - assert_equal('draft151cm', @context['product["variants"][0]["title"]']) - assert_equal('element151cm', @context['product["variants"].last["title"]']) - end - - def test_access_variable_with_hash_notation - @context['foo'] = 'baz' - @context['bar'] = 'foo' - - assert_equal('baz', @context['["foo"]']) - assert_equal('baz', @context['[bar]']) - end - - def test_access_hashes_with_hash_access_variables - @context['var'] = 'tags' - @context['nested'] = { 'var' => 'tags' } - @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] } - - assert_equal('deepsnow', @context['products[var].first']) - assert_equal('freestyle', @context['products[nested.var].last']) - end - - def test_hash_notation_only_for_hash_access - @context['array'] = [1, 2, 3, 4, 5] - @context['hash'] = { 'first' => 'Hello' } - - assert_equal(1, @context['array.first']) - assert_nil(@context['array["first"]']) - assert_equal('Hello', @context['hash["first"]']) - end - - def test_first_can_appear_in_middle_of_callchain - @context['product'] = { 'variants' => [{ 'title' => 'draft151cm' }, { 'title' => 'element151cm' }] } - - assert_equal('draft151cm', @context['product.variants[0].title']) - assert_equal('element151cm', @context['product.variants[1].title']) - assert_equal('draft151cm', @context['product.variants.first.title']) - assert_equal('element151cm', @context['product.variants.last.title']) - end - - def test_cents - @context.merge("cents" => HundredCentes.new) - assert_equal(100, @context['cents']) - end - - def test_nested_cents - @context.merge("cents" => { 'amount' => HundredCentes.new }) - assert_equal(100, @context['cents.amount']) - - @context.merge("cents" => { 'cents' => { 'amount' => HundredCentes.new } }) - assert_equal(100, @context['cents.cents.amount']) - end - - def test_cents_through_drop - @context.merge("cents" => CentsDrop.new) - assert_equal(100, @context['cents.amount']) - end - - def test_nested_cents_through_drop - @context.merge("vars" => { "cents" => CentsDrop.new }) - assert_equal(100, @context['vars.cents.amount']) - end - - def test_drop_methods_with_question_marks - @context.merge("cents" => CentsDrop.new) - assert(@context['cents.non_zero?']) - end - - def test_context_from_within_drop - @context.merge("test" => '123', "vars" => ContextSensitiveDrop.new) - assert_equal('123', @context['vars.test']) - end - - def test_nested_context_from_within_drop - @context.merge("test" => '123', "vars" => { "local" => ContextSensitiveDrop.new }) - assert_equal('123', @context['vars.local.test']) - end - - def test_ranges - @context.merge("test" => '5') - assert_equal((1..5), @context['(1..5)']) - assert_equal((1..5), @context['(1..test)']) - assert_equal((5..5), @context['(test..test)']) - end - - def test_cents_through_drop_nestedly - @context.merge("cents" => { "cents" => CentsDrop.new }) - assert_equal(100, @context['cents.cents.amount']) - - @context.merge("cents" => { "cents" => { "cents" => CentsDrop.new } }) - assert_equal(100, @context['cents.cents.cents.amount']) - end - - def test_drop_with_variable_called_only_once - @context['counter'] = CounterDrop.new - - assert_equal(1, @context['counter.count']) - assert_equal(2, @context['counter.count']) - assert_equal(3, @context['counter.count']) - end - - def test_drop_with_key_called_only_once - @context['counter'] = CounterDrop.new - - assert_equal(1, @context['counter["count"]']) - assert_equal(2, @context['counter["count"]']) - assert_equal(3, @context['counter["count"]']) - end - - def test_proc_as_variable - @context['dynamic'] = proc { 'Hello' } - - assert_equal('Hello', @context['dynamic']) - end - - def test_lambda_as_variable - @context['dynamic'] = proc { 'Hello' } - - assert_equal('Hello', @context['dynamic']) - end - - def test_nested_lambda_as_variable - @context['dynamic'] = { "lambda" => proc { 'Hello' } } - - assert_equal('Hello', @context['dynamic.lambda']) - end - - def test_array_containing_lambda_as_variable - @context['dynamic'] = [1, 2, proc { 'Hello' }, 4, 5] - - assert_equal('Hello', @context['dynamic[2]']) - end - - def test_lambda_is_called_once - @context['callcount'] = proc { - @global ||= 0 - @global += 1 - @global.to_s - } - - assert_equal('1', @context['callcount']) - assert_equal('1', @context['callcount']) - assert_equal('1', @context['callcount']) - - @global = nil - end - - def test_nested_lambda_is_called_once - @context['callcount'] = { "lambda" => proc { - @global ||= 0 - @global += 1 - @global.to_s - } } - - assert_equal('1', @context['callcount.lambda']) - assert_equal('1', @context['callcount.lambda']) - assert_equal('1', @context['callcount.lambda']) - - @global = nil - end - - def test_lambda_in_array_is_called_once - @context['callcount'] = [1, 2, proc { - @global ||= 0 - @global += 1 - @global.to_s - }, 4, 5] - - assert_equal('1', @context['callcount[2]']) - assert_equal('1', @context['callcount[2]']) - assert_equal('1', @context['callcount[2]']) - - @global = nil - end - - def test_access_to_context_from_proc - @context.registers[:magic] = 345392 - - @context['magic'] = proc { @context.registers[:magic] } - - assert_equal(345392, @context['magic']) - end - - def test_to_liquid_and_context_at_first_level - @context['category'] = Category.new("foobar") - assert_kind_of(CategoryDrop, @context['category']) - assert_equal(@context, @context['category'].context) - end - - def test_interrupt_avoids_object_allocations - assert_no_object_allocations do - @context.interrupt? - end - end - - def test_context_initialization_with_a_proc_in_environment - contx = Context.new([test: ->(c) { c['poutine'] }], test: :foo) - - assert(contx) - assert_nil(contx['poutine']) - end - - def test_apply_global_filter - global_filter_proc = ->(output) { "#{output} filtered" } - - context = Context.new - context.global_filter = global_filter_proc - - assert_equal('hi filtered', context.apply_global_filter('hi')) - end - - def test_static_environments_are_read_with_lower_priority_than_environments - context = Context.build( - static_environments: { 'shadowed' => 'static', 'unshadowed' => 'static' }, - environments: { 'shadowed' => 'dynamic' } - ) - - assert_equal('dynamic', context['shadowed']) - assert_equal('static', context['unshadowed']) - end - - def test_apply_global_filter_when_no_global_filter_exist - context = Context.new - assert_equal('hi', context.apply_global_filter('hi')) - end - - def test_new_isolated_subcontext_does_not_inherit_variables - super_context = Context.new - super_context['my_variable'] = 'some value' - subcontext = super_context.new_isolated_subcontext - - assert_nil(subcontext['my_variable']) - end - - def test_new_isolated_subcontext_inherits_static_environment - super_context = Context.build(static_environments: { 'my_environment_value' => 'my value' }) - subcontext = super_context.new_isolated_subcontext - - assert_equal('my value', subcontext['my_environment_value']) - end - - def test_new_isolated_subcontext_inherits_resource_limits - resource_limits = ResourceLimits.new({}) - super_context = Context.new({}, {}, {}, false, resource_limits) - subcontext = super_context.new_isolated_subcontext - assert_equal(resource_limits, subcontext.resource_limits) - end - - def test_new_isolated_subcontext_inherits_exception_renderer - super_context = Context.new - super_context.exception_renderer = ->(_e) { 'my exception message' } - subcontext = super_context.new_isolated_subcontext - assert_equal('my exception message', subcontext.handle_error(Liquid::Error.new)) - end - - def test_new_isolated_subcontext_does_not_inherit_non_static_registers - registers = { - my_register: :my_value, - } - super_context = Context.new({}, {}, StaticRegisters.new(registers)) - super_context.registers[:my_register] = :my_alt_value - subcontext = super_context.new_isolated_subcontext - assert_equal(:my_value, subcontext.registers[:my_register]) - end - - def test_new_isolated_subcontext_inherits_static_registers - super_context = Context.build(registers: { my_register: :my_value }) - subcontext = super_context.new_isolated_subcontext - assert_equal(:my_value, subcontext.registers[:my_register]) - end - - def test_new_isolated_subcontext_registers_do_not_pollute_context - super_context = Context.build(registers: { my_register: :my_value }) - subcontext = super_context.new_isolated_subcontext - subcontext.registers[:my_register] = :my_alt_value - assert_equal(:my_value, super_context.registers[:my_register]) - end - - def test_new_isolated_subcontext_inherits_filters - my_filter = Module.new do - def my_filter(*) - 'my filter result' - end - end - - super_context = Context.new - super_context.add_filters([my_filter]) - subcontext = super_context.new_isolated_subcontext - template = Template.parse('{{ 123 | my_filter }}') - assert_equal('my filter result', template.render(subcontext)) - end - - def test_disables_tag_specified - context = Context.new - context.with_disabled_tags(%w(foo bar)) do - assert_equal true, context.tag_disabled?("foo") - assert_equal true, context.tag_disabled?("bar") - assert_equal false, context.tag_disabled?("unknown") - end - end - - def test_disables_nested_tags - context = Context.new - context.with_disabled_tags(["foo"]) do - context.with_disabled_tags(["foo"]) do - assert_equal true, context.tag_disabled?("foo") - assert_equal false, context.tag_disabled?("bar") - end - context.with_disabled_tags(["bar"]) do - assert_equal true, context.tag_disabled?("foo") - assert_equal true, context.tag_disabled?("bar") - context.with_disabled_tags(["foo"]) do - assert_equal true, context.tag_disabled?("foo") - assert_equal true, context.tag_disabled?("bar") - end - end - assert_equal true, context.tag_disabled?("foo") - assert_equal false, context.tag_disabled?("bar") - end - end - - private - - def assert_no_object_allocations - unless RUBY_ENGINE == 'ruby' - skip("stackprof needed to count object allocations") - end - require 'stackprof' - - profile = StackProf.run(mode: :object) do - yield - end - assert_equal(0, profile[:samples]) - end -end # ContextTest