spree_piwik 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +14 -0
  3. data/.hound.yml +2 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +7 -0
  7. data/README.md +41 -0
  8. data/Rakefile +21 -0
  9. data/app/assets/javascripts/spree/backend/spree_piwik.js +2 -0
  10. data/app/assets/javascripts/spree/frontend/spree_piwik.js +2 -0
  11. data/app/assets/stylesheets/spree/backend/spree_piwik.css +4 -0
  12. data/app/assets/stylesheets/spree/frontend/spree_piwik.css +4 -0
  13. data/app/helpers/spree/base_helper_decorator.rb +5 -0
  14. data/app/models/spree/piwik/client.rb +29 -0
  15. data/app/models/spree/piwik/line_item.rb +44 -0
  16. data/app/models/spree/piwik_configuration.rb +4 -0
  17. data/app/overrides/add_piwik_tracking_tag_to_layout.rb +5 -0
  18. data/app/views/spree/_ecommerce_item.html.erb +7 -0
  19. data/app/views/spree/_ecommerce_view.html.erb +6 -0
  20. data/app/views/spree/_piwik.html.erb +19 -0
  21. data/bin/rails +7 -0
  22. data/config/.jshint.json +3 -0
  23. data/config/locales/en.yml +5 -0
  24. data/config/routes.rb +3 -0
  25. data/config/spring.rb +1 -0
  26. data/lib/generators/spree_piwik/install/install_generator.rb +32 -0
  27. data/lib/spree/piwik/engine.rb +32 -0
  28. data/lib/spree_piwik.rb +2 -0
  29. data/spec/features/interact_with_cart_spec.rb +49 -0
  30. data/spec/features/visit_home_pages_spec.rb +21 -0
  31. data/spec/features/visit_product_page_spec.rb +45 -0
  32. data/spec/fixtures/empty_cart.js +9 -0
  33. data/spec/fixtures/index_example_com.js +8 -0
  34. data/spec/fixtures/multiple_products_in_cart.js +23 -0
  35. data/spec/fixtures/one_product_in_cart.js +16 -0
  36. data/spec/fixtures/product_example_com.js +14 -0
  37. data/spec/fixtures/product_with_categories.js +14 -0
  38. data/spec/helpers/spree/base_helper_decorator_spec.rb +35 -0
  39. data/spec/models/spree/piwik/client_spec.rb +71 -0
  40. data/spec/models/spree/piwik/line_item_spec.rb +59 -0
  41. data/spec/models/spree/piwik_configuration_spec.rb +11 -0
  42. data/spec/overrides/add_piwik_tracking_tag_to_layout_spec.rb +20 -0
  43. data/spec/spec_helper.rb +96 -0
  44. data/spec/support/components/piwig_tag_component.rb +37 -0
  45. data/spec/support/helpers/fixture_helpers.rb +11 -0
  46. data/spree_piwik.gemspec +35 -0
  47. metadata +370 -0
