active-cart 0.0.1
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.
- data/.gitignore +2 -0
- data/README +24 -0
- data/Rakefile +55 -0
- data/generators/schwacms-gallery/schwacms_gallery_generator.rb +11 -0
- data/generators/schwacms-gallery/templates/schwacms_gallery_migration.rb +26 -0
- data/install.rb +1 -0
- data/lib/active_cart.rb +12 -0
- data/lib/active_cart/cart.rb +83 -0
- data/lib/active_cart/cart_storage.rb +36 -0
- data/lib/active_cart/order_total.rb +23 -0
- data/lib/active_cart/order_total_collection.rb +44 -0
- data/test/mocks/test_cart_storage.rb +7 -0
- data/test/mocks/test_item.rb +20 -0
- data/test/mocks/test_order_total.rb +15 -0
- data/test/performance/browsing_test.rb +9 -0
- data/test/test_helper.rb +16 -0
- data/test/unit/cart_storage_test.rb +137 -0
- data/test/unit/cart_test.rb +188 -0
- data/test/unit/order_total_collection_test.rb +87 -0
- data/uninstall.rb +1 -0
- metadata +81 -0
data/.gitignore
ADDED
data/README
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
== ActiveCart
|
2
|
+
|
3
|
+
ActiveCart is a Shopping Cart framework, it's not a fullyfledged cart, so you will need to do some stuff to get it to work.
|
4
|
+
|
5
|
+
The cart system has a storage engine, which means you aren't bound to a particular database (Eventually there will be different engines already built to get you started
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
gem install active_cart
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'active_cart'
|
12
|
+
|
13
|
+
@cart = ActiveCart::Cart.setup(MyStorageEngine.new) do |t|
|
14
|
+
t << ShippingOrderTotal.new
|
15
|
+
t << GstOrderTotal.new
|
16
|
+
end
|
17
|
+
|
18
|
+
In this example the ShippingOrderTotal and GstOrderTotal have been created by the developer and follow the OrderTotal interface.
|
19
|
+
|
20
|
+
== Todo
|
21
|
+
|
22
|
+
Write some actual Storage Engines and OrderTotal examples, and finish the docs.
|
23
|
+
|
24
|
+
Copyright (c) 2010 Myles Eftos (myles@madpilot.com.au), released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = "active-cart"
|
11
|
+
gem.summary = "Shopping Cart framework gem. Supports 'storage engines' and order total plugins"
|
12
|
+
gem.description = "You can use active-cart as the basis of a shopping cart system. It's definately not complete, you need to build a website around it."
|
13
|
+
gem.email = "myles@madpilot.com.au"
|
14
|
+
gem.homepage = "http://gemcutter.org/gems/active-cart"
|
15
|
+
gem.authors = ["Myles Eftos"]
|
16
|
+
gem.version = "0.0.1"
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/unit/*_test.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/unit/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
task :test => :check_dependencies
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "saasu_connect #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class SchwacmsGalleryGenerator < Rails::Generator::NamedBase
|
2
|
+
def initialize(runtime_args, runtime_options = {})
|
3
|
+
super
|
4
|
+
end
|
5
|
+
|
6
|
+
def manifest
|
7
|
+
record do |m|
|
8
|
+
m.migration_template 'schwacms_gallery_migration.rb', 'db/migrate', :migration_file_name => 'create_schwacms_gallery'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class CreateSchwacmsGallery < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table "galleries", :force => true do |t|
|
4
|
+
t.integer "width"
|
5
|
+
t.integer "height"
|
6
|
+
t.integer "thumbnail_width"
|
7
|
+
t.integer "thumbnail_height"
|
8
|
+
t.datetime "created_at"
|
9
|
+
t.datetime "updated_at"
|
10
|
+
end
|
11
|
+
|
12
|
+
create_table "gallery_images", :force => true do |t|
|
13
|
+
t.string "path"
|
14
|
+
t.text "description"
|
15
|
+
t.integer "gallery_id"
|
16
|
+
t.integer "position"
|
17
|
+
t.datetime "created_at"
|
18
|
+
t.datetime "updated_at"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.down
|
23
|
+
drop_table "gallery_images"
|
24
|
+
drop_table "galleries"
|
25
|
+
end
|
26
|
+
end
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
data/lib/active_cart.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'active_cart'))
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'active_cart/cart_storage'
|
6
|
+
require 'active_cart/order_total'
|
7
|
+
require 'active_cart/order_total_collection'
|
8
|
+
require 'active_cart/cart'
|
9
|
+
|
10
|
+
module ActiveCart
|
11
|
+
VERSION = "0.0.1"
|
12
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module ActiveCart
|
2
|
+
# The Cart class is the core class in ActiveCart. It is a singleton (so you can only have one cart per application), that gets setup initially by passing in
|
3
|
+
# a storage engine instance. Storage engines abstract away the storage of the cart, and is left as an exercise to the user. See the Storage engine docs
|
4
|
+
# for details.
|
5
|
+
#
|
6
|
+
# The Cart class also takes order_total objects, which will calculate order totals. it may include thinkgs like shipping, or gift vouchers etc. See the Order Total
|
7
|
+
# docs for details.
|
8
|
+
#
|
9
|
+
# The Cart object delegates a number of Array methods:
|
10
|
+
# :[], :<<, :[]=, :at, :clear, :collect, :map, :delete, :delete_at, :each, :each_index, :empty?, :eql?, :first, :include?, :index, :inject, :last, :length, :pop, :push, :shift, :size, :unshift
|
11
|
+
class Cart
|
12
|
+
attr_accessor :storage_engine, :order_total_calculators, :customer
|
13
|
+
include Singleton
|
14
|
+
include Enumerable
|
15
|
+
|
16
|
+
#nodoc
|
17
|
+
def self.instance_with_setup_check
|
18
|
+
raise StandardError, 'Please call setup first' unless @setup_called
|
19
|
+
instance_without_setup_check
|
20
|
+
end
|
21
|
+
|
22
|
+
# The method MUST be called before you call instance, otherwise you will receive and StandardError
|
23
|
+
# You need to supply a storage engine. An optional block can be given which allows you to add order total items.
|
24
|
+
#
|
25
|
+
# A typical initialization block might look like this
|
26
|
+
#
|
27
|
+
# @cart = Cart.setup(MyAwesomeStorageEngine.new) do |o|
|
28
|
+
# o << ShippingOrderTotal.new
|
29
|
+
# o << GstOrderTotal.new
|
30
|
+
# end
|
31
|
+
def self.setup(storage_engine, &block)
|
32
|
+
@setup_called = true
|
33
|
+
instance = self.instance_without_setup_check
|
34
|
+
instance.storage_engine = storage_engine
|
35
|
+
instance.order_total_calculators = OrderTotalCollection.new(self)
|
36
|
+
|
37
|
+
if block_given?
|
38
|
+
yield instance.order_total_calculators
|
39
|
+
end
|
40
|
+
instance
|
41
|
+
end
|
42
|
+
|
43
|
+
class << self
|
44
|
+
alias_method :instance_without_setup_check, :instance
|
45
|
+
alias_method :instance, :instance_with_setup_check
|
46
|
+
end
|
47
|
+
|
48
|
+
extend Forwardable
|
49
|
+
# Storage Engine Array delegators
|
50
|
+
def_delegators :@storage_engine, :[], :<<, :[]=, :at, :clear, :collect, :map, :delete, :delete_at, :each, :each_index, :empty?, :eql?, :first, :include?, :index, :inject, :last, :length, :pop, :push, :shift, :size, :unshift
|
51
|
+
|
52
|
+
# Returns a unique id for the invoice. It's upto the storage engine to generate and track these numbers
|
53
|
+
def invoice_id
|
54
|
+
@storage_engine.invoice_id
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the number of items in the cart. Each different item in the cart may have different quantities, and this method will return the sum of that.
|
58
|
+
# For example if the first item has a quantity of 2 and the second has a quantity of 3, this method will return 5
|
59
|
+
def quantity
|
60
|
+
@storage_engine.quantity
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the subtotal of cart, which is effectively the total of all the items multiplied by their quantites. Does NOT include order_totals
|
64
|
+
def sub_total
|
65
|
+
@storage_engine.sub_total
|
66
|
+
end
|
67
|
+
|
68
|
+
# Adds an item (or a quantity of that item) to the cart. If the item already exists, the internal quantity will be incremented by the quantity paramater
|
69
|
+
def add_to_cart(item, quantity = 1)
|
70
|
+
@storage_engine.add_to_cart(item, quantity)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Removes an item (or a quantity of that item) from the cart. If final total is 0, the item will be removed from the cart
|
74
|
+
def remove_from_cart(item, quantity = 1)
|
75
|
+
@storage_engine.remove_from_cart(item, quantity)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the total of the cart. THis includes all the order_total calculations
|
79
|
+
def total
|
80
|
+
sub_total + order_total_calculators.total
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActiveCart
|
2
|
+
module CartStorage
|
3
|
+
def invoice_id
|
4
|
+
raise NotImplementedError
|
5
|
+
end
|
6
|
+
|
7
|
+
def sub_total
|
8
|
+
inject(0) { |t, item| t + (item.quantity * item.price) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def quantity
|
12
|
+
inject(0) { |t, item| t + item.quantity }
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_to_cart(item, quantity = 1)
|
16
|
+
if self.include?(item)
|
17
|
+
index = self.index(item)
|
18
|
+
self.at(index).quantity += quantity
|
19
|
+
else
|
20
|
+
item.quantity += quantity
|
21
|
+
self << item
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_from_cart(item, quantity = 1)
|
26
|
+
if self.include?(item)
|
27
|
+
index = self.index(item)
|
28
|
+
if (existing = self.at(index)).quantity - quantity > 0
|
29
|
+
existing.quantity = existing.quantity - quantity
|
30
|
+
else
|
31
|
+
self.delete_at(index)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActiveCart
|
2
|
+
module OrderTotal
|
3
|
+
def active?
|
4
|
+
@active || false
|
5
|
+
end
|
6
|
+
|
7
|
+
def active=(active)
|
8
|
+
@active = active
|
9
|
+
end
|
10
|
+
|
11
|
+
def price(cart)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def description
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveCart
|
2
|
+
class OrderTotalCollection < Array
|
3
|
+
# Create a new collection
|
4
|
+
def initialize(cart, *seed)
|
5
|
+
@cart = cart
|
6
|
+
seed.each do |s|
|
7
|
+
self.push(s)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Created a new collection that is the concatenations of the old collection and the supplied collection. The supplied collections can be a normal array.
|
12
|
+
def +(tc)
|
13
|
+
tmp = OrderTotalCollection.new(@cart)
|
14
|
+
self.each { |s| tmp << s }
|
15
|
+
tc.each { |s| tmp << s }
|
16
|
+
tmp
|
17
|
+
end
|
18
|
+
|
19
|
+
# Inserts the items before the item that is currently at the supplied index
|
20
|
+
def insert_before(index, *items)
|
21
|
+
items.reverse.each do |item|
|
22
|
+
self.insert(index, item)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#Inserts the items after the item that is currently at the supplied index
|
27
|
+
def insert_after(index, *items)
|
28
|
+
items.each_with_index do |item, i|
|
29
|
+
self.insert(index + i + 1, item)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Allows you to reorder the order totals. Moves the item at index <em>from</em> to index <em>to</em>
|
34
|
+
def move(from, to)
|
35
|
+
index = self.delete_at(from)
|
36
|
+
self.insert(to, index)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Calculates the total variation caused by the order total objects
|
40
|
+
def total
|
41
|
+
self.inject(0) { |t, calculator| t + (calculator.active? ? calculator.price(@cart) : 0) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class TestItem
|
2
|
+
attr_accessor :id, :price, :quantity
|
3
|
+
|
4
|
+
def ==(item)
|
5
|
+
self.id == item.id
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(id = 1)
|
9
|
+
self.id = id
|
10
|
+
self.quantity = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def price
|
14
|
+
@price || 2
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect
|
18
|
+
"TestItem: #{self.id}: #{self.quantity}x$#{self.price}"
|
19
|
+
end
|
20
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$:.unshift(File.join(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'redgreen'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'shoulda'
|
8
|
+
require 'mocha'
|
9
|
+
|
10
|
+
require 'active_cart'
|
11
|
+
require 'mocks/test_cart_storage'
|
12
|
+
require 'mocks/test_item'
|
13
|
+
require 'mocks/test_order_total'
|
14
|
+
|
15
|
+
class Test::Unit::TestCase
|
16
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CartStorageTest < Test::Unit::TestCase
|
4
|
+
context '' do
|
5
|
+
setup do
|
6
|
+
@cart_storage_engine = TestCartStorage.new
|
7
|
+
@cart = ActiveCart::Cart.setup(@cart_storage_engine)
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'sub_total' do
|
11
|
+
setup do
|
12
|
+
@item_1 = TestItem.new(1)
|
13
|
+
@item_2 = TestItem.new(2)
|
14
|
+
@item_3 = TestItem.new(3)
|
15
|
+
@item_1.price = 10
|
16
|
+
@item_2.price = 12
|
17
|
+
@item_3.price = 9
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
should 'return the price of a single item in the cart' do
|
22
|
+
@cart.add_to_cart(@item_1)
|
23
|
+
assert_equal 10, @cart.sub_total
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'return the price of a single item with a quantity' do
|
27
|
+
@cart.add_to_cart(@item_2, 3)
|
28
|
+
assert_equal 36, @cart.sub_total
|
29
|
+
end
|
30
|
+
|
31
|
+
should 'return the sum of all the items in the cart' do
|
32
|
+
@cart.add_to_cart(@item_1)
|
33
|
+
@cart.add_to_cart(@item_2, 3)
|
34
|
+
assert_equal 46, @cart.sub_total
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'add to cart' do
|
39
|
+
should 'add an item to the cart if the cart is empty' do
|
40
|
+
assert @cart.empty?
|
41
|
+
item = TestItem.new
|
42
|
+
@cart.add_to_cart(item)
|
43
|
+
assert_equal 1, @cart.size
|
44
|
+
assert_equal 1, @cart[0].quantity
|
45
|
+
assert_equal 1, @cart.quantity
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'increase the item quantity if the same item is added to the cart again' do
|
49
|
+
assert @cart.empty?
|
50
|
+
item = TestItem.new(1)
|
51
|
+
@cart.add_to_cart(item)
|
52
|
+
assert_equal 1, @cart.size
|
53
|
+
assert_equal 1, @cart[0].quantity
|
54
|
+
|
55
|
+
item_2 = TestItem.new(1) # Has the same id, is the same as item
|
56
|
+
@cart.add_to_cart(item_2)
|
57
|
+
assert_equal 1, @cart.size
|
58
|
+
assert_equal 2, @cart[0].quantity
|
59
|
+
assert_equal 2, @cart.quantity
|
60
|
+
end
|
61
|
+
|
62
|
+
should 'increase the item quantity by the supplied number if the same item is add to the cart again and a quantity is supplied' do
|
63
|
+
assert @cart.empty?
|
64
|
+
item = TestItem.new(1)
|
65
|
+
@cart.add_to_cart(item)
|
66
|
+
assert_equal 1, @cart.size
|
67
|
+
assert_equal 1, @cart[0].quantity
|
68
|
+
|
69
|
+
item_2 = TestItem.new(1) # Has the same id, is the same as item
|
70
|
+
@cart.add_to_cart(item_2, 10)
|
71
|
+
assert_equal 1, @cart.size
|
72
|
+
assert_equal 11, @cart[0].quantity
|
73
|
+
assert_equal 11, @cart.quantity
|
74
|
+
end
|
75
|
+
|
76
|
+
should 'add another item to the cart' do
|
77
|
+
assert @cart.empty?
|
78
|
+
item = TestItem.new(1)
|
79
|
+
@cart.add_to_cart(item)
|
80
|
+
assert_equal 1, @cart.size
|
81
|
+
assert_equal 1, @cart[0].quantity
|
82
|
+
|
83
|
+
item_2 = TestItem.new(2)
|
84
|
+
@cart.add_to_cart(item_2, 10)
|
85
|
+
assert_equal 2, @cart.size
|
86
|
+
assert_equal 1, @cart[0].quantity
|
87
|
+
assert_equal 10, @cart[1].quantity
|
88
|
+
assert_equal 11, @cart.quantity
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'remove_from_cart' do
|
93
|
+
should 'remove the quantity supplied from the cart' do
|
94
|
+
item = TestItem.new(1)
|
95
|
+
@cart.add_to_cart(item, 10)
|
96
|
+
assert_equal 1, @cart.size
|
97
|
+
assert_equal 10, @cart.quantity
|
98
|
+
|
99
|
+
@cart.remove_from_cart(item)
|
100
|
+
assert_equal 1, @cart.size
|
101
|
+
assert_equal 9, @cart.quantity
|
102
|
+
end
|
103
|
+
|
104
|
+
should 'remove the item from the cart if the quantity to be removed is equal to the number in cart' do
|
105
|
+
item = TestItem.new(1)
|
106
|
+
@cart.add_to_cart(item, 10)
|
107
|
+
assert_equal 1, @cart.size
|
108
|
+
assert_equal 10, @cart.quantity
|
109
|
+
|
110
|
+
@cart.remove_from_cart(item, 10)
|
111
|
+
assert_equal 0, @cart.size
|
112
|
+
end
|
113
|
+
|
114
|
+
should 'remove the item from the cart if the quantity to be removed is greater than the number in cart' do
|
115
|
+
item = TestItem.new(1)
|
116
|
+
@cart.add_to_cart(item, 10)
|
117
|
+
assert_equal 1, @cart.size
|
118
|
+
assert_equal 10, @cart.quantity
|
119
|
+
|
120
|
+
@cart.remove_from_cart(item, 11)
|
121
|
+
assert_equal 0, @cart.size
|
122
|
+
end
|
123
|
+
|
124
|
+
should "simply return if the item doesn't exist in the cart" do
|
125
|
+
item = TestItem.new(1)
|
126
|
+
@cart.add_to_cart(item, 10)
|
127
|
+
assert_equal 1, @cart.size
|
128
|
+
assert_equal 10, @cart.quantity
|
129
|
+
|
130
|
+
item_2 = TestItem.new(2)
|
131
|
+
@cart.remove_from_cart(item_2, 10)
|
132
|
+
assert_equal 1, @cart.size
|
133
|
+
assert_equal 10, @cart.quantity
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CartTest < Test::Unit::TestCase
|
4
|
+
context '' do
|
5
|
+
should 'raise exception if instance is called without calling setup first' do
|
6
|
+
assert_raise StandardError do
|
7
|
+
ActiveCart::Cart.instance_variable_set(:@setup_called, false)
|
8
|
+
ActiveCart::Cart.instance
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'after setup' do
|
13
|
+
setup do
|
14
|
+
@cart_storage_engine = TestCartStorage.new
|
15
|
+
@cart = ActiveCart::Cart.setup(@cart_storage_engine)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'delegate to cart storage' do
|
19
|
+
should 'delegate []' do
|
20
|
+
@cart_storage_engine.expects(:[]).with(0)
|
21
|
+
@cart[0]
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'delegate <<' do
|
25
|
+
test = TestItem.new
|
26
|
+
@cart_storage_engine.expects(:<<).with(test)
|
27
|
+
@cart << test
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'delegate []=' do
|
31
|
+
test = TestItem.new
|
32
|
+
@cart_storage_engine.expects(:[]=).with(0, test)
|
33
|
+
@cart[0] = test
|
34
|
+
end
|
35
|
+
|
36
|
+
should 'delegate :at' do
|
37
|
+
@cart_storage_engine.expects(:at).with(1)
|
38
|
+
@cart.at(1)
|
39
|
+
end
|
40
|
+
|
41
|
+
should 'delegate :clear' do
|
42
|
+
@cart_storage_engine.expects(:clear)
|
43
|
+
@cart.clear
|
44
|
+
end
|
45
|
+
|
46
|
+
should 'delegate :collect' do
|
47
|
+
@cart_storage_engine.expects(:collect)
|
48
|
+
@cart.collect
|
49
|
+
end
|
50
|
+
|
51
|
+
should 'delegate :map' do
|
52
|
+
@cart_storage_engine.expects(:map)
|
53
|
+
@cart.map
|
54
|
+
end
|
55
|
+
|
56
|
+
should 'delegate :delete' do
|
57
|
+
test = TestItem.new
|
58
|
+
@cart_storage_engine.expects(:delete).with(test)
|
59
|
+
@cart.delete(test)
|
60
|
+
end
|
61
|
+
|
62
|
+
should 'delegate :delete_at' do
|
63
|
+
@cart_storage_engine.expects(:delete_at).with(3)
|
64
|
+
@cart.delete_at(3)
|
65
|
+
end
|
66
|
+
|
67
|
+
should 'delegate :each' do
|
68
|
+
@cart_storage_engine.expects(:each)
|
69
|
+
@cart.each
|
70
|
+
end
|
71
|
+
|
72
|
+
should 'delegate :each_index' do
|
73
|
+
@cart_storage_engine.expects(:each_index)
|
74
|
+
@cart.each_index
|
75
|
+
end
|
76
|
+
|
77
|
+
should 'delegate :empty' do
|
78
|
+
@cart_storage_engine.expects(:empty?)
|
79
|
+
@cart.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
should 'delegate :eql?' do
|
83
|
+
@cart_storage_engine.expects(:eql?)
|
84
|
+
@cart.eql?
|
85
|
+
end
|
86
|
+
|
87
|
+
should 'delegate :first' do
|
88
|
+
@cart_storage_engine.expects(:first)
|
89
|
+
@cart.first
|
90
|
+
end
|
91
|
+
|
92
|
+
should 'delegate :include?' do
|
93
|
+
@cart_storage_engine.expects(:include?)
|
94
|
+
@cart.include?
|
95
|
+
end
|
96
|
+
|
97
|
+
should 'delegate :index' do
|
98
|
+
@cart_storage_engine.expects(:index)
|
99
|
+
@cart.index
|
100
|
+
end
|
101
|
+
|
102
|
+
should 'delegate :inject' do
|
103
|
+
@cart_storage_engine.expects(:inject)
|
104
|
+
@cart.inject
|
105
|
+
end
|
106
|
+
|
107
|
+
should 'delegate :last' do
|
108
|
+
@cart_storage_engine.expects(:last)
|
109
|
+
@cart.last
|
110
|
+
end
|
111
|
+
|
112
|
+
should 'delegate :length' do
|
113
|
+
@cart_storage_engine.expects(:length)
|
114
|
+
@cart.length
|
115
|
+
end
|
116
|
+
|
117
|
+
should 'delegate :pop' do
|
118
|
+
@cart_storage_engine.expects(:pop)
|
119
|
+
@cart.pop
|
120
|
+
end
|
121
|
+
|
122
|
+
should 'delegate :push' do
|
123
|
+
@cart_storage_engine.expects(:push)
|
124
|
+
@cart.push
|
125
|
+
end
|
126
|
+
|
127
|
+
should 'delegate :shift' do
|
128
|
+
@cart_storage_engine.expects(:shift)
|
129
|
+
@cart.shift
|
130
|
+
end
|
131
|
+
|
132
|
+
should 'delegate :size' do
|
133
|
+
@cart_storage_engine.expects(:size)
|
134
|
+
@cart.size
|
135
|
+
end
|
136
|
+
|
137
|
+
should 'delegate :unshift' do
|
138
|
+
@cart_storage_engine.expects(:unshift)
|
139
|
+
@cart.unshift
|
140
|
+
end
|
141
|
+
|
142
|
+
should 'delegate :invoice_id' do
|
143
|
+
@cart_storage_engine.expects(:invoice_id)
|
144
|
+
@cart.invoice_id
|
145
|
+
end
|
146
|
+
|
147
|
+
should 'delegate :sub_total' do
|
148
|
+
@cart_storage_engine.expects(:sub_total)
|
149
|
+
@cart.sub_total
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'setup' do
|
154
|
+
should 'take a block to add order_totals' do
|
155
|
+
@total_1 = TestOrderTotal.new(10, true)
|
156
|
+
@total_2 = TestOrderTotal.new(20, true)
|
157
|
+
|
158
|
+
@cart_storage_engine = TestCartStorage.new
|
159
|
+
@cart = ActiveCart::Cart.setup(@cart_storage_engine) do |o|
|
160
|
+
o << @total_1
|
161
|
+
o << @total_2
|
162
|
+
end
|
163
|
+
assert_equal [ @total_1, @total_2 ], @cart.order_total_calculators
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'total' do
|
168
|
+
should 'sum all the items in the cart with order totals' do
|
169
|
+
@item_1 = TestItem.new(1)
|
170
|
+
@item_1.price = 10
|
171
|
+
@item_2 = TestItem.new(2)
|
172
|
+
@item_2.price = 20
|
173
|
+
@item_3 = TestItem.new(3)
|
174
|
+
@item_3.price = 30
|
175
|
+
@total_1 = TestOrderTotal.new(10, true)
|
176
|
+
@total_2 = TestOrderTotal.new(20, true)
|
177
|
+
|
178
|
+
@cart.order_total_calculators += [ @total_1, @total_2 ]
|
179
|
+
@cart.add_to_cart(@item_1)
|
180
|
+
@cart.add_to_cart(@item_2)
|
181
|
+
@cart.add_to_cart(@item_3)
|
182
|
+
|
183
|
+
assert_equal 90, @cart.total
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OrderTotalCollectionTest < Test::Unit::TestCase
|
4
|
+
context '' do
|
5
|
+
setup do
|
6
|
+
@cart_storage_engine = TestCartStorage.new
|
7
|
+
@cart = ActiveCart::Cart.setup(@cart_storage_engine)
|
8
|
+
@collection = ActiveCart::OrderTotalCollection.new(@cart)
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'insert_before' do
|
12
|
+
should 'insert an object before the item at the supplied index' do
|
13
|
+
@collection << '0'
|
14
|
+
@collection << '1'
|
15
|
+
@collection << '2'
|
16
|
+
@collection << '3'
|
17
|
+
@collection << '4'
|
18
|
+
|
19
|
+
@collection.insert_before(3, '5')
|
20
|
+
assert_equal [ '0', '1', '2', '5', '3', '4' ], @collection
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'insert all the objects before the item at the supplied index' do
|
24
|
+
@collection << '0'
|
25
|
+
@collection << '1'
|
26
|
+
@collection << '2'
|
27
|
+
@collection << '3'
|
28
|
+
@collection << '4'
|
29
|
+
|
30
|
+
@collection.insert_before(3, '5', '6', '7', '8')
|
31
|
+
assert_equal [ '0', '1', '2', '5', '6', '7', '8', '3', '4' ], @collection
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'insert_after' do
|
37
|
+
should 'insert an object after the item at the supplied index' do
|
38
|
+
@collection << '0'
|
39
|
+
@collection << '1'
|
40
|
+
@collection << '2'
|
41
|
+
@collection << '3'
|
42
|
+
@collection << '4'
|
43
|
+
|
44
|
+
@collection.insert_after(3, '5')
|
45
|
+
assert_equal [ '0', '1', '2', '3', '5', '4' ], @collection
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'insert all the objects after the item at the supplied index' do
|
49
|
+
@collection << '0'
|
50
|
+
@collection << '1'
|
51
|
+
@collection << '2'
|
52
|
+
@collection << '3'
|
53
|
+
@collection << '4'
|
54
|
+
|
55
|
+
@collection.insert_after(3, '5', '6', '7', '8')
|
56
|
+
assert_equal [ '0', '1', '2', '3', '5', '6', '7', '8', '4' ], @collection
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'move' do
|
61
|
+
should 'move the item at the from index to the to index' do
|
62
|
+
@collection << '0'
|
63
|
+
@collection << '1'
|
64
|
+
@collection << '2'
|
65
|
+
@collection << '3'
|
66
|
+
@collection << '4'
|
67
|
+
|
68
|
+
@collection.move(3, 0)
|
69
|
+
assert_equal [ '3', '0', '1', '2', '4' ], @collection
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'total' do
|
74
|
+
setup do
|
75
|
+
@total_1 = TestOrderTotal.new(10, true)
|
76
|
+
@total_2 = TestOrderTotal.new(5, false)
|
77
|
+
@total_3 = TestOrderTotal.new(2, true)
|
78
|
+
@total_4 = TestOrderTotal.new(14, true)
|
79
|
+
end
|
80
|
+
|
81
|
+
should 'call price on each order_total item that are active' do
|
82
|
+
@collection += [ @total_1, @total_2, @total_3, @total_4 ]
|
83
|
+
assert_equal 26, @collection.total
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active-cart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Myles Eftos
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-25 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: You can use active-cart as the basis of a shopping cart system. It's definately not complete, you need to build a website around it.
|
17
|
+
email: myles@madpilot.com.au
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- README
|
27
|
+
- Rakefile
|
28
|
+
- generators/schwacms-gallery/schwacms_gallery_generator.rb
|
29
|
+
- generators/schwacms-gallery/templates/schwacms_gallery_migration.rb
|
30
|
+
- install.rb
|
31
|
+
- lib/active_cart.rb
|
32
|
+
- lib/active_cart/cart.rb
|
33
|
+
- lib/active_cart/cart_storage.rb
|
34
|
+
- lib/active_cart/order_total.rb
|
35
|
+
- lib/active_cart/order_total_collection.rb
|
36
|
+
- test/mocks/test_cart_storage.rb
|
37
|
+
- test/mocks/test_item.rb
|
38
|
+
- test/mocks/test_order_total.rb
|
39
|
+
- test/performance/browsing_test.rb
|
40
|
+
- test/test_helper.rb
|
41
|
+
- test/unit/cart_storage_test.rb
|
42
|
+
- test/unit/cart_test.rb
|
43
|
+
- test/unit/order_total_collection_test.rb
|
44
|
+
- uninstall.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://gemcutter.org/gems/active-cart
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options:
|
51
|
+
- --charset=UTF-8
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.5
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Shopping Cart framework gem. Supports 'storage engines' and order total plugins
|
73
|
+
test_files:
|
74
|
+
- test/unit/order_total_collection_test.rb
|
75
|
+
- test/unit/cart_storage_test.rb
|
76
|
+
- test/unit/cart_test.rb
|
77
|
+
- test/mocks/test_cart_storage.rb
|
78
|
+
- test/mocks/test_order_total.rb
|
79
|
+
- test/mocks/test_item.rb
|
80
|
+
- test/test_helper.rb
|
81
|
+
- test/performance/browsing_test.rb
|