dugway 1.0.14 → 1.1.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: 7eae3c870ceda8207acc698d61c2aeb008b1f315e4e8bf4347578b90e10e365e
4
- data.tar.gz: 0a2f33a7f2d6be0402e95c23385703ce8bef02f6b6825b0c2b17bc8e7d24198f
3
+ metadata.gz: 4ec5c841ba4d98980fab27d7fe34b9f93c84f6fa80088e0c5ff819aa55b69d8b
4
+ data.tar.gz: 15b36e7b6cd237cec37662746ddf19303cdb224e09385d0ee3f993401c234ba7
5
5
  SHA512:
6
- metadata.gz: 14f7065a90a40eeff514d2816326af0cbc3341e0608a39e22c4059db4924557120b06de94ee11f1601a883707ef905b3ae26ae651490b6931a4c1f604d498d43
7
- data.tar.gz: 1877a14d06d370d659a1c747f1d9f52642c6e6696942aa3d0a01d1fad9fa719d7bc373cf10538eb9b86a1a9aa37c27cad4cb26d462f2544084f99c43ddc07079
6
+ metadata.gz: f0738d371dc90b8d86a3ad908b4095761956fae568f61f9e2e4fe63bf7044fefb35548e3fc0d0dd0ba95076945a26fec02bd7c9012dc6fb7faad077fc1ac7ca9
7
+ data.tar.gz: 6395af7c43b59c158a3aaf080437ac96a098c35bca088eb63206c2ca89b354136d15bcec5f0528ef19c761aeee80050aab2a636092d297df1d8fa5b2b07483be
@@ -8,7 +8,7 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- ruby-version: [2.7.5, 2.6.7, 2.5.9, 2.4.10, 2.3.8]
11
+ ruby-version: [2.7.5, 2.6.7]
12
12
 
13
13
  steps:
14
14
  - uses: actions/checkout@v2
data/README.md CHANGED
@@ -193,6 +193,15 @@ dugway server
193
193
  By default this will serve your theme at http://127.0.0.1:9292/. You can then stop
194
194
  the server by hitting CTRL+C.
195
195
 
196
+ If you want to run with logging, enable it via your theme's `settings.json`
197
+ file with `"log": true`. When Dugway is running, it will then create a log
198
+ in `log/dugway.log` in your theme's directory. You can then log output
199
+ with `debug`, `info` and `warn`, such as:
200
+
201
+ ```
202
+ Dugway.logger.debug("Debug statement here")
203
+ ```
204
+
196
205
  ## Testing your theme
197
206
 
198
207
  Part of building a great theme is making sure it works well in a variety of
@@ -105,7 +105,7 @@ module Dugway
105
105
  end
106
106
 
107
107
  def self.set_page_name_and_render_page(object, type)
108
- page['name'] = object['name']
108
+ page['name'] = object['name'] if type == :artists
109
109
  render_page(type => object)
110
110
  end
111
111
 
@@ -15,6 +15,11 @@ module Dugway
15
15
  default: false,
16
16
  desc: "Skip layout file data attribute validation"
17
17
 
18
+ class_option 'skip-options-validation',
19
+ type: :boolean,
20
+ default: false,
21
+ desc: "Skip options validation"
22
+
18
23
  def self.source_root
19
24
  File.join(Dir.pwd, 'source')
20
25
  end
@@ -24,7 +29,13 @@ module Dugway
24
29
  end
25
30
 
26
31
  def validate
27
- unless theme.valid?(validate_colors: !options['skip-color-validation'], validate_layout_attributes: !options['skip-layout-attribute-validation'])
32
+ validation_options = {
33
+ validate_colors: !options['skip-color-validation'],
34
+ validate_layout_attributes: !options['skip-layout-attribute-validation'],
35
+ validate_options: !options['skip-options-validation']
36
+ }
37
+
38
+ unless theme.valid?(**validation_options)
28
39
  theme.errors.each { |error| say(error, :red) }
29
40
  say("\nTheme is invalid", :red)
30
41
  exit(1)
@@ -13,8 +13,19 @@ module Dugway
13
13
  default: false,
14
14
  desc: "Skip layout file data attribute validation"
15
15
 
