dugway 0.5.3 → 0.5.4

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +1 -1
  6. data/LICENSE.txt +22 -0
  7. data/dugway.gemspec +3 -0
  8. data/lib/dugway/cart.rb +8 -12
  9. data/lib/dugway/cli/templates/Gemfile.tt +1 -1
  10. data/lib/dugway/cli/templates/gitignore.tt +1 -0
  11. data/lib/dugway/cli/templates/source/product.html +5 -3
  12. data/lib/dugway/cli/templates/source/stylesheets/cart.css.sass +8 -0
  13. data/lib/dugway/cli/templates/source/stylesheets/product.css.sass +32 -0
  14. data/lib/dugway/liquid/drops/cart_item_drop.rb +4 -0
  15. data/lib/dugway/liquid/drops/product_drop.rb +10 -6
  16. data/lib/dugway/liquid/drops/product_option_drop.rb +1 -1
  17. data/lib/dugway/liquid/drops/shipping_option_drop.rb +2 -0
  18. data/lib/dugway/liquid/tags/checkout_form.rb +1 -1
  19. data/lib/dugway/version.rb +1 -1
  20. data/spec/features/contact_form_spec.rb +43 -0
  21. data/spec/features/page_rendering_spec.rb +69 -0
  22. data/spec/features/shopping_spec.rb +38 -0
  23. data/spec/fixtures/store/products.js +1 -1
  24. data/spec/fixtures/store/store.js +1 -1
  25. data/spec/fixtures/theme/cart.html +22 -7
  26. data/spec/fixtures/theme/contact.html +37 -37
  27. data/spec/fixtures/theme/layout.html +8 -0
  28. data/spec/fixtures/theme/settings.json +1 -0
  29. data/spec/fixtures/theme/styles.css +2 -2
  30. data/spec/spec_helper.rb +8 -0
  31. data/spec/units/dugway/cart_spec.rb +204 -0
  32. data/spec/units/dugway/liquid/drops/account_drop_spec.rb +54 -0
  33. data/spec/units/dugway/liquid/drops/artist_drop_spec.rb +40 -0
  34. data/spec/units/dugway/liquid/drops/artists_drop_spec.rb +41 -0
  35. data/spec/units/dugway/liquid/drops/cart_drop_spec.rb +81 -0
  36. data/spec/units/dugway/liquid/drops/cart_item_drop_spec.rb +72 -0
  37. data/spec/units/dugway/liquid/drops/categories_drop_spec.rb +41 -0
  38. data/spec/units/dugway/liquid/drops/category_drop_spec.rb +40 -0
  39. data/spec/units/dugway/liquid/drops/contact_drop_spec.rb +124 -0
  40. data/spec/units/dugway/liquid/drops/country_drop_spec.rb +17 -0
  41. data/spec/units/dugway/liquid/drops/image_drop_spec.rb +23 -0
  42. data/spec/units/dugway/liquid/drops/page_drop_spec.rb +70 -0
  43. data/spec/units/dugway/liquid/drops/pages_drop_spec.rb +29 -0
  44. data/spec/units/dugway/liquid/drops/product_drop_spec.rb +269 -0
  45. data/spec/units/dugway/liquid/drops/product_option_drop_spec.rb +86 -0
  46. data/spec/units/dugway/liquid/drops/products_drop_spec.rb +127 -0
  47. data/spec/units/dugway/liquid/drops/shipping_option_drop_spec.rb +26 -0
  48. data/spec/units/dugway/liquid/drops/theme_drop_spec.rb +68 -0
  49. data/spec/units/dugway/store_spec.rb +27 -27
  50. data/spec/units/dugway/template_spec.rb +12 -0
  51. data/spec/units/dugway/theme_spec.rb +198 -0
  52. metadata +95 -57
  53. data/spec/units/dugway_spec.rb +0 -9
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 753ddf37dd59de0812e32500da4fcf189b9d2f89
4
+ data.tar.gz: be0e35b01e22f044c8da70bc6888647476e38cac
5
+ SHA512:
6
+ metadata.gz: 9898d404fa7127e8163d712d12448052bbb845c40b03c5382a7c8b0e0bb302514dc0c5a8918c6492533f7d876e9f359f35b09dc923a30039353a515bcb72b150
7
+ data.tar.gz: ec25ce081aee329d90e937a5d40a21dd599362416a7c0a568e520e2cb825395066888faea7f4e5bcb20373a8141d1df0c6e77d3fa5157f904e0541820aeff104
data/.gitignore CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Gemfile.lock
4
4
 
5
+ coverage
6
+
5
7
  *.gem
6
8
  *.tmproj
7
9
  *.sublime*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -1,3 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