@@ -0,0 +1,9 @@
1
+ var _paq = _paq || [];
2
+ (function(){ var u=(('https:' == document.location.protocol) ? 'https://example.com/' : 'http://example.com/');
3
+ _paq.push(['setSiteId', 0]);
4
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
5
+ _paq.push(['trackEcommerceCartUpdate', 0.0]);
6
+ _paq.push(['trackPageView']);
7
+ _paq.push(['enableLinkTracking']);
8
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
9
+ s.parentNode.insertBefore(g,s); })();
@@ -0,0 +1,8 @@
1
+ var _paq = _paq || [];
2
+ (function(){ var u=(('https:' == document.location.protocol) ? 'https://piwik.example.com/' : 'http://piwik.example.com/');
3
+ _paq.push(['setSiteId', 1337]);
4
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
5
+ _paq.push(['trackPageView']);
6
+ _paq.push(['enableLinkTracking']);
7
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
8
+ s.parentNode.insertBefore(g,s); })();
@@ -0,0 +1,23 @@
1
+ var _paq = _paq || [];
2
+ (function(){ var u=(('https:' == document.location.protocol) ? 'https://example.com/' : 'http://example.com/');
3
+ _paq.push(['setSiteId', 0]);
4
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
5
+ _paq.push(['addEcommerceItem',
6
+ 'SKU-1',
7
+ 'RoR Shirt',
8
+ [],
9
+ 19.99,
10
+ 1
11
+ ]);
12
+ _paq.push(['addEcommerceItem',
13
+ 'SKU-2',
14
+ 'RoR Sticker',
15
+ [],
16
+ 0.99,
17
+ 1
18
+ ]);
19
+ _paq.push(['trackEcommerceCartUpdate', 20.98]);
20
+ _paq.push(['trackPageView']);
21
+ _paq.push(['enableLinkTracking']);
22
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
23
+ s.parentNode.insertBefore(g,s); })();
@@ -0,0 +1,16 @@
1
+ var _paq = _paq || [];
2
+ (function(){ var u=(('https:' == document.location.protocol) ? 'https://example.com/' : 'http://example.com/');
3
+ _paq.push(['setSiteId', 0]);
4
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
5
+ _paq.push(['addEcommerceItem',
6
+ 'SKU-1',
7
+ 'RoR Shirt',
8
+ [],
9
+ 19.99,
10
+ 1
11
+ ]);
12
+ _paq.push(['trackEcommerceCartUpdate', 19.99]);
13
+ _paq.push(['trackPageView']);
14
+ _paq.push(['enableLinkTracking']);
15
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
16
+ s.parentNode.insertBefore(g,s); })();
@@ -0,0 +1,14 @@
1
+ var _paq = _paq || [];
2
+ (function(){ var u=(('https:' == document.location.protocol) ? 'https://example.com/' : 'http://example.com/');
3
+ _paq.push(['setSiteId', 0]);
4
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
5
+ _paq.push(['setEcommerceView',
6
+ 'SKU-1',
7
+ 'RoR Shirt',
8
+ [],
9
+ 19.99
10
+ ]);
11
+ _paq.push(['trackPageView']);
12
+ _paq.push(['enableLinkTracking']);
13
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
14
+ s.parentNode.insertBefore(g,s); })();
@@ -0,0 +1,14 @@
1
+ var _paq = _paq || [];
2
+ (function(){ var u=(('https:' == document.location.protocol) ? 'https://example.com/' : 'http://example.com/');
3
+ _paq.push(['setSiteId', 0]);
4
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
5
+ _paq.push(['setEcommerceView',
6
+ 'SKU-1',
7
+ 'RoR Shirt',
8
+ ["shirts","ror","webdev"],
9
+ 19.99
10
+ ]);
11
+ _paq.push(['trackPageView']);
12
+ _paq.push(['enableLinkTracking']);
13
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
14
+ s.parentNode.insertBefore(g,s); })();
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::BaseHelper, type: :helper do
4
+ describe "#piwik_client" do
5
+ it 'returns a PiwikClient' do
6
+ expect(helper.piwik_client).to be_an_instance_of(Spree::Piwik::Client)
7
+ end
8
+
9
+ it 'memoizes the piwik_client' do
10
+ expect(helper.piwik_client).to be helper.piwik_client
11
+ end
12
+
13
+ context 'when there is an @product' do
14
+ before { @product = assign(:product, double(:product)) }
15
+ it 'passes in @product' do
16
+ expect(Spree::Piwik::Client).to receive(:new).with(hash_including(product: @product))
17
+ helper.piwik_client
18
+ end
19
+ end
20
+
21
+ context 'when there is no @product' do
22
+ it 'passes in nil' do
23
+ expect(helper.piwik_client.product).to be_nil
24
+ end
25
+ end
26
+
27
+ context 'when there is an @order' do
28
+ before { @order = assign(:order, double(:order)) }
29
+ it 'passes in the order' do
30
+ expect(Spree::Piwik::Client).to receive(:new).with(hash_including(order: @order))
31
+ helper.piwik_client
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Piwik::Client, type: :model do
4
+ it 'fetches the url from preferences' do
5
+ allow(Spree::Piwik::Config).to receive(:preferred_piwik_url).and_return 'piwik.example.com'
6
+ expect(subject.url).to eq 'piwik.example.com'
7
+ end
8
+
9
+ it 'fetches the piwik_id from preferences' do
10
+ allow(Spree::Piwik::Config).to receive(:preferred_piwik_id).and_return 1337
11
+ expect(subject.site_id).to eq 1337
12
+ end
13
+
14
+ describe '#product' do
15
+ context 'when it has a product' do
16
+ before { subject.product = double(:product, sku: 'sku', name: nil, price: nil, taxons: []) }
17
+ it 'is an line_item with that product' do
18
+ expect(subject.product).to be_a_kind_of Spree::Piwik::LineItem
19
+ expect(subject.product.sku).to eq 'sku'
20
+ end
21
+ end
22
+
23
+ context 'when it has no product' do
24
+ before { subject.product = nil }
25
+ it 'is nil' do
26
+ expect(subject.product).to be_nil
27
+ end
28
+ end
29
+ end
30
+
31
+ describe '#order' do
32
+ it 'can be set on initialisation' do
33
+ order = double(:order)
34
+ expect(Spree::Piwik::Client.new(order: order).order).to eq order
35
+ end
36
+ end
37
+
38
+ describe '#ecommerce_items' do
39
+ context 'when order is set' do
40
+ it 'has the ine_items in the order' do
41
+ product = double(:product, sku: 'sku', name: 'name', price: 'price', quantity: 1)
42
+ subject.order = double(:order, line_items: [product])
43
+ expect(subject.ecommerce_items.first).to be_a_kind_of Spree::Piwik::LineItem
44
+ expect(subject.ecommerce_items.first.sku).to eq 'sku'
45
+ expect(subject.ecommerce_items.first.quantity).to eq 1
46
+ end
47
+ end
48
+ end
49
+
50
+ describe '#track_cart_update?' do
51
+ context 'when order with state cart is set' do
52
+ it 'is true' do
53
+ order = double(:order, cart?: true)
54
+ expect(Spree::Piwik::Client.new(order: order).track_cart_update?).to eq true
55
+ end
56
+ end
57
+
58
+ context 'when order state is not cart' do
59
+ it 'is false' do
60
+ order = double(:order, cart?: false)
61
+ expect(Spree::Piwik::Client.new(order: order).track_cart_update?).to eq false
62
+ end
63
+ end
64
+
65
+ context 'when order is empty' do
66
+ it 'is false' do
67
+ expect(subject.track_cart_update?).to eq false
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Piwik::LineItem, type: :model do
4
+ describe '.from_product_ish' do
5
+ let(:product) { double(:product, sku: 'sku', name: 'name', price: 'price', quantity: 'quantity', taxons: []) }
6
+ let(:line_item) { Spree::Piwik::LineItem.from_product_ish(product) }
7
+
8
+ it 'instantiates self from a line_item-ish item' do
9
+ expect(line_item).to be_a_kind_of Spree::Piwik::LineItem
10
+ expect(line_item.sku).to eq 'sku'
11
+ expect(line_item.name).to eq 'name'
12
+ expect(line_item.price).to eq 'price'
13
+ expect(line_item.quantity).to eq 'quantity'
14
+ expect(line_item.categories).to eq []
15
+ end
16
+
17
+ describe '#categories' do
18
+ let(:taxon) { double(:taxon, name: 'shirts') }
19
+ context 'when it has a product with taxons' do
20
+ before { allow(product).to receive(:taxons).and_return([taxon]) }
21
+ it 'returns the name of the taxons of the product' do
22
+ expect(line_item.categories).to match_array ['shirts']
23
+ end
24
+ end
25
+
26
+ context 'when it has a product with more then 5 taxons' do
27
+ before { allow(product).to receive(:taxons).and_return(Array.new(6, taxon)) }
28
+ it 'limits the categories to five items' do
29
+ expect(line_item.categories.length).to eq 5
30
+ end
31
+ end
32
+
33
+ context 'when it has a product with no taxons' do
34
+ before { allow(product).to receive(:taxons).and_return([]) }
35
+ it 'returns an empty array' do
36
+ expect(line_item.categories).to eq []
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#sku' do
43
+ it { expect(subject).to respond_to :sku }
44
+ it { expect(subject).to respond_to :sku= }
45
+ end
46
+ describe '#name' do
47
+ it { expect(subject).to respond_to :name }
48
+ it { expect(subject).to respond_to :name= }
49
+ end
50
+ describe '#price' do
51
+ it { expect(subject).to respond_to :price }
52
+ it { expect(subject).to respond_to :price= }
53
+ end
54
+ describe '#quantity' do
55
+ it { expect(subject).to respond_to :quantity }
56
+ it { expect(subject).to respond_to :quantity= }
57
+ end
58
+
59
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe Spree::PiwikConfiguration do
4
+ it 'has a default piwik_url example.com' do
5
+ expect(Spree::Piwik::Config.preferred_piwik_url).to eq 'example.com'
6
+ end
7
+
8
+ it 'has a default piwik_id 0' do
9
+ expect(Spree::Piwik::Config.preferred_piwik_id).to eq 0
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "deface override call" do
4
+ subject { Deface::Override.find(virtual_path: "spree/layouts/spree_application").first }
5
+
6
+ it "triggers on spree_application layout" do
7
+ expect(subject.name).to eq "add_piwik_tracking_tag_to_layout"
8
+ end
9
+
10
+ it "inserts at the bottom of the body tag" do
11
+ selector = %([data-hook='body'])
12
+ expect(subject.selector).to eq selector
13
+ expect(subject.args[:insert_bottom]).to eq selector
14
+ end
15
+
16
+ it "users spree/piwik partial" do
17
+ expect(subject.source_argument).to eq :partial
18
+ expect(subject.args[:partial]).to eq 'spree/piwik'
19
+ end
20
+ end
@@ -0,0 +1,96 @@
1
+ # Run Coverage report
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter 'spec/dummy'
5
+ add_group 'Controllers', 'app/controllers'
6
+ add_group 'Helpers', 'app/helpers'
7
+ add_group 'Mailers', 'app/mailers'
8
+ add_group 'Models', 'app/models'
9
+ add_group 'Views', 'app/views'
10
+ add_group 'Libraries', 'lib'
11
+ end
12
+
13
+ # Configure Rails Environment
14
+ ENV['RAILS_ENV'] = 'test'
15
+
16
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
17
+
18
+ require 'rspec/rails'
19
+ require 'launchy'
20
+ require 'database_cleaner'
21
+ require 'ffaker'
22
+
23
+ # Requires supporting ruby files with custom matchers and macros, etc,
24
+ # in spec/support/ and its subdirectories.
25
+ Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
26
+
27
+ # Requires factories and other useful helpers defined in spree_core.
28
+ require 'spree/testing_support/authorization_helpers'
29
+ require 'spree/testing_support/capybara_ext'
30
+ require 'spree/testing_support/controller_requests'
31
+ require 'spree/testing_support/factories'
32
+ require 'spree/testing_support/url_helpers'
33
+ require 'spree/testing_support/preferences'
34
+
35
+ RSpec.configure do |config|
36
+ config.include FactoryGirl::Syntax::Methods
37
+
38
+ # Infer an example group's spec type from the file location.
39
+ config.infer_spec_type_from_file_location!
40
+
41
+ # == URL Helpers
42
+ #
43
+ # Allows access to Spree's routes in specs:
44
+ #
45
+ # visit spree.admin_path
46
+ # current_path.should eql(spree.products_path)
47
+ config.include Spree::TestingSupport::UrlHelpers
48
+
49
+ # Allow resetting of config.
50
+ config.include Spree::TestingSupport::Preferences
51
+
52
+ ## == Fixture Helpers
53
+ #
54
+ # Allows access to fixture files
55
+ config.include FixtureHelpers
56
+
57
+ # == Mock Framework
58
+ #
59
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
60
+ #
61
+ # config.mock_with :mocha
62
+ # config.mock_with :flexmock
63
+ # config.mock_with :rr
64
+ config.mock_with :rspec
65
+ config.color = true
66
+
67
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
68
+ config.fixture_path = File.join(File.dirname(__FILE__), 'fixtures')
69
+
70
+ # Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner
71
+ # to cleanup after each test instead. Without transactional fixtures set to false the records created
72
+ # to setup a test will be unavailable to the browser, which runs under a separate server instance.
73
+ config.use_transactional_fixtures = false
74
+
75
+ # Ensure Suite is set to use transactions for speed.
76
+ config.before :suite do
77
+ DatabaseCleaner.strategy = :transaction
78
+ DatabaseCleaner.clean_with :truncation
79
+ end
80
+
81
+ # Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary.
82
+ config.before :each do
83
+ DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction
84
+ DatabaseCleaner.start
85
+
86
+ reset_spree_preferences
87
+ end
88
+
89
+ # After each spec clean the database.
90
+ config.after :each do
91
+ DatabaseCleaner.clean
92
+ end
93
+
94
+ config.fail_fast = ENV['FAIL_FAST'] || false
95
+ config.order = "random"
96
+ end
@@ -0,0 +1,37 @@
1
+ require 'rkelly'
2
+
3
+ class PiwikTagComponent
4
+ extend Capybara::DSL
5
+ include Capybara::DSL
6
+
7
+ def in_html?
8
+ return false if script_tag.empty?
9
+ page.body.include?('<!-- Piwik -->') && page.body.include?('<!-- End Piwik Code -->')
10
+ end
11
+
12
+ def tracker_url_assigment
13
+ script_tag.to_s.lines.find { |l| l.match(/var u=/) }.strip
14
+ end
15
+
16
+ def to_s
17
+ script_tag.to_s
18
+ end
19
+
20
+ def as_ecma
21
+ parser.parse(script_tag.text).to_ecma
22
+ end
23
+
24
+ private
25
+
26
+ def parser
27
+ @parser ||= RKelly::Parser.new
28
+ end
29
+
30
+ def script_tag
31
+ doc.xpath('//body/script')
32
+ end
33
+
34
+ def doc
35
+ Nokogiri::HTML(page.body)
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ module FixtureHelpers
2
+ def fixture(filename)
3
+ parser.parse(File.read(File.join(fixture_path, filename))).to_ecma
4
+ end
5
+
6
+ private
7
+
8
+ def parser
9
+ @parser ||= RKelly::Parser.new
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+ Gem::Specification.new do |s|
3
+ s.platform = Gem::Platform::RUBY
4
+ s.name = 'spree_piwik'
5
+ s.version = '0.0.1'
6
+ s.summary = 'Adds piwik tracking with Ecommerce tracking'
7
+ s.description = File.read(File.join(File.dirname(__FILE__), 'README.md'))
8
+ s.required_ruby_version = '>= 1.9.3'
9
+
10
+ s.author = 'Bèr Kessels'
11
+ s.email = 'ber@berk.es'
12
+ s.homepage = 'http://berk.es'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_path = 'lib'
17
+ s.requirements << 'none'
18
+
19
+ s.add_dependency 'spree_core', '~> 2.3.6'
20
+
21
+ s.add_development_dependency 'therubyracer'
22
+ s.add_development_dependency 'capybara', '~> 2.4'
23
+ s.add_development_dependency 'coffee-rails'
24
+ s.add_development_dependency 'database_cleaner'
25
+ s.add_development_dependency 'factory_girl', '~> 4.5'
26
+ s.add_development_dependency 'ffaker'
27
+ s.add_development_dependency 'rspec-rails', '~> 3.1'
28
+ s.add_development_dependency 'spring-commands-rspec'
29
+ s.add_development_dependency 'rkelly-remix'
30
+ s.add_development_dependency 'launchy'
31
+ s.add_development_dependency 'sass-rails', '~> 4.0.2'
32
+ s.add_development_dependency 'selenium-webdriver'
33
+ s.add_development_dependency 'simplecov'
34
+ s.add_development_dependency 'sqlite3'
35
+ end