16
+ class_option 'skip-options-validation',
17
+ type: :boolean,
18
+ default: false,
19
+ desc: "Skip options validation"
20
+
16
21
  def validate
17
- unless theme.valid?(validate_colors: !options['skip-color-validation'], validate_layout_attributes: !options['skip-layout-attribute-validation'])
22
+ validation_options = {
23
+ validate_colors: !options['skip-color-validation'],
24
+ validate_layout_attributes: !options['skip-layout-attribute-validation'],
25
+ validate_options: !options['skip-options-validation']
26
+ }
27
+
28
+ unless theme.valid?(**validation_options)
18
29
  theme.errors.each { |error| say(error, :red) }
19
30
  say("\nTheme is invalid", :red)
20
31
  exit(1)
@@ -104,6 +104,14 @@ module Dugway
104
104
  end
105
105
  end
106
106
 
107
+ def related_products
108
+ @related_products ||= begin
109
+ drop = RelatedProductsDrop.new(source)
110
+ drop.context = @context if @context
111
+ drop.products
112
+ end
113
+ end
114
+
107
115
  private
108
116
 
109
117
  def price_min_max
@@ -33,7 +33,7 @@ module Dugway
33
33
  when 'newest', 'date'
34
34
  'date'
35
35
  # We don't pass these in the API, so fake it
36
- when 'sales', 'sells', 'views'
36
+ when 'sales', 'sells', 'top-selling', 'views'
37
37
  'shuffle'
38
38
  else
39
39
  'position'
@@ -0,0 +1,88 @@
1
+ module Dugway
2
+ module Drops
3
+ class RelatedProductsDrop < BaseDrop
4
+ def initialize(product)
5
+ super()
6
+ @product = product
7
+ end
8
+
9
+ def products
10
+ fetch_related_products
11
+ end
12
+
13
+ private
14
+
15
+ def settings
16
+ @settings ||= theme.customization
17
+ end
18
+
19
+ def limit
20
+ @limit ||= begin
21
+ if settings
22
+ limit = settings['similar_products'] ||
23
+ settings['related_items'] ||
24
+ settings['related_products'] ||
25
+ settings['number_related_products'] ||
26
+ 4
27
+ limit
28
+ else
29
+ 4
30
+ end
31
+ end
32
+ end
33
+
34
+ def sort_order
35
+ @sort_order ||= begin
36
+ if settings
37
+ order = settings['related_products_order'] ||
38
+ settings['similar_products_order'] ||
39
+ "position"
40
+ order
41
+ else
42
+ "position"
43
+ end
44
+ end
45
+ end
46
+
47
+ def fetch_related_products
48
+ return [] unless @product
49
+
50
+ category_products = sort_products(fetch_category_products).take(limit)
51
+ return category_products if category_products.size >= limit
52
+
53
+ remaining_limit = limit - category_products.size
54
+ fallback_products = sort_products(fetch_fallback_products(category_products, remaining_limit)).take(remaining_limit)
55
+
56
+ category_products + fallback_products
57
+ end
58
+
59
+ def fetch_category_products
60
+ # Filter Dugway's product data to match the categories of the current product
61
+ Dugway.store.products.select do |product|
62
+ product_cats = product['category_ids'] || []
63
+ current_cats = @product['category_ids'] || []
64
+ (product_cats & current_cats).any? && product['id'] != @product['id']
65
+ end.map { |p| ProductDrop.new(p) }
66
+ end
67
+
68
+ def fetch_fallback_products(category_products, limit)
69
+ # Get additional products excluding already included ones
70
+ excluded_ids = category_products.map { |p| p['id'] } + [@product['id']]
71
+ Dugway.store.products
72
+ .reject { |product| excluded_ids.include?(product['id']) }
73
+ .map { |p| ProductDrop.new(p) }
74
+ end
75
+
76
+ def sort_products(products)
77
+ case sort_order
78
+ when 'date', 'newest'
79
+ products.sort { |a,b| b.source['id'] <=> a.source['id'] }
80
+ when 'sales', 'sells', 'top-selling', 'views'
81
+ products.shuffle
82
+ else
83
+ products.sort_by { |p| p.source['position'] }
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/dugway/theme.rb CHANGED
@@ -93,7 +93,7 @@ module Dugway
93
93
  end
94
94
  end