+ - 2.0
5
+ notifications:
6
+ email: false
data/Gemfile CHANGED
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Big Cartel, LLC
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -41,4 +41,7 @@ Gem::Specification.new do |s|
41
41
  s.add_development_dependency('rake', '~> 10.0.3')
42
42
  s.add_development_dependency('rspec', '~> 2.12.0')
43
43
  s.add_development_dependency('webmock', '~> 1.9.3')
44
+ s.add_development_dependency('json_expressions', '~> 0.8.2')
45
+ s.add_development_dependency('capybara', '~> 2.0.2')
46
+ s.add_development_dependency('simplecov', '~> 0.7.1')
44
47
  end
@@ -10,6 +10,10 @@ module Dugway
10
10
  self.items = []
11
11
  end
12
12
 
13
+ def empty?
14
+ items.empty?
15
+ end
16
+
13
17
  def item_count
14
18
  items.map { |item| item.quantity }.inject(:+) || 0
15
19
  end
@@ -53,14 +57,10 @@ module Dugway
53
57
  def update(params)
54
58
  add, adds, updates = params.delete(:add), params.delete(:adds), params.delete(:update)
55
59
  add_item(add) if add
56
- add_item(adds) if adds
60
+ add_items(adds) if adds
57
61
  update_quantities(updates) if updates
58
62
  end
59
63
 
60
- def empty?
61
- items.empty?
62
- end
63
-
64
64
  def as_json(options=nil)
