shopify_liquid_test_helper 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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