95
95
 
96
- def valid?(validate_colors: true, validate_layout_attributes: true)
96
+ def valid?(validate_colors: true, validate_layout_attributes: true, validate_options: true)
97
97
  @errors = []
98
98
 
99
99
  REQUIRED_FILES.each do |file|
@@ -117,12 +117,22 @@ module Dugway
117
117
 
118
118
  validate_required_color_settings if validate_colors
119
119
  validate_required_layout_attributes if validate_layout_attributes
120
+ validate_options_settings if validate_options
120
121
 
121
122
  @errors.empty?
122
123
  end
123
124
 
124
125
  def validate_required_color_settings
126
+ if !settings['colors']
127
+ @errors << "Missing colors section in theme settings"
128
+ return
129
+ end
130
+
125
131
  required_colors_attribute_names = THEME_COLOR_ATTRIBUTE_MAPPINGS['required_color_attributes']
132
+ if !required_colors_attribute_names
133
+ @errors << "Missing required color attributes configuration"
134
+ return
135
+ end
126
136
 
127
137
  theme_colors = settings['colors'].map { |c| c['variable'] }
128
138
  mappings = THEME_COLOR_ATTRIBUTE_MAPPINGS[name] || {}
@@ -154,6 +164,13 @@ module Dugway
154
164
  @errors << "layout.html must have exactly one `data-bc-hook=\"footer\"`" if footer_hooks != 1
155
165
  end
156
166
 
167
+ def validate_options_settings
168
+ return unless settings['options']
169
+
170
+ validate_options_descriptions
171
+ validate_options_requires
172
+ end
173
+
157
174
  private
158
175
 
159
176
  def validate_preview
@@ -225,6 +242,58 @@ module Dugway
225
242
  @errors << "Duplicate style names found: #{duplicates.join(', ')}" if duplicates.any?
226
243
  end
227
244
 
245
+ def validate_options_descriptions
246
+ missing_descriptions = settings['options'].select { |option|
247
+ option['description'].nil? || option['description'].strip.empty?
248
+ }.map { |option| option['variable'] }
249
+
250
+ @errors << "Missing descriptions for settings: #{missing_descriptions.join(', ')}" unless missing_descriptions.empty?
251
+ end
252
+
253
+ # Validate that any dependent settings are present in the theme settings
254
+ def validate_options_requires
255
+ return unless settings['options']
256
+ all_variables = settings['options'].map { |o| o['variable'] }
257
+
258
+ settings['options'].each do |option|
259
+ next unless option['requires']
260
+
261
+ # Handle case where requires is a string
262
+ if option['requires'].is_a?(String)
263
+ next if option['requires'] == 'inventory'
264
+ unless all_variables.include?(option['requires'])
265
+ @errors << "Option '#{option['variable']}' requires unknown setting '#{option['requires']}'"
266
+ end
267
+ next
268
+ end
269
+
270
+ # Validate requires is either a string or array
271
+ unless option['requires'].is_a?(Array)
272
+ @errors << "Option '#{option['variable']}' requires must be string 'inventory' or array of rules"
273
+ next
274
+ end
275
+
276
+ # Process each rule in the array
277
+ option['requires'].each do |rule|
278
+ next if rule == 'inventory'
279
+
280
+ # Extract setting name from rule
281
+ # Handle both simple cases ("show_search") and complex cases ("show_search eq true")
282
+ setting_name = if rule.include?(' ')
283
+ rule.split(/\s+/).first
284
+ else
285
+ rule
286
+ end
287
+
288
+ # Verify the referenced setting exists
289
+ unless all_variables.include?(setting_name)
290
+ @errors << "Option '#{option['variable']}' requires unknown setting '#{setting_name}'"
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+
228
297
  def source_dir
229
298
  Dugway.source_dir
230
299
  end
@@ -1,3 +1,3 @@
1
1
  module Dugway
2
- VERSION = "1.0.14"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -3,6 +3,19 @@ require 'spec_helper'
3
3
  describe Dugway::Drops::ProductDrop do
4
4
  let(:product) { Dugway::Drops::ProductDrop.new(Dugway.store.products.first) }
5
5
 
