shopify_liquid_test_helper 0.1.1 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84284c898f11a3cdb722b02acd0ec877884b31a05fa0898ab5e7a928e6f20cae
4
- data.tar.gz: c998c86408b453d132537b191f94faa96b5cd7f98459e948ccb8a41871fa4a5c
3
+ metadata.gz: 0ddfc04095edd38e1d15ea3077d4023f1e45c1527c8d8296180f6fe31ecd69f2
4
+ data.tar.gz: 8394cc4880370163215a194c95cc256acc7bc20f19dedf5ed4623af839f53bc1
5
5
  SHA512:
6
- metadata.gz: 125d273dc6e140eadd9cc06d0cf788948d3ec1cc66089cfc7c3b27da865b0d4d3a83c388a0db69b3634067aeab525cc0e3e21a6cbb181d16bea0c01999935769
7
- data.tar.gz: 6716beb9dfa4bfb3c6dc44ecf7bec268642bab035adfb595478e12eea4611bbbf4c2afcbd536976907d78849b7e743175d3c70a9af785dda59285b37919c4a38
6
+ metadata.gz: 63bab7c6a918c254bacbfa8343a1383b3f2ce73c495016f26ab82ce31533766a02e1cd54a33ec9d9d83658c022e5809f5cb68c4786599fec7f3a3812c78c2240
7
+ data.tar.gz: 49711d147d87237160f6fef93b64297ec8a18a9632ae3441944e6cbd553bb539eb03118cd14e51cea122b00ea8c078ada47fa2d64fca4b67138f26333b92ecd3
data/README.md CHANGED
@@ -7,7 +7,6 @@ ShopifyLiquidTestHelper is a Ruby gem designed to assist in testing Shopify Liqu
7
7
  | Tag | Status |
8
8
  | --- | ------ |
9
9
  | `render` | ✅ |
10
- | `capture` | ✅ |
11
10
 
12
11
 
13
12
  ## Installation
@@ -138,6 +137,61 @@ end
138
137
 
139
138
  ShopifyLiquidTestHelper will automatically load the `product_card` snippet from the `snippets` directory when you use the `render` tag in your Liquid template.
140
139
 