65
65
  {
66
66
  :item_count => item_count,
@@ -83,7 +83,7 @@ module Dugway
83
83
  product, option = Dugway.store.product_and_option(id)
84
84
 
85
85
  if product && option
86
- item = CartItem.new
86
+ item = Item.new
87
87
  item.id = items.size + 1
88
88
  item.name = option['name'] == 'Default' ? product['name'] : "#{ product['name'] } - #{ option['name'] }"
89
89
  item.unit_price = option['price']
@@ -103,11 +103,7 @@ module Dugway
103
103
  end
104
104
 
105
105
  def add_items(adds)
106
- if adds.kind_of?(Array)
107
- adds.each { |add| add_item(add) }
108
- elsif adds.kind_of?(Hash)
109
- adds.each_pair { |key, add| add_item(add.reverse_merge(:id => key)) }
110
- end
106
+ adds.each { |add| add_item(add) }
111
107
  end
112
108
 
113
109
  def update_quantities(updates)
@@ -121,7 +117,7 @@ module Dugway
121
117
  end
122
118
  end
123
119
 
124
- CartItem = Struct.new(:id, :name, :unit_price, :quantity, :product, :option) do
120
+ Item = Struct.new(:id, :name, :unit_price, :quantity, :product, :option) do
125
121
  def price
126
122
  unit_price * quantity
127
123
  end
@@ -1,2 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gem 'dugway'
@@ -1,3 +1,4 @@
1
+ .bundle
1
2
  .DS_Store
2
3
 
3
4
  build
@@ -24,12 +24,14 @@
24
24
  <h5>{{ product.default_price | money_with_sign }}{% if product.on_sale %} <em>On Sale{% endif %}</em></h5>
25
25
  <h5>Availability</h5>
26
26
 
27
- <ul>
27
+ <ul class="availability">
28
28
  {% for option in product.options %}
29
29
  <li>
30
30
  {% unless product.has_default_option %}<span>{{ option.name }}</span>{% endunless %}
31
- <span>{% if option.sold_out %}Sold Out{% else %}{{ option.inventory }}%{% endif %}</span>
32
- <div style="width:{{ option.inventory }}%"></div>
31
+ <span>{% if option.sold_out %}Sold Out{% endif %}</span>
32
+ <b>
33
+ <b style="width:{{ option.inventory }}%"></b>
34
+ </b>
33
35
  </li>
34
36
  {% endfor %}
35
37
  </ul>
@@ -1,8 +1,16 @@
1
1
  body#cart
2
2
  form
3
3
  ul
4
+ border-bottom: dashed 1px #ddd
4
5
  margin-bottom: 2em
5
6
 
7
+ ul + p
8
+ float: left
9
+
10
+ button
11
+ float: right
12
+ margin: 1.2em 0
13
+
6
14
  li
7
15
  overflow: hidden
8
16
 
@@ -8,6 +8,9 @@ body#product
8
8
  margin-right: 18px
9
9
  border: 3px solid #eee
10
10
 
11
+ img
12
+ float: left
13
+
11
14
  li.selected
12
15
  border-color: #72c29b
13
16
 
@@ -17,3 +20,32 @@ body#product
17
20
  border-right: none
18
21
  margin-left: 30px
19
22
  padding-left: 30px
23
+ width: 30%
24
+
25
+ form
26
+ div
27
+ float: left
28
+ margin-right: 5px
29
+ button
30
+ font-size: 12px
31
+
32
+ .availability
33
+ li
34
+ height: 16px
35
+ font-size: 11px
36
+ margin-bottom: 5px
37
+
38
+ span
39
+ display: block
40
+ float: left
41
+ width: 20%
42
+
43
+ > b
44
+ display: block
45
+ margin-left: 20%
46
+ width: 80%
47
+
48
+ b
49
+ background: #eee
50
+ display: block
51
+ height: 16px
@@ -5,6 +5,10 @@ module Dugway
5
5
  unit_price * quantity
6
6
  end
7
7
 
8
+ def total
9
+ price + shipping
10
+ end
11
+
8
12
  def product
9
13
  ProductDrop.new(source['product'])
10
14
  end
@@ -1,6 +1,10 @@
1
1
  module Dugway
2
2
  module Drops
3
3
  class ProductDrop < BaseDrop
4
+ def created_at
5
+ Time.parse(source['created_at'])
6
+ end
7
+
4
8
  def price
5
9
  nil # price is deprecated in favor of default_price
6
10
  end
@@ -18,7 +22,7 @@ module Dugway
18
22
  end
19
23
 
20
24
  def has_default_option
21
- @has_default_option ||= options.size == 1 && option.default
25
+ @has_default_option ||= options.size == 1 && option.name.downcase == 'default'
22
26
  end
23
27
 
24
28
  def option
@@ -30,11 +34,11 @@ module Dugway
30
34
  end
31
35
 
32
36
  def options_in_stock
33
- @options_in_stock ||= options
37
+ @options_in_stock ||= options.reject { |o| o.sold_out }
34
38
  end
35
39
 
36
40
  def shipping
37
- @shipping ||= source['shipping'].map { |o| ShippingOptionDrop.new(o.update('product' => self)) }
41
+ @shipping ||= source['shipping'].present? ? source['shipping'].map { |o| ShippingOptionDrop.new(o.update('product' => self)) } : []
38
42
  end
39
43
 
40
44
  def image
@@ -70,15 +74,15 @@ module Dugway
70
74
  end
71
75
 
72
76
  def edit_url
73
- "http://bigcartel.com"
77
+ 'http://bigcartel.com'
74
78
  end
75
79
 
76
80
  def categories
77
- @categories ||= CategoriesDrop.new(source['categories'].map { |c| CategoryDrop.new(c) }) rescue []
81
+ @categories ||= source['categories'].map { |c| CategoryDrop.new(c) } rescue []
78
82
  end
79
83
 
80
84
  def artists
81
- @artists ||= ArtistsDrop.new(source['artists'].map { |a| ArtistDrop.new(a) }) rescue []
85
+ @artists ||= source['artists'].map { |a| ArtistDrop.new(a) } rescue []
82
86
  end
83
87
 
84
88
  def css_class
@@ -2,7 +2,7 @@ module Dugway
2
2
  module Drops
3
3
  class ProductOptionDrop < BaseDrop
4
4
  def default
5
- name.downcase == 'default'
5
+ position == 1
6
6
  end
7
7
 
8
8
  def has_custom_price
@@ -5,6 +5,8 @@ module Dugway
5
5
  @country ||= CountryDrop.new(source['country'])
6
6
  end
7
7
 
8
+ # internal
9
+
8
10
  def strict
9
11
  @strict ||= product.shipping.size > 1 || product.shipping.first.country.name.present?
10
12
  end
@@ -2,7 +2,7 @@ module Dugway
2
2
  module Tags
3
3
  class CheckoutForm < ::Liquid::Block
4
4
  def render(context)
5
- %{<form id="checkout_form" name="checkout_form" method="post" action="/success"></form>}
5
+ %{<form id="checkout_form" name="checkout_form" method="post" action="/success">#{ render_all(@nodelist, context) }</form>}
6
6
  end
7
7
  end
8
8
  end
@@ -1,3 +1,3 @@
1
1
  module Dugway
2
- VERSION = "0.5.3"
2
+ VERSION = "0.5.4"
3
3
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Contact form' do
4
+ scenario 'submitting the form' do
5
+ submit_contact_form
6
+ expect(page).to have_content('Your message has been sent')
7
+ end
8
+
9
+ scenario 'with a missing field' do
10
+ submit_contact_form(:name => '')
11
+ expect(page).to have_content('All fields are required')
12
+ end
13
+
14
+ scenario 'with an invalid email' do
15
+ submit_contact_form(:email => 'blah')
16
+ expect(page).to have_content('Invalid email address')
17
+ end
18
+
19
+ scenario 'with an invalid captcha' do
20
+ submit_contact_form(:captcha => 'blah')
21
+ expect(page).to have_content('Spam check was incorrect')
22
+ end
23
+
24
+ def submit_contact_form(fields={})
25
+ fields.reverse_merge!(
26
+ :name => 'Joe',
27
+ :email => 'joe@example.com',
28
+ :subject => 'Testing',
29
+ :message => 'Hi there',
30
+ :captcha => 'rQ9pC'
31
+ )
32
+
33
+ visit '/contact'
34
+
35
+ fill_in 'Name', :with => fields[:name]
36
+ fill_in 'Email', :with => fields[:email]
37
+ fill_in 'Subject', :with => fields[:subject]
38
+ fill_in 'Message', :with => fields[:message]
39
+ fill_in 'Spam check', :with => fields[:captcha]
40
+
41
+ click_button 'Send'
42
+ end
43
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Page rendering' do
4
+ scenario 'home.html' do
5
+ visit '/'
6
+ expect(page).to have_content('Dugway') # layout.html
7
+ expect(page).to have_content('My Product')
8
+ expect(page).to have_content('$10.00')
9
+ end
10
+
11
+ scenario 'products.html' do
12
+ visit '/products'
13
+ expect(page).to have_content('Dugway') # layout.html
14
+ expect(page).to have_content('Products')
15
+ expect(page).to have_content('My Product')
16
+ expect(page).to have_content('$10.00')
17
+ end
18
+
19
+ scenario 'product.html' do
20
+ visit '/product/my-product'
21
+ expect(page).to have_content('Dugway') # layout.html
22
+ expect(page).to have_content('My Product')
23
+ expect(page).to have_content('$10.00')
24
+ end
25
+
26
+ scenario 'cart.html' do
27
+ visit '/cart'
28
+ expect(page).to have_content('Dugway') # layout.html
29
+ expect(page).to have_content('Cart')
30
+ expect(page).to have_content('Your cart is empty')
31
+ end
32
+
33
+ scenario 'success.html' do
34
+ visit '/success'
35
+ expect(page).to have_content('Dugway') # layout.html
36
+ expect(page).to have_content('Thank You. Your order has been placed.')
37
+ end
38
+
39
+ scenario 'contact.html' do
40
+ visit '/contact'
41
+ expect(page).to have_content('Dugway') # layout.html
42
+ expect(page).to have_content('Contact')
43
+ expect(page).to have_content('Spam check')
44
+ end
45
+
46
+ scenario 'maintenance.html' do
47
+ visit '/maintenance'
48
+ expect(page).to have_content('Please check back soon.')
49
+ end
50
+
51
+ scenario 'custom page' do
52
+ visit '/about-us'
53
+ expect(page).to have_content('Dugway') # layout.html
54
+ expect(page).to have_content('About Us')
55
+ expect(page).to have_content("We're really cool!")
56
+ end
57
+
58
+ scenario 'styles.css' do
59
+ visit '/styles.css'
60
+ expect(page).to have_content('height: 100%;') # one.css
61
+ expect(page).to have_content('color: red;') # two.css.sass
62
+ end
63
+
64
+ scenario 'scripts.js' do
65
+ visit '/scripts.js'
66
+ expect(page).to have_content("console.log('One')") # one.js
67
+ expect(page).to have_content("console.log('Two')") # two.js.coffee
68
+ end
69
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Shopping' do
4
+ scenario 'buying a product' do
5
+ visit '/'
6
+ expect(page).to have_content('Cart ($0.00)')
7
+
8
+ add_product_to_cart
9
+ expect(page).to have_content('Cart ($10.00)')
10
+
11
+ click_button 'Checkout'
12
+ expect(page).to have_content('One moment...')
13
+
14
+ click_button 'Checkout'
15
+ expect(page).to have_content('Thank You. Your order has been placed.')
16
+ expect(page).to have_content('Cart ($0.00)')
17
+ end
18
+
19
+ scenario 'updating a cart' do
20
+ add_product_to_cart
21
+ fill_in 'item_1_qty', :with => 3
22
+ click_button 'Update'
23
+ expect(page).to have_content('Cart ($30.00)')
24
+ end
25
+
26
+ scenario 'removing a product' do
27
+ add_product_to_cart
28
+ fill_in 'item_1_qty', :with => 0
29
+ click_button 'Update'
30
+ expect(page).to have_content('Cart ($0.00)')
31
+ expect(page).to have_content('Your cart is empty')
32
+ end
33
+
34
+ def add_product_to_cart
35
+ visit '/product/my-product'
36
+ click_button 'Add to Cart'
37
+ end
38
+ end