6
+ let(:related_products_mock) do
7
+ [
8
+ { 'id' => 2, 'name' => 'Related Product 1' },
9
+ { 'id' => 3, 'name' => 'Related Product 2' }
10
+ ]
11
+ end
12
+
13
+ before do
14
+ allow(Dugway::Drops::RelatedProductsDrop).to receive(:new)
15
+ .with(product.source, limit: 5, sort_order: nil)
16
+ .and_return(double(products: related_products_mock))
17
+ end
18
+
6
19
  describe "#id" do
7
20
  it "should return the product's id" do
8
21
  product.id.should == 9422939
@@ -266,4 +279,27 @@ describe Dugway::Drops::ProductDrop do
266
279
  end
267
280
  end
268
281
  end
282
+
283
+ describe "#related_products" do
284
+ let(:theme) { double('Dugway::Theme') }
285
+ let(:theme_customization) do
286
+ {
287
+ 'related_items' => 5,
288
+ 'related_products_order' => 'position'
289
+ }
290
+ end
291
+
292
+ before do
293
+ allow(Dugway).to receive(:theme).and_return(theme)
294
+ allow(theme).to receive(:customization).and_return(theme_customization)
295
+ allow(Dugway::Drops::RelatedProductsDrop).to receive(:new)
296
+ .with(product.source)
297
+ .and_return(double(products: related_products_mock))
298
+ end
299
+
300
+ it "returns the related products from RelatedProductsDrop" do
301
+ related_products = product.related_products
302
+ expect(related_products).to eq(related_products_mock)
303
+ end
304
+ end
269
305
  end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dugway::Drops::RelatedProductsDrop do
4
+ let(:product) do
5
+ {
6
+ 'id' => 1,
7
+ 'category_ids' => [1, 2],
8
+ 'name' => 'Sample Product'
9
+ }
10
+ end
11
+
12
+ let(:related_product_1) do
13
+ {
14
+ 'id' => 2,
15
+ 'category_ids' => [1],
16
+ 'name' => 'Related Product 1'
17
+ }
18
+ end
19
+
20
+ let(:related_product_2) do
21
+ {
22
+ 'id' => 3,
23
+ 'category_ids' => [2],
24
+ 'name' => 'Related Product 2'
25
+ }
26
+ end
27
+
28
+ let(:unrelated_product) do
29
+ {
30
+ 'id' => 4,
31
+ 'category_ids' => [3],
32
+ 'name' => 'Unrelated Product'
33
+ }
34
+ end
35
+
36
+ let(:theme) { double('Dugway::Theme') }
37
+ let(:theme_customization) do
38
+ {
39
+ 'related_items' => 2,
40
+ 'related_products_order' => 'position'
41
+ }
42
+ end
43
+
44
+ before do
45
+ allow(Dugway.store).to receive(:products).and_return([
46
+ product,
47
+ related_product_1,
48
+ related_product_2,
49
+ unrelated_product
50
+ ])
51
+ allow(Dugway).to receive(:theme).and_return(theme)
52
+ allow(theme).to receive(:customization).and_return(theme_customization)
53
+ end
54
+
55
+ let(:drop) { described_class.new(product) }
56
+
57
+ describe "#products" do
58
+ it "returns related products within the same categories" do
59
+ products = drop.products
60
+ expect(products.map { |p| p['id'] }).to match_array([2, 3])
61
+ end
62
+
63
+ it "limits the number of related products returned" do
64
+ allow(theme).to receive(:customization).and_return({ 'related_items' => 1 })
65
+ products = drop.products
66
+ expect(products.size).to eq(1)
67
+ end
68
+
69
+ it "excludes the original product from the results" do
70
+ products = drop.products
71
+ expect(products.map { |p| p['id'] }).not_to include(product['id'])
72
+ end
73
+
74
+ it "falls back to other products if category matches are insufficient" do
75
+ product['category_ids'] = [] # No categories
76
+ products = drop.products
77
+ expect(products.map { |p| p['id'] }).to match_array([2, 3])
78
+ end
79
+ end
80
+ end
@@ -4,18 +4,30 @@ describe Dugway::Theme do
4
4
  let(:theme) { Dugway.theme }
5
5
 
6
6
  describe "#layout" do
7
+ before(:each) do
8
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
9
+ end
10
+
7
11
  it "should return the theme's layout" do
