spree_piwik 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.
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