140
+
141
+ ### Mocking render with `allow` in RSpec
142
+
143
+ ShopifyLiquidTestHelper provides functionality to mock Liquid snippets using RSpec's `allow` method. This is particularly useful when testing templates that depend on other snippets.
144
+
145
+ Here's a simple example of how to use `allow` for mocking:
146
+
147
+ ```liquid
148
+ <!-- snippets/product.liquid -->
149
+ <div class="product">
150
+ <h1>{{ product.title }}</h1>
151
+ <div class="price">
152
+ {% render 'product_price' %}
153
+ </div>
154
+ <div class="description">
155
+ {{ product.description }}
156
+ </div>
157
+ {% if product.available %}
158
+ <button type="button" class="add-to-cart">Add to Cart</button>
159
+ {% else %}
160
+ <p>Sold Out</p>
161
+ {% endif %}
162
+ </div>
163
+ ```
164
+
165
+
166
+ ```ruby
167
+ RSpec.describe 'ProductTemplate' do
168
+ let(:template) { ShopifyLiquidTestHelper.parse_template('snippets/product.liquid') }
169
+ let(:product) { { 'title' => 'Test Product', 'price' => 1000 } }
170
+
171
+ before do
172
+ # Mock the 'product_price' snippet to return a formatted price
173
+ allow(ShopifyLiquidTestHelper).to receive(:get_snippet).with('product_price').and_return('{{ product.price | money }}')
174
+ end
175
+
176
+ it 'renders the product title and price' do
177
+ rendered = template.render('product' => product)
178
+ expect(rendered).to include('Test Product')
179
+ expect(rendered).to include('$10.00')
180
+ end
181
+
182
+ context 'when the product is on sale' do
183
+ before do
184
+ # Override the mock for a specific test
185
+ allow(ShopifyLiquidTestHelper).to receive(:get_snippet).with('product_price').and_return('On Sale: {{ product.price | money }}')
186
+ end
187
+
188
+ it 'shows the sale price' do
189
+ rendered = template.render('product' => product)
190
+ expect(rendered).to include('On Sale: $10.00')
191
+ end
192
+ end
193
+ end
194
+
141
195
  ### Customizing the Snippets Directory
142
196
 
143
197
  If your snippets are located in a different directory, you can specify the path when initializing ShopifyLiquidTestHelper:
@@ -216,7 +270,7 @@ This gem allows you to test your Shopify Liquid templates thoroughly, ensuring t
216
270
 
217
271
  ## Contributing
218
272
 
219
- Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/shopify_liquid_test_helper.
273
+ Bug reports and pull requests are welcome on GitHub at https://github.com/giwa/shopify_liquid_test_helper.
220
274
 
221
275
  ## License
222
276
 
@@ -0,0 +1 @@
1
+ require 'shopify_liquid_test_helper/rspec_configuration'
@@ -0,0 +1,40 @@
1
+ module ShopifyLiquidTestHelper
2
+ module Matchers
3
+ extend RSpec::Matchers::DSL
4
+
5
+ matcher :render_liquid_template do |expected|
6
+ match do |template|
7
+ @rendered = if template.is_a?(String)
8
+ Liquid::Template.parse(template).render(@assigns)
9
+ elsif template.is_a?(Liquid::Template)
10
+ template.render(@assigns)
11
+ else
12
+ raise ArgumentError, "Template must be a String or Liquid::Template object"
13
+ end
14
+ @rendered == expected
15
+ end
16
+
17
+ chain :with do |assigns|
18
+ @assigns = assigns
19
+ end
20
+
21
+ failure_message do |template|
22
+ "expected that Liquid template \"#{template}\" " \
23
+ "would render as \"#{expected}\", but got \"#{@rendered}\""
24
+ end
25
+
26
+ failure_message_when_negated do |template|
27
+ "expected that Liquid template \"#{template}\" " \
28
+ "would not render as \"#{expected}\", but it did"
29
+ end
30
+
31
+ description do
32
+ "render Liquid template to \"#{expected}\""
33
+ end
34
+ end
35
+
36
+ def expect_liquid_template_result(template, expected, assigns = {})
37
+ expect(template).to render_liquid_template(expected).with(assigns)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ require 'rspec'
2
+ require 'shopify_liquid_test_helper/test_helpers'
3
+ require 'shopify_liquid_test_helper/matchers'
4
+
5
+ RSpec.configure do |config|
6
+ config.include ShopifyLiquidTestHelper::Matchers
7
+ config.include ShopifyLiquidTestHelper::TestHelpers
8
+
9
+ config.before(:all) do
10
+ ShopifyLiquidTestHelper.register_custom_tags
11
+ ShopifyLiquidTestHelper.reset_snippets
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module ShopifyLiquidTestHelper
2
+ module TestHelpers
3
+ def parse_liquid(template)
4
+ Liquid::Template.parse(template)
5
+ end
6
+
7
+ def parse_liquid_file(template_name)
8
+ Liquid::Template.parse(File.read(template_name))
9
+ end
10
+
11
+ def render_liquid(template, assigns = {})
12
+ case template
13
+ when String
14
+ parse_liquid(template).render(assigns)
15
+ when Liquid::Template
16
+ template.render(assigns)
17
+ else
18
+ raise ArgumentError, "Template must be a String or Liquid::Template object"
19
+ end
20
+ end
21
+
22
+ def register_snippet(name, content)
23
+ ShopifyLiquidTestHelper.register_snippet(name, content)
24
+ end
25
+ end
26
+ end
@@ -1,19 +1,18 @@
1
+ require 'shopify_liquid_simulator'
1
2
  require 'liquid'
2
- require 'shopify_liquid_test_helper/render_tag'
3
- require 'shopify_liquid_test_helper/capture_tag'
4
3
 
5
4
  module ShopifyLiquidTestHelper
6
5
  class << self
7
6
  attr_accessor :snippets_dir
7
+ attr_writer :snippet_provider
8
8
 
9
- def parse_template(template_name)
9
+ def parse_liquid_file(template_name)
10
10
  Liquid::Template.parse(File.read(template_name))
11
11
  end
12
12
 
13
13
  def register_custom_tags
14
- # TODO: separate tag implementations
15
- Liquid::Template.register_tag('render', RenderTag)
16
- Liquid::Template.register_tag('capture', CaptureTag)
14
+ ShopifyLiquidSimulator.register_tags
15
+ ShopifyLiquidSimulator::Render.snippet_provider = method(:get_snippet)
17
16
  end
18
17
 
19
18
  def register_snippet(name, content)
@@ -21,13 +20,25 @@ module ShopifyLiquidTestHelper
21
20
  end
22
21
 
23
22
  def get_snippet(name)
24
- snippets[name] || load_snippet(name)
23
+ snippet_provider.call(name)
24
+ end
25
+
26
+ def reset_snippets
27
+ Thread.current[:snippets] = {}
28
+ end
29
+
30
+ def snippet_provider
31
+ @snippet_provider ||= method(:default_snippet_provider)
25
32
  end
26
33
 
27
34
  private
28
35
 
29
36
  def snippets
30
- @snippets ||= {}
37
+ Thread.current[:snippets] ||= {}
38
+ end
39
+
40
+ def default_snippet_provider(name)
41
+ snippets[name] || load_snippet(name)
31
42
  end
32
43
 
33
44
  def load_snippet(name)
@@ -42,6 +53,7 @@ module ShopifyLiquidTestHelper
42
53
  end
43
54
  end
44
55
 
45
- # デフォルトのsnippetsディレクトリを設定
46
56
  @snippets_dir = 'snippets'
47
- end
57
+ end
58
+
59
+ require 'shopify_liquid_test_helper/integration' if defined?(RSpec)
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe ShopifyLiquidTestHelper::RenderTag do
3
+ RSpec.describe ShopifyLiquidTestHelper do
4
4
  before(:all) do
5
- ShopifyLiquidTestHelper.register_custom_tags
6
5
  ShopifyLiquidTestHelper.register_snippet('simple', 'Hello, {{ name }}!')
7
6
  ShopifyLiquidTestHelper.register_snippet('for_loop', 'Item: {{ item }}')
8
7
  ShopifyLiquidTestHelper.register_snippet('with_object', 'Name: {{ object.name }}')
@@ -15,25 +14,25 @@ RSpec.describe ShopifyLiquidTestHelper::RenderTag do
15
14
  describe 'render tag' do
16
15
  it 'renders a simple snippet' do
17
16
  template = "{% render 'simple', name: 'World' %}"
18
- expect(render(template)).to eq 'Hello, World!'
17
+ expect(template).to render_liquid_template('Hello, World!')
19
18
  end
20
19
 
21
20
  it 'renders a snippet with a for loop' do
22
21
  template = "{% render 'for_loop' for items as item %}"
23
22
  assigns = { 'items' => %w[A B C] }
24
- expect(render(template, assigns)).to eq 'Item: AItem: BItem: C'
23
+ expect(template).to render_liquid_template('Item: AItem: BItem: C').with(assigns)
25
24
  end
26
25
 
27
26
  it 'renders a snippet with an object' do
28
27
  template = "{% render 'with_object' with user as object %}"
29
28
  assigns = { 'user' => { 'name' => 'John' } }
30
- expect(render(template, assigns)).to eq 'Name: John'
29
+ expect(template).to render_liquid_template('Name: John').with(assigns)
31
30
  end
32
31
 
33
32
  it 'does not allow access to variables outside the snippet' do
34
33
  ShopifyLiquidTestHelper.register_snippet('isolated', '{{ outside_var }}')
35
34
  template = "{% assign outside_var = 'Outside' %}{% render 'isolated' %}"
36
- expect(render(template)).to eq ''
35
+ expect(template).to render_liquid_template('').with('outside_var' => 'Outside')
37
36
  end
38
37
 
39
38
  it 'provides all forloop variables in for loop rendering' do
@@ -41,35 +40,18 @@ RSpec.describe ShopifyLiquidTestHelper::RenderTag do
41
40
  '{{ forloop.index }},{{ forloop.index0 }},{{ forloop.first }},{{ forloop.last }},{{ forloop.length }},{{ forloop.rindex }},{{ forloop.rindex0 }}|')
42
41
  template = "{% render 'forloop_vars' for items as item %}"
43
42
  assigns = { 'items' => %w[A B C] }
44
- expect(render(template, assigns)).to eq '1,0,true,false,3,3,2|2,1,false,false,3,2,1|3,2,false,true,3,1,0|'
43
+ expect(template).to render_liquid_template('1,0,true,false,3,3,2|2,1,false,false,3,2,1|3,2,false,true,3,1,0|').with(assigns)
45
44
  end
46
45
 
47
46
  it 'allows using an alias for the rendered variable' do
48
47
  template = "{% render 'simple' with 'Alias' as name %}"
49
- expect(render(template)).to eq 'Hello, Alias!'
48
+ expect(template).to render_liquid_template('Hello, Alias!')
50
49
  end
51
50
 
52
51
  it 'does not pollute the outer scope' do
53
52
  template = "{% render 'simple' with 'Inner' as name %}{{ name }}"
54
53
  assigns = { 'name' => 'Outer' }
55
- expect(render(template, assigns)).to eq 'Hello, Inner!Outer'
56
- end
57
- end
58
-
59
- describe 'capture tag' do
60
- it 'captures content into a variable' do
61
- template = "{% capture my_variable %}Hello, Capture!{% endcapture %}{{ my_variable }}"
62
- expect(render(template)).to eq 'Hello, Capture!'
63
- end
64
-
65
- it 'captures complex content with Liquid logic' do
66
- template = "{% capture complex %}{% for i in (1..3) %}{{ i }}{% endfor %}{% endcapture %}{{ complex }}"
67
- expect(render(template)).to eq '123'
68
- end
69
-
70
- it 'overwrites previously captured variables' do
71
- template = "{% capture var %}First{% endcapture %}{% capture var %}Second{% endcapture %}{{ var }}"
72
- expect(render(template)).to eq 'Second'
54
+ expect(template).to render_liquid_template('Hello, Inner!Outer').with(assigns)
73
55
  end
74
56
  end
75
57
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'shopify_liquid_test_helper'
2
2
 
3
- RSpec.configure do |config|
4
- config.before(:all) do
5
- ShopifyLiquidTestHelper.register_custom_tags
6
- end
7
- end
3
+ # RSpec.configure do |config|
4
+ # config.before(:all) do
5
+ # ShopifyLiquidTestHelper.register_custom_tags
6
+ # end
7
+ # end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_liquid_test_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Takagiwa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-24 00:00:00.000000000 Z
11
+ date: 2024-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: shopify_liquid_simulator
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -63,11 +77,13 @@ files:
63
77
  - README.md
64
78
  - Rakefile
65
79
  - lib/shopify_liquid_test_helper.rb
66
- - lib/shopify_liquid_test_helper/capture_tag.rb
67
- - lib/shopify_liquid_test_helper/render_tag.rb
68
- - spec/render_tag_spec.rb
80
+ - lib/shopify_liquid_test_helper/integration.rb
81
+ - lib/shopify_liquid_test_helper/matchers.rb
82
+ - lib/shopify_liquid_test_helper/rspec_configuration.rb
83
+ - lib/shopify_liquid_test_helper/test_helpers.rb
84
+ - spec/shopify_liquid_test_helper_spec.rb
69
85
  - spec/spec_helper.rb
70
- homepage: https://github.com/yourusername/shopify_liquid_test_helper
86
+ homepage: https://github.com/giwa/shopify_liquid_test_helper
71
87
  licenses:
72
88
  - MIT
73
89
  metadata: {}
@@ -1,14 +0,0 @@
1
- module ShopifyLiquidTestHelper
2
- class CaptureTag < Liquid::Block
3
- def initialize(tag_name, markup, tokens)
4
- super
5
- @variable_name = markup.strip
6
- end
7
-
8
- def render(context)
9
- result = super
10
- context.scopes.last[@variable_name] = result
11
- ''
12
- end
13
- end
14
- end
@@ -1,107 +0,0 @@
1
- module ShopifyLiquidTestHelper
2
- class RenderTag < Liquid::Tag
3
- SYNTAX = /(#{Liquid::QuotedFragment}+)(\s+(?:with|for)\s+(#{Liquid::QuotedFragment}+))?(\s+as\s+(#{Liquid::QuotedFragment}+))?/o
4
-
5
- def initialize(tag_name, markup, tokens)
6
- super
7
- parse_markup(markup)
8
- @params = extract_params(markup)
9
- end
10
-
11
- def render(context)
12
- snippet_name = resolve_snippet_name(context)
13
- snippet = fetch_snippet(snippet_name)
14
-
15
- temp_context = create_isolated_context(context)
16
- variable = resolve_variable(context)
17
-
18
- if @for_loop
19
- render_for_loop(snippet, variable, temp_context)
20
- else
21
- render_with_variable(snippet, variable, temp_context)
22
- end
23
- end
24
-
25
- private
26
-
27
- def parse_markup(markup)
28
- unless markup =~ SYNTAX
29
- raise Liquid::SyntaxError,
30
- "Syntax Error in 'render' - Valid syntax: render 'snippet' [with object|for array] [as alias]"
31
- end
32
-
33
- @snippet_name = ::Regexp.last_match(1)
34
- @variable_name = ::Regexp.last_match(3)
35
- @alias = ::Regexp.last_match(5)
36
- @for_loop = ::Regexp.last_match(2) =~ /\s+for\s+/
37
- end
38
-
39
- def extract_params(markup)
40
- params = {}
41
- markup.scan(Liquid::TagAttributes) { |key, value| params[key] = value }
42
- params
43
- end
44
-
45
- def resolve_snippet_name(context)
46
- snippet_name = context[@snippet_name] || @snippet_name
47
- snippet_name.gsub(/['"]/, '')
48
- end
49
-
50
- def fetch_snippet(snippet_name)
51
- snippet = ShopifyLiquidTestHelper.get_snippet(snippet_name)
52
- raise Liquid::SyntaxError, "Unknown snippet '#{snippet_name}'" unless snippet
53
-
54
- snippet
55
- end
56
-
57
- def resolve_variable(context)
58
- @variable_name ? context[@variable_name] : nil
59
- end
60
-
61
- def render_for_loop(snippet, array, context)
62
- return unless array.respond_to?(:each)
63
-
64
- array.each_with_index.map do |item, index|
65
- item_context = create_item_context(context, item, index, array.size)
66
- Liquid::Template.parse(snippet).render(item_context)
67
- end.join
68
- end
69
-
70
- def create_item_context(context, item, index, array_size)
71
- item_context = context.new_isolated_subcontext
72
- item_context[@alias || 'item'] = item
73
-
74
- item_context['forloop'] = {
75
- 'first' => index.zero?,
76
- 'index' => index + 1,
77
- 'index0' => index,
78
- 'last' => index == array_size - 1,
79
- 'length' => array_size,
80
- 'rindex' => array_size - index,
81
- 'rindex0' => array_size - index - 1
82
- }
83
-
84
- @params.each do |key, value|
85
- item_context[key] = context[value] || context.evaluate(value) || value
86
- end
87
-
88
- item_context
89
- end
90
-
91
- def render_with_variable(snippet, variable, context)
92
- context[@alias || 'object'] = variable if @variable_name
93
-
94
- @params.each do |key, value|
95
- context[key] = context[value] || context.evaluate(value) || value
96
- end
97
-
98
- Liquid::Template.parse(snippet).render(context)
99
- end
100
-
101
- def create_isolated_context(context)
102
- new_context = context.new_isolated_subcontext
103
- @params.each { |key, value| new_context[key] = context[value] || context.evaluate(value) || value }
104
- new_context
105
- end
106
- end
107
- end