8
12
  theme.layout.should == read_file('layout.html')
9
13
  end
10
14
  end
11
15
 
12
16
  describe "#settings" do
17
+ before(:each) do
18
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
19
+ end
20
+
13
21
  it "should return a hash of the theme's settings" do
14
22
  theme.settings.should == JSON.parse(read_file('settings.json'))
15
23
  end
16
24
  end
17
25
 
18
26
  describe "#fonts" do
27
+ before(:each) do
28
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
29
+ end
30
+
19
31
  it "should return a hash of font settings values" do
20
32
  theme.fonts.should == {
21
33
  'text_font' => 'Georgia',
@@ -25,6 +37,10 @@ describe Dugway::Theme do
25
37
  end
26
38
 
27
39
  describe "#images" do
40
+ before(:each) do
41
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
42
+ end
43
+
28
44
  it "should return a hash of the image settings" do
29
45
  theme.images.should == {
30
46
  'logo' => { :url => 'images/logo_bc.png', :width => 1, :height => 1 }
@@ -33,6 +49,10 @@ describe Dugway::Theme do
33
49
  end
34
50
 
35
51
  describe "#image_sets" do
52
+ before(:each) do
53
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
54
+ end
55
+
36
56
  it "should return a hash of the image set settings" do
37
57
  theme.image_sets.should == {
38
58
  'slideshow_images' => [
@@ -47,6 +67,10 @@ describe Dugway::Theme do
47
67
  end
48
68
 
49
69
  describe "#customization" do
70
+ before(:each) do
71
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
72
+ end
73
+
50
74
  it "should return a hash of font, color, option, images and image sets settings values" do
51
75
  theme.customization.should == {
52
76
  'background_color' => 'white',
@@ -76,6 +100,8 @@ describe Dugway::Theme do
76
100
  Dugway.stub(:theme) {
77
101
  Dugway::Theme.new(:fixed_sidebar => false, :link_text_color => 'blue')
78
102
  }
103
+
104
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
79
105
  end
80
106
 
81
107
  it "should merge those values into the defaults" do
@@ -105,18 +131,30 @@ describe Dugway::Theme do
105
131
  end
106
132
 
107
133
  describe "#name" do
134
+ before(:each) do
135
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
136
+ end
137
+
108
138
  it "should return the theme's name" do
109
139
  theme.name.should == 'Test Theme'
110
140
  end
111
141
  end
112
142
 
113
143
  describe "#version" do
144
+ before(:each) do
145
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
146
+ end
147
+
114
148
  it "should return the theme's version" do
115
149
  theme.version.should == '1.2.3'
116
150
  end
117
151
  end
118
152
 
119
153
  describe "#file_content" do
154
+ before(:each) do
155
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
156
+ end
157
+
120
158
  it "should return the file content for most files" do
121
159
  %w( home.html products.html screenshot.jpg ).each { |file_name|
122
160
  theme.file_content(file_name).should == read_file(file_name)
@@ -133,6 +171,10 @@ describe Dugway::Theme do
133
171
  end
134
172
 
135
173
  describe "#build_file" do
174
+ before(:each) do
175
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
176
+ end
177
+
136
178
  it "should return the file content for most files" do
137
179
  %w( home.html products.html screenshot.jpg ).each { |file_name|
138
180
  theme.build_file(file_name).should == read_file(file_name)
@@ -149,25 +191,55 @@ describe Dugway::Theme do
149
191
  end
150
192
 
151
193
  describe "#files" do
194
+ before(:each) do
195
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
196
+ end
197
+
152
198
  it "should return an array of all files" do
153
199
  theme.files.should =~ ["cart.html", "contact.html", "home.html", "layout.html", "maintenance.html", "product.html", "products.html", "screenshot.jpg", "settings.json", "theme.css", "theme.js", "images/logo_bc.png", "images/slideshow/1.gif", "images/slideshow/2.gif", "images/slideshow/3.gif", "images/slideshow/4.gif", "images/slideshow/5.gif", "images/small.svg", "fonts/icons.ttf", "fonts/icons.woff"]
154
200
  end
155
201
  end
156
202
 
157
203
  describe "#image_files" do
204
+ before(:each) do
205
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
206
+ end
207
+
158
208
  it "should return an array of all image files" do
159
209
  theme.image_files.should =~ ["images/logo_bc.png", "images/slideshow/1.gif", "images/slideshow/2.gif", "images/slideshow/3.gif", "images/slideshow/4.gif", "images/slideshow/5.gif", "images/small.svg"]
160
210
  end
161
211
  end
162
212
 
163
213
  describe "#font_files" do
214
+ before(:each) do
215
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
216
+ end
217
+
164
218
  it "should return an array of all font files" do
165
219
  theme.font_files.should include("fonts/icons.ttf", "fonts/icons.woff")
166
220
  end
167
221
  end
168
222
 
169
223
  describe "#valid?" do
224
+ let(:required_colors) {[
225
+ 'background_color',
226
+ 'primary_text_color',
227
+ 'link_text_color',
228
+ 'link_hover_color',
229
+ 'button_background_color',
230
+ 'button_text_color',
231
+ 'button_hover_background_color'
232
+ ]}
233
+
170
234
  it "should return true when a theme has everything it needs" do
235
+ allow(theme).to receive(:validate_required_color_settings) { true }
236
+
237
+ allow(theme).to receive(:settings).and_return({
238
+ 'name' => 'Test Theme',
239
+ 'version' => '1.2.3',
240
+ 'colors' => required_colors.map { |color| {'variable' => color} }
241
+ })
242
+
171
243
  theme.valid?.should be(true)
172
244
  theme.errors.should be_empty
173
245
  end
@@ -175,6 +247,7 @@ describe Dugway::Theme do
175
247
  describe "when missing a required file" do
176
248
  before(:each) do
177
249
  theme.stub(:read_source_file).with('cart.html') { theme.unstub(:read_source_file); nil }
250
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
178
251
  end
179
252
 
180
253
  it "should not be valid" do
@@ -187,6 +260,7 @@ describe Dugway::Theme do
187
260
  describe "when missing a name" do
188
261
  before(:each) do
189
262
  theme.stub(:name) { nil }
263
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
190
264
  end
191
265
 
192
266
  it "should not be valid" do
@@ -199,6 +273,7 @@ describe Dugway::Theme do
199
273
  describe "when missing a version" do
200
274
  before(:each) do
201
275
  theme.stub(:version) { nil }
276
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
202
277
  end
203
278
 
204
279
  it "should not be valid" do
@@ -211,6 +286,7 @@ describe Dugway::Theme do
211
286
  describe "when having an invalid version" do
212
287
  before(:each) do
213
288
  theme.stub(:version) { '1.3' }
289
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
214
290
  end
215
291
 
216
292
  it "should not be valid" do
@@ -224,6 +300,7 @@ describe Dugway::Theme do
224
300
  before(:each) do
225
301
  theme.stub(:name) { nil }
226
302
  theme.stub(:version) { nil }
303
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
227
304
  end
228
305
 
229
306
  it "should return all of them" do
@@ -273,6 +350,7 @@ describe Dugway::Theme do
273
350
  end
274
351
 
275
352
  before(:each) do
353
+ allow(theme).to receive(:validate_required_color_settings) { true }
276
354
  allow(theme).to receive(:name) { "Test Theme" }
277
355
  allow(theme).to receive(:version) { "1.2.3" }
278
356
  end
@@ -293,6 +371,88 @@ describe Dugway::Theme do
293
371
  theme.errors.should include('Style in group \'Classic\' - Missing style_name')
294
372
  end
295
373
  end
374
+
375
+ describe "when missing option descriptions" do
376
+ before(:each) do
377
+ allow_any_instance_of(Dugway::Theme).to receive(:validate_required_color_settings) { true }
378
+ theme.stub(:settings) { {
379
+ 'name' => 'Test Theme',
380
+ 'version' => '1.2.3',
381
+ 'colors' => [
382
+ {'variable' => 'background_color'},
383
+ {'variable' => 'primary_text_color'},
384
+ {'variable' => 'link_text_color'},
385
+ {'variable' => 'link_hover_color'},
386
+ {'variable' => 'button_background_color'},
387
+ {'variable' => 'button_text_color'},
388
+ {'variable' => 'button_hover_background_color'}
389
+ ],
390
+ 'options' => [{ 'variable' => 'show_search', 'label' => 'Show search' }]
391
+ } }
392
+ end
393
+
394
+ it "should not be valid" do
395
+ theme.valid?.should be(false)
396
+ theme.errors.size.should == 1
397
+ theme.errors.first.should == 'Missing descriptions for settings: show_search'
398
+ end
399
+
400
+ it "should be valid when skipping options validation" do
401
+ theme.valid?(validate_options: false).should be(true)
402
+ end
403
+ end
404
+
405
+ describe "when validating option requirements" do
406
+ let(:required_colors) {[
407
+ 'background_color',
408
+ 'primary_text_color',
409
+ 'link_text_color',
410
+ 'link_hover_color',
411
+ 'button_background_color',
412
+ 'button_text_color',
413
+ 'button_hover_background_color'
414
+ ]}
415
+
416
+ it "allows options with no requires" do
417
+ settings = theme.settings.merge({
418
+ 'options' => [{
419
+ 'variable' => 'show_search',
420
+ 'label' => 'Show search',
421
+ 'description' => 'Show search in header'
422
+ }]
423
+ })
424
+ allow(theme).to receive(:settings).and_return(settings)
425
+
426
+ theme.valid?.should be(true)
427
+ theme.errors.should be_empty
428
+ end
429
+
430
+ it "should not be valid when colors section is missing" do
431
+ allow(theme).to receive(:settings).and_return({
432
+ 'name' => 'Test Theme',
433
+ 'version' => '1.2.3',
434
+ 'options' => []
435
+ })
436
+
437
+ theme.valid?.should be(false)
438
+ theme.errors.should include("Missing colors section in theme settings")
439
+ end
440
+
441
+ it "should not be valid when required colors are missing" do
442
+
443
+ allow(theme).to receive(:settings).and_return({
444
+ 'name' => 'Test Theme',
445
+ 'version' => '1.2.3',
446
+ 'colors' => [
447
+ { 'variable' => 'background_color' }
448
+ ],
449
+ 'options' => []
450
+ })
451
+
452
+ theme.valid?.should be(false)
453
+ theme.errors.first.should match(/Missing required color settings:/)
454
+ end
455
+ end
296
456
  end
297
457
 
298
458
  def read_file(file_name)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dugway
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.14
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Big Cartel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-17 00:00:00.000000000 Z
11
+ date: 2025-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -490,6 +490,7 @@ files:
490
490
  - lib/dugway/liquid/drops/product_drop.rb
491
491
  - lib/dugway/liquid/drops/product_option_drop.rb
492
492
  - lib/dugway/liquid/drops/products_drop.rb
493
+ - lib/dugway/liquid/drops/related_products_drop.rb
493
494
  - lib/dugway/liquid/drops/shipping_option_drop.rb
494
495
  - lib/dugway/liquid/drops/theme_drop.rb
495
496
  - lib/dugway/liquid/drops/theme_image_sets_drop.rb
@@ -560,6 +561,7 @@ files:
560
561
  - spec/units/dugway/liquid/drops/product_drop_spec.rb
561
562
  - spec/units/dugway/liquid/drops/product_option_drop_spec.rb
562
563
  - spec/units/dugway/liquid/drops/products_drop_spec.rb
564
+ - spec/units/dugway/liquid/drops/related_products_drop_spec.rb
563
565
  - spec/units/dugway/liquid/drops/shipping_option_drop_spec.rb
564
566
  - spec/units/dugway/liquid/drops/theme_drop_spec.rb
565
567
  - spec/units/dugway/liquid/drops/theme_image_sets_drop_spec.rb
@@ -648,6 +650,7 @@ test_files:
648
650
  - spec/units/dugway/liquid/drops/product_drop_spec.rb
649
651
  - spec/units/dugway/liquid/drops/product_option_drop_spec.rb
650
652
  - spec/units/dugway/liquid/drops/products_drop_spec.rb
653
+ - spec/units/dugway/liquid/drops/related_products_drop_spec.rb
651
654
  - spec/units/dugway/liquid/drops/shipping_option_drop_spec.rb
652
655
  - spec/units/dugway/liquid/drops/theme_drop_spec.rb
653
656
  - spec/units/dugway/liquid/drops/theme_image_sets_drop_spec.rb