disco_app 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/disco_app/install_controller.rb +1 -1
  3. data/app/jobs/disco_app/concerns/app_installed_job.rb +4 -4
  4. data/app/jobs/disco_app/concerns/render_asset_group_job.rb +8 -0
  5. data/app/jobs/disco_app/concerns/shop_update_job.rb +1 -1
  6. data/app/jobs/disco_app/concerns/subscription_changed_job.rb +1 -1
  7. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +1 -1
  8. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +1 -1
  9. data/app/jobs/disco_app/render_asset_group_job.rb +3 -0
  10. data/app/jobs/disco_app/shop_job.rb +1 -1
  11. data/app/models/disco_app/concerns/renders_assets.rb +148 -0
  12. data/app/services/disco_app/subscription_service.rb +1 -1
  13. data/lib/disco_app/version.rb +1 -1
  14. data/lib/generators/disco_app/disco_app_generator.rb +1 -2
  15. data/lib/tasks/carrier_service.rake +1 -1
  16. data/lib/tasks/shops.rake +1 -1
  17. data/lib/tasks/webhooks.rake +1 -1
  18. data/test/dummy/app/jobs/products_create_job.rb +1 -1
  19. data/test/dummy/app/jobs/products_delete_job.rb +1 -1
  20. data/test/dummy/app/jobs/products_update_job.rb +1 -1
  21. data/test/dummy/app/models/js_configuration.rb +8 -0
  22. data/test/dummy/app/models/widget_configuration.rb +10 -0
  23. data/test/dummy/app/views/assets/script_tag.js.erb +1 -0
  24. data/test/dummy/app/views/assets/test.js.erb +1 -0
  25. data/test/dummy/app/views/assets/widget.js.erb +2 -0
  26. data/test/dummy/app/views/assets/widget.scss.erb +3 -0
  27. data/test/dummy/db/migrate/20160530160739_create_asset_models.rb +19 -0
  28. data/test/dummy/db/schema.rb +16 -1
  29. data/test/fixtures/api/widget_store/assets/create_script_tag_js_request.json +6 -0
  30. data/test/fixtures/api/widget_store/assets/create_script_tag_js_response.json +12 -0
  31. data/test/fixtures/api/widget_store/assets/create_script_tag_request.json +6 -0
  32. data/test/fixtures/api/widget_store/assets/create_script_tag_response.json +10 -0
  33. data/test/fixtures/api/widget_store/assets/create_test_js_request.json +6 -0
  34. data/test/fixtures/api/widget_store/assets/create_test_js_response.json +12 -0
  35. data/test/fixtures/api/widget_store/assets/create_widget_js_request.json +6 -0
  36. data/test/fixtures/api/widget_store/assets/create_widget_js_response.json +12 -0
  37. data/test/fixtures/api/widget_store/assets/create_widget_scss_request.json +6 -0
  38. data/test/fixtures/api/widget_store/assets/create_widget_scss_response.json +12 -0
  39. data/test/fixtures/api/widget_store/assets/get_script_tags_empty_request.json +1 -0
  40. data/test/fixtures/api/widget_store/assets/get_script_tags_empty_response.json +1 -0
  41. data/test/fixtures/api/widget_store/assets/get_script_tags_preexisting_request.json +1 -0
  42. data/test/fixtures/api/widget_store/assets/get_script_tags_preexisting_response.json +12 -0
  43. data/test/fixtures/api/widget_store/assets/update_script_tag_request.json +10 -0
  44. data/test/fixtures/api/widget_store/assets/update_script_tag_response.json +10 -0
  45. data/test/fixtures/assets/test.js +1 -0
  46. data/test/fixtures/js_configurations.yml +3 -0
  47. data/test/fixtures/widget_configurations.yml +4 -0
  48. data/test/jobs/disco_app/app_installed_job_test.rb +3 -3
  49. data/test/jobs/disco_app/app_uninstalled_job_test.rb +1 -1
  50. data/test/models/disco_app/renders_assets_test.rb +100 -0
  51. data/test/support/test_shopify_api.rb +1 -1
  52. metadata +72 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e11c5ff7beaece5d87fda19c4d06bcc08ded718b71ce4050a5380c15e638be0
4
- data.tar.gz: 7a1ceffb9b2c33f6dffe4a31b6877cbab52946cd3d37ad4396270c397dd99805
3
+ metadata.gz: 7b67b4667e899a379d0cc4152f228bfe7a80bef4aa6b35c26f54ee76c20c967f
4
+ data.tar.gz: d421b6283198d07e8ddc9a902e71a13320745e84f8fd5b3dbc981e6e88b70062
5
5
  SHA512:
6
- metadata.gz: 6da76ea6fd5ac63a77fe4acaf4552946416841228994d4cf6b431a094180aa63d6d07a1ef586c71c44eeca0cfc38a4da30d6f0ed1a5b62c54b28b109fcdb485f
7
- data.tar.gz: 1a96f567be81a5bc6189bb43bb98fd34181009459b2ec085ded5ad820ea662fa7a3780a40e3103a480debe70b74914d224e20cc90a21df3a5c5e949a74801ba4
6
+ metadata.gz: b713f8e47aefe3614a2016bad8046d91fdee669fa5635f3768d167d9c6768622af51ec5f6cb711040f7d712dc2cdac2e9f879f4d752956c008444de52ad326ec
7
+ data.tar.gz: df1e8549d1e7474f137bc7d6a483f7e06450f26273181bdb4724b79003d6a3f51e19b4b29c6d0736f2f390e9d2c8dcd922d5b7e1785717166e70f6e152b4ebdd
@@ -6,7 +6,7 @@ class DiscoApp::InstallController < ApplicationController
6
6
 
7
7
  # Start the installation process for the current shop, then redirect to the installing screen.
8
8
  def install
9
- DiscoApp::AppInstalledJob.perform_later(@shop.shopify_domain, cookies[DiscoApp::CODE_COOKIE_KEY], cookies[DiscoApp::SOURCE_COOKIE_KEY])
9
+ DiscoApp::AppInstalledJob.perform_later(@shop, cookies[DiscoApp::CODE_COOKIE_KEY], cookies[DiscoApp::SOURCE_COOKIE_KEY])
10
10
  redirect_to action: :installing
11
11
  end
12
12
 
@@ -14,10 +14,10 @@ module DiscoApp::Concerns::AppInstalledJob
14
14
  # - Perform initial update of shop information.
15
15
  # - Subscribe to default plan, if any exists.
16
16
  #
17
- def perform(shopify_domain, plan_code = nil, source = nil)
18
- DiscoApp::SynchroniseWebhooksJob.perform_now(shopify_domain)
19
- DiscoApp::SynchroniseCarrierServiceJob.perform_now(shopify_domain)
20
- DiscoApp::ShopUpdateJob.perform_now(shopify_domain)
17
+ def perform(shop, plan_code = nil, source = nil)
18
+ DiscoApp::SynchroniseWebhooksJob.perform_now(@shop)
19
+ DiscoApp::SynchroniseCarrierServiceJob.perform_now(@shop)
20
+ DiscoApp::ShopUpdateJob.perform_now(@shop)
21
21
 
22
22
  @shop.reload
23
23
 
@@ -0,0 +1,8 @@
1
+ module DiscoApp::Concerns::RenderAssetGroupJob
2
+ extend ActiveSupport::Concern
3
+
4
+ def perform(shop, instance, asset_group)
5
+ instance.render_asset_group(asset_group.to_sym)
6
+ end
7
+
8
+ end
@@ -2,7 +2,7 @@ module DiscoApp::Concerns::ShopUpdateJob
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  # Perform an update of the current shop's information.
5
- def perform(shopify_domain, shop_data = nil)
5
+ def perform(shop, shop_data = nil)
6
6
  # If we weren't provided with shop data (eg from a webhook), fetch it.
7
7
  shop_data ||= ActiveSupport::JSON::decode(ShopifyAPI::Shop.current.to_json)
8
8
 
@@ -1,7 +1,7 @@
1
1
  module DiscoApp::Concerns::SubscriptionChangedJob
2
2
  extend ActiveSupport::Concern
3
3
 
4
- def perform(shopify_domain, subscription)
4
+ def perform(shop, subscription)
5
5
  end
6
6
 
7
7
  end
@@ -2,7 +2,7 @@ module DiscoApp::Concerns::SynchroniseCarrierServiceJob
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  # Ensure that any carrier service required by our app is registered.
5
- def perform(shopify_domain)
5
+ def perform(shop)
6
6
  # Don't proceed unless we have a name and callback url.
7
7
  return unless carrier_service_name and callback_url
8
8
 
@@ -3,7 +3,7 @@ module DiscoApp::Concerns::SynchroniseWebhooksJob
3
3
 
4
4
  # Ensure the webhooks registered with our shop are the same as those listed
5
5
  # in our application configuration.
6
- def perform(shopify_domain)
6
+ def perform(shop)
7
7
  # Get the full list of expected webhook topics.
8
8
  expected_topics = [:'app/uninstalled', :'shop/update'] + topics
9
9
 
@@ -0,0 +1,3 @@
1
+ class DiscoApp::RenderAssetGroupJob < DiscoApp::ShopJob
2
+ include DiscoApp::Concerns::RenderAssetGroupJob
3
+ end
@@ -15,7 +15,7 @@ class DiscoApp::ShopJob < ActiveJob::Base
15
15
  private
16
16
 
17
17
  def find_shop(job)
18
- @shop ||= DiscoApp::Shop.find_by!(shopify_domain: job.arguments.first)
18
+ @shop ||= job.arguments.first.is_a?(DiscoApp::Shop) ? job.arguments.first : DiscoApp::Shop.find_by!(shopify_domain: job.arguments.first)
19
19
  end
20
20
 
21
21
  def shop_context(job, block)
@@ -0,0 +1,148 @@
1
+ require 'render_anywhere'
2
+
3
+ module DiscoApp::Concerns::RendersAssets
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include RenderAnywhere
8
+ after_commit :queue_render_asset_group_job
9
+ end
10
+
11
+ class_methods do
12
+
13
+ # Ruby "macro" that allows the definition of a number of Shopify assets that
14
+ # should be rendered and uploaded when certain attributes on the including
15
+ # class change. This assumes that the including class (1) is an ActiveRecord
16
+ # model that supports an `after_commit` callback; and (2) that the model has
17
+ # a `shop` method (or attribute) that references the DiscoApp::Shop instance
18
+ # associated with the current model.
19
+ #
20
+ # Options
21
+ #
22
+ # assets: Required. A list of asset templates to be rendered and
23
+ # uploaded to Shopify. The order of assets matters only
24
+ # in that subsequent asset templates will have access to
25
+ # the public CDN url of earlier-rendered assets through
26
+ # a "@public_urls" context variable.
27
+ #
28
+ # triggered_by: Optional. A list of attributes that should trigger the
29
+ # re-rendering and upload of the assets defined by the
30
+ # `assets` option, provided as a list of string. If
31
+ # empty or nil, nothing will be triggered.
32
+ #
33
+ # script_tags: Optional. A list of assets that should have script
34
+ # tags created or updated after being rendered to the
35
+ # storefront.
36
+ #
37
+ # compress: Optional. Whether Javascript and SCSS assets should be
38
+ # compressed after being rendered. Defaults to true in
39
+ # production environments, false otherwise.
40
+ #
41
+ def renders_assets(*asset_groups)
42
+ options = asset_groups.last.is_a?(Hash) ? asset_groups.pop : {}
43
+ options = renders_assets_default_options.merge(options)
44
+
45
+ # Ensure assets, triggered by and script tag options are arrays.
46
+ options[:assets] = options[:assets] ? Array(options[:assets]).map(&:to_sym) : []
47
+ options[:triggered_by] = options[:triggered_by] ? Array(options[:triggered_by]).map(&:to_s) : []
48
+ options[:script_tags] = options[:script_tags] ? Array(options[:script_tags]).map(&:to_sym) : []
49
+
50
+ asset_groups.each do |asset_group|
51
+ renderable_asset_groups[asset_group.to_sym] = options
52
+ end
53
+ end
54
+
55
+ # Return a list of renderable asset groups, along with their options.
56
+ def renderable_asset_groups
57
+ @renderable_asset_groups ||= {}
58
+ end
59
+
60
+ # Return the default options for the `renders_assets` macro.
61
+ def renders_assets_default_options
62
+ {
63
+ assets: nil,
64
+ triggered_by: nil,
65
+ compress: Rails.env.production?
66
+ }
67
+ end
68
+
69
+ end
70
+
71
+ # Callback, triggered after a model save. Iterates through each asset group
72
+ # defined on the model and queues a render job if any of the changed
73
+ # attributes are found in the asset group's triggered_by list.
74
+ def queue_render_asset_group_job
75
+ renderable_asset_groups.each do |asset_group, options|
76
+ unless (previous_changes.keys & options[:triggered_by]).empty?
77
+ DiscoApp::RenderAssetGroupJob.perform_later(shop, self, asset_group.to_s)
78
+ end
79
+ end
80
+ end
81
+
82
+ # Copies the class-level hash of assets with symbol asset name as keys and
83
+ # their corresponding options as values to the instance.
84
+ def renderable_asset_groups
85
+ @renderable_asset_groups ||= self.class.renderable_asset_groups.dup
86
+ end
87
+
88
+ # Render the specified asset group and upload the result to Shopify.
89
+ def render_asset_group(asset_group)
90
+ options = renderable_asset_groups[asset_group]
91
+ public_urls = {}
92
+
93
+ options[:assets].each do |asset|
94
+ # Create/replace the asset via the Shopify API.
95
+ shopify_asset = shop.temp {
96
+ ShopifyAPI::Asset.create(
97
+ key: "assets/#{asset}",
98
+ value: render_asset_group_asset(asset, public_urls)
99
+ )
100
+ }
101
+
102
+ # Store the public URL to this asset, so that we're able to use it in
103
+ # subsequent template renders. Adds a .css suffix to .scss assets, so that
104
+ # we use the Shopify-compiled version of any SCSS stylesheets.
105
+ public_urls[asset] = shopify_asset.public_url.gsub(/\.scss\?/, '.scss.css?')
106
+ end
107
+
108
+ # If we specified the creation of any script tags based on newly rendered
109
+ # assets, do that now.
110
+ unless options[:script_tags].empty?
111
+ render_asset_script_tags(options, public_urls)
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ # Render an individual asset within an asset group.
118
+ def render_asset_group_asset(asset, public_urls)
119
+ render_asset_renderer.render_to_string(
120
+ template: "assets/#{asset}",
121
+ layout: nil,
122
+ locals: {
123
+ :"@#{self.class.name.underscore}" => self,
124
+ :@public_urls => public_urls
125
+ }
126
+ )
127
+ end
128
+
129
+ def render_asset_renderer
130
+ @render_asset_renderer ||= self.class.const_get('RenderingController').new
131
+ end
132
+
133
+ # Render any script tags defined by the :script_tags options that we have
134
+ # a public URL for.
135
+ def render_asset_script_tags(options, public_urls)
136
+ # Fetch the current set of script tags for the store.
137
+ current_script_tags = shop.temp { ShopifyAPI::ScriptTag.find(:all) }
138
+
139
+ # Iterate each script tag for which we have a known public URL and create
140
+ # or update the corresponding script tag resource.
141
+ public_urls.slice(*options[:script_tags]).each do |asset, public_url|
142
+ script_tag = current_script_tags.find(lambda { ShopifyAPI::ScriptTag.new(event: 'onload') }) { |script_tag| script_tag.src.include?("#{asset}?") }
143
+ script_tag.src = public_url
144
+ shop.temp { script_tag.save }
145
+ end
146
+ end
147
+
148
+ end
@@ -37,7 +37,7 @@ class DiscoApp::SubscriptionService
37
37
  )
38
38
 
39
39
  # Enqueue the subscription changed background job.
40
- DiscoApp::SubscriptionChangedJob.perform_later(shop.shopify_domain, new_subscription)
40
+ DiscoApp::SubscriptionChangedJob.perform_later(shop, new_subscription)
41
41
 
42
42
  # Return the new subscription.
43
43
  new_subscription
@@ -1,3 +1,3 @@
1
1
  module DiscoApp
2
- VERSION = '0.9.3'
2
+ VERSION = '0.9.4'
3
3
  end
@@ -38,10 +38,9 @@ class DiscoAppGenerator < Rails::Generators::Base
38
38
  gem 'react-rails', '~> 1.6.0'
39
39
  gem 'classnames-rails', '~> 2.1.5'
40
40
  gem 'active_link_to', '~> 1.0.2'
41
- # Add premailer gem to Gemfile.
42
41
  gem 'premailer-rails', '~> 1.8.2'
43
- # Add explicit dependency on Nokogiri
44
42
  gem 'nokogiri', '~> 1.6.7.2'
43
+ gem 'render_anywhere', '~> 0.0.12', require: false
45
44
 
46
45
  # Add gems for development and testing only.
47
46
  gem_group :development, :test do
@@ -3,7 +3,7 @@ namespace :carrier_service do
3
3
  desc 'Synchronise carrier service across all installed shops.'
4
4
  task sync: :environment do
5
5
  DiscoApp::Shop.installed.has_active_shopify_plan.each do |shop|
6
- DiscoApp::SynchroniseCarrierServiceJob.perform_later(shop.shopify_domain)
6
+ DiscoApp::SynchroniseCarrierServiceJob.perform_later(shop)
7
7
  end
8
8
  end
9
9
 
data/lib/tasks/shops.rake CHANGED
@@ -3,7 +3,7 @@ namespace :shops do
3
3
  desc 'Synchronise shop data across all installed shops.'
4
4
  task sync: :environment do
5
5
  DiscoApp::Shop.installed.has_active_shopify_plan.each do |shop|
6
- DiscoApp::ShopUpdateJob.perform_later(shop.shopify_domain)
6
+ DiscoApp::ShopUpdateJob.perform_later(shop)
7
7
  end
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ namespace :webhooks do
3
3
  desc 'Synchronise webhooks across all installed shops.'
4
4
  task sync: :environment do
5
5
  DiscoApp::Shop.installed.has_active_shopify_plan.each do |shop|
6
- DiscoApp::SynchroniseWebhooksJob.perform_later(shop.shopify_domain)
6
+ DiscoApp::SynchroniseWebhooksJob.perform_later(shop)
7
7
  end
8
8
  end
9
9
 
@@ -1,6 +1,6 @@
1
1
  class ProductsCreateJob < DiscoApp::ShopJob
2
2
 
3
- def perform(shopify_domain, product_data)
3
+ def perform(shop, product_data)
4
4
  Product.synchronise(@shop, product_data)
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
1
  class ProductsDeleteJob < DiscoApp::ShopJob
2
2
 
3
- def perform(shopify_domain, product_data)
3
+ def perform(shop, product_data)
4
4
  Product.synchronise_deletion(@shop, product_data)
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
1
  class ProductsUpdateJob < DiscoApp::ShopJob
2
2
 
3
- def perform(shopify_domain, product_data)
3
+ def perform(shop, product_data)
4
4
  Product.synchronise(@shop, product_data)
5
5
  end
6
6
 
@@ -0,0 +1,8 @@
1
+ class JsConfiguration < ActiveRecord::Base
2
+ include DiscoApp::Concerns::RendersAssets
3
+
4
+ belongs_to :shop, class_name: 'DiscoApp::Shop'
5
+
6
+ renders_assets :js_assets, assets: 'test.js', triggered_by: 'locale'
7
+
8
+ end
@@ -0,0 +1,10 @@
1
+ class WidgetConfiguration < ActiveRecord::Base
2
+ include DiscoApp::Concerns::RendersAssets
3
+
4
+ belongs_to :shop, class_name: 'DiscoApp::Shop'
5
+
6
+ renders_assets :widget_assets, assets: ['widget.scss', 'widget.js'], triggered_by: ['locale', 'background_color']
7
+ renders_assets :liquid_assets, assets: 'widget.liquid', triggered_by: ['locale']
8
+ renders_assets :script_tag_assets, assets: 'script_tag.js', script_tags: 'script_tag.js'
9
+
10
+ end
@@ -0,0 +1 @@
1
+ (function() { console.log('Script Tag!') });
@@ -0,0 +1 @@
1
+ var locale = '<%= @js_configuration.locale %>';
@@ -0,0 +1,2 @@
1
+ var locale = '<%= @widget_configuration.locale %>';
2
+ var cssUrl = '<%= @public_urls[:'widget.scss'] %>';
@@ -0,0 +1,3 @@
1
+ #widget {
2
+ background-color: <%= @widget_configuration.background_color %>;
3
+ }
@@ -0,0 +1,19 @@
1
+ class CreateAssetModels < ActiveRecord::Migration
2
+ def change
3
+ create_table :js_configurations do |t|
4
+ t.integer :shop_id, limit: 8
5
+ t.string :label, default: 'Default'
6
+ t.string :locale, default: 'en'
7
+ end
8
+
9
+ create_table :widget_configurations do |t|
10
+ t.integer :shop_id, limit: 8
11
+ t.string :label, default: 'Default'
12
+ t.string :locale, default: 'en'
13
+ t.string :background_color, default: '#FFFFFF'
14
+ end
15
+
16
+ add_foreign_key :js_configurations, :disco_app_shops, column: :shop_id
17
+ add_foreign_key :widget_configurations, :disco_app_shops, column: :shop_id
18
+ end
19
+ end
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20160521135510) do
14
+ ActiveRecord::Schema.define(version: 20160530160739) do
15
15
 
16
16
  # These are extensions that must be enabled in order to support this database
17
17
  enable_extension "plpgsql"
@@ -108,6 +108,12 @@ ActiveRecord::Schema.define(version: 20160521135510) do
108
108
  add_index "disco_app_subscriptions", ["plan_id"], name: "index_disco_app_subscriptions_on_plan_id", using: :btree
109
109
  add_index "disco_app_subscriptions", ["shop_id"], name: "index_disco_app_subscriptions_on_shop_id", using: :btree
110
110
 
111
+ create_table "js_configurations", force: :cascade do |t|
112
+ t.integer "shop_id", limit: 8
113
+ t.string "label", default: "Default"
114
+ t.string "locale", default: "en"
115
+ end
116
+
111
117
  create_table "products", force: :cascade do |t|
112
118
  t.integer "shop_id", limit: 8
113
119
  t.jsonb "data"
@@ -115,6 +121,13 @@ ActiveRecord::Schema.define(version: 20160521135510) do
115
121
  t.datetime "updated_at", null: false
116
122
  end
117
123
 
124
+ create_table "widget_configurations", force: :cascade do |t|
125
+ t.integer "shop_id", limit: 8
126
+ t.string "label", default: "Default"
127
+ t.string "locale", default: "en"
128
+ t.string "background_color", default: "#FFFFFF"
129
+ end
130
+
118
131
  add_foreign_key "disco_app_application_charges", "disco_app_shops", column: "shop_id"
119
132
  add_foreign_key "disco_app_application_charges", "disco_app_subscriptions", column: "subscription_id"
120
133
  add_foreign_key "disco_app_plan_codes", "disco_app_plans", column: "plan_id"
@@ -122,5 +135,7 @@ ActiveRecord::Schema.define(version: 20160521135510) do
122
135
  add_foreign_key "disco_app_recurring_application_charges", "disco_app_subscriptions", column: "subscription_id"
123
136
  add_foreign_key "disco_app_sessions", "disco_app_shops", column: "shop_id", on_delete: :cascade
124
137
  add_foreign_key "disco_app_subscriptions", "disco_app_plan_codes", column: "plan_code_id"
138
+ add_foreign_key "js_configurations", "disco_app_shops", column: "shop_id"
125
139
  add_foreign_key "products", "disco_app_shops", column: "shop_id"
140
+ add_foreign_key "widget_configurations", "disco_app_shops", column: "shop_id"
126
141
  end
@@ -0,0 +1,6 @@
1
+ {
2
+ "asset":{
3
+ "key":"assets/script_tag.js",
4
+ "value":"(function() { console.log('Script Tag!') });\n"
5
+ }
6
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "asset": {
3
+ "key": "assets/script_tag.js",
4
+ "public_url": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/script_tag.js?8557426387360348643",
5
+ "created_at": "2016-05-31T10:58:51-04:00",
6
+ "updated_at": "2016-05-31T10:58:51-04:00",
7
+ "content_type": "application/javascript",
8
+ "size": 45,
9
+ "theme_id": 106913286,
10
+ "warnings": []
11
+ }
12
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "script_tag":{
3
+ "event":"onload",
4
+ "src":"https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/script_tag.js?8557426387360348643"
5
+ }
6
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "script_tag": {
3
+ "id": 38138886,
4
+ "src": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/script_tag.js?8557426387360348643",
5
+ "event": "onload",
6
+ "created_at": "2016-05-31T11:09:17-04:00",
7
+ "updated_at": "2016-05-31T11:09:17-04:00",
8
+ "display_scope": "all"
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "asset":{
3
+ "key":"assets/test.js",
4
+ "value":"var locale = 'sv';\n"
5
+ }
6
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "asset": {
3
+ "key": "assets/test.js",
4
+ "public_url": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/test.js?8565972447222863489",
5
+ "created_at": "2016-05-31T08:22:07-04:00",
6
+ "updated_at": "2016-05-31T08:22:07-04:00",
7
+ "content_type": "application/javascript",
8
+ "size": 19,
9
+ "theme_id": 106913286,
10
+ "warnings": []
11
+ }
12
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "asset":{
3
+ "key":"assets/widget.js",
4
+ "value":"var locale = 'sv';\nvar cssUrl = 'https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/widget.scss.css?12368054146898033463';\n"
5
+ }
6
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "asset": {
3
+ "key": "assets/widget.js",
4
+ "public_url": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/widget.js?14127703044459766029",
5
+ "created_at": "2016-05-31T10:15:25-04:00",
6
+ "updated_at": "2016-05-31T10:15:25-04:00",
7
+ "content_type": "application/javascript",
8
+ "size": 123,
9
+ "theme_id": 106913286,
10
+ "warnings": []
11
+ }
12
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "asset":{
3
+ "key":"assets/widget.scss",
4
+ "value":"#widget {\n background-color: #006AA7;\n}\n"
5
+ }
6
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "asset": {
3
+ "key": "assets/widget.scss",
4
+ "public_url": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/widget.scss?12368054146898033463",
5
+ "created_at": "2016-05-31T08:40:24-04:00",
6
+ "updated_at": "2016-05-31T08:40:24-04:00",
7
+ "content_type": "text/css",
8
+ "size": 41,
9
+ "theme_id": 106913286,
10
+ "warnings": []
11
+ }
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "script_tags": [
3
+ {
4
+ "id": 38138886,
5
+ "src": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/script_tag.js?8557426387360348000",
6
+ "event": "onload",
7
+ "created_at": "2016-05-31T11:09:17-04:00",
8
+ "updated_at": "2016-05-31T11:09:17-04:00",
9
+ "display_scope": "all"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "script_tag":{
3
+ "id":38138886,
4
+ "src":"https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/script_tag.js?8557426387360348643",
5
+ "event":"onload",
6
+ "created_at":"2016-05-31T11:09:17-04:00",
7
+ "updated_at":"2016-05-31T11:09:17-04:00",
8
+ "display_scope":"all"
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "script_tag": {
3
+ "id": 38138886,
4
+ "src": "https://cdn.shopify.com/s/files/1/1308/2083/t/1/assets/script_tag.js?8557426387360348643",
5
+ "event": "onload",
6
+ "created_at": "2016-05-31T11:09:17-04:00",
7
+ "updated_at": "2016-05-31T11:09:17-04:00",
8
+ "display_scope": "all"
9
+ }
10
+ }
@@ -0,0 +1 @@
1
+ var locale = 'sv';
@@ -0,0 +1,3 @@
1
+ js_swedish:
2
+ shop: widget_store
3
+ locale: sv
@@ -0,0 +1,4 @@
1
+ widget_swedish:
2
+ shop: widget_store
3
+ locale: sv
4
+ background_color: '#006AA7'
@@ -20,7 +20,7 @@ class DiscoApp::AppInstalledJobTest < ActionController::TestCase
20
20
  test 'app installed job performs shop update job' do
21
21
  # Assert the main install job can be enqueued and performed.
22
22
  perform_enqueued_jobs do
23
- DiscoApp::AppInstalledJob.perform_later(@shop.shopify_domain)
23
+ DiscoApp::AppInstalledJob.perform_later(@shop)
24
24
  end
25
25
 
26
26
  # Assert the update shop job was performed.
@@ -32,7 +32,7 @@ class DiscoApp::AppInstalledJobTest < ActionController::TestCase
32
32
  @shop.current_subscription.destroy
33
33
 
34
34
  perform_enqueued_jobs do
35
- DiscoApp::AppInstalledJob.perform_later(@shop.shopify_domain)
35
+ DiscoApp::AppInstalledJob.perform_later(@shop)
36
36
  end
37
37
 
38
38
  # Assert the shop was subscribed to the development plan.
@@ -43,7 +43,7 @@ class DiscoApp::AppInstalledJobTest < ActionController::TestCase
43
43
  @shop.current_subscription.destroy
44
44
 
45
45
  perform_enqueued_jobs do
46
- DiscoApp::AppInstalledJob.perform_later(@shop.shopify_domain, 'PODCAST', 'smpodcast')
46
+ DiscoApp::AppInstalledJob.perform_later(@shop, 'PODCAST', 'smpodcast')
47
47
  end
48
48
 
49
49
  # Assert the shop was subscribed to the development plan.
@@ -7,7 +7,7 @@ class DiscoApp::AppUninstalledJobTest < ActionController::TestCase
7
7
  @shop = disco_app_shops(:widget_store)
8
8
 
9
9
  perform_enqueued_jobs do
10
- DiscoApp::AppUninstalledJob.perform_later(@shop.shopify_domain, {})
10
+ DiscoApp::AppUninstalledJob.perform_later(@shop, {})
11
11
  end
12
12
  end
13
13
 
@@ -0,0 +1,100 @@
1
+ require 'test_helper'
2
+
3
+ class DiscoApp::RendersAssetsTest < ActiveSupport::TestCase
4
+ include ActiveJob::TestHelper
5
+ include DiscoApp::Test::ShopifyAPI
6
+
7
+ def setup
8
+ @shop = disco_app_shops(:widget_store)
9
+ @js_configuration = js_configurations(:js_swedish)
10
+ @widget_configuration = widget_configurations(:widget_swedish)
11
+ end
12
+
13
+ def teardown
14
+ @shop = nil
15
+ @js_configuration = nil
16
+ @widget_configuration = nil
17
+ end
18
+
19
+ ##
20
+ # Test queueing behaviour.
21
+ ##
22
+
23
+ test 'rendering of javascript asset group queued when locale changed' do
24
+ assert_enqueued_with(job: DiscoApp::RenderAssetGroupJob) do
25
+ @js_configuration.update(locale: :no)
26
+ end
27
+ end
28
+
29
+ test 'rendering of javascript asset group not queued when label changed' do
30
+ assert_no_enqueued_jobs do
31
+ @js_configuration.update(label: 'Sample')
32
+ end
33
+ end
34
+
35
+ test 'rendering of widget asset group queued when locale changed' do
36
+ assert_enqueued_with(job: DiscoApp::RenderAssetGroupJob, args: [@widget_configuration.shop, @widget_configuration, 'widget_assets']) do
37
+ @widget_configuration.update(locale: :no)
38
+ end
39
+ end
40
+
41
+ test 'rendering of liquid asset group queued when locale changed' do
42
+ assert_enqueued_with(job: DiscoApp::RenderAssetGroupJob, args: [@widget_configuration.shop, @widget_configuration, 'liquid_assets']) do
43
+ @widget_configuration.update(locale: :no)
44
+ end
45
+ end
46
+
47
+ test 'rendering of widget asset group queued when background color changed' do
48
+ assert_enqueued_with(job: DiscoApp::RenderAssetGroupJob, args: [@widget_configuration.shop, @widget_configuration, 'widget_assets']) do
49
+ @widget_configuration.update(background_color: '#FF0000')
50
+ end
51
+ end
52
+
53
+ test 'rendering of liquid asset group not queued when background color changed' do
54
+ assert_enqueued_jobs 1 do
55
+ @widget_configuration.update(background_color: '#FF0000')
56
+ end
57
+ end
58
+
59
+ ##
60
+ # Test rendering behaviour.
61
+ ##
62
+
63
+ test 'individual js asset renders correctly' do
64
+ assert_equal asset_fixture('test.js'), @js_configuration.send('render_asset_group_asset', 'test.js', {})
65
+ end
66
+
67
+ test 'js asset group renders and uploads to shopify' do
68
+ stub_api_request(:put, "#{@shop.admin_url}/assets.json", 'widget_store/assets/create_test_js')
69
+ @js_configuration.render_asset_group(:js_assets)
70
+ end
71
+
72
+ test 'widget asset group renders and uploads to shopify' do
73
+ stub_api_request(:put, "#{@shop.admin_url}/assets.json", 'widget_store/assets/create_widget_scss')
74
+ stub_api_request(:put, "#{@shop.admin_url}/assets.json", 'widget_store/assets/create_widget_js')
75
+ @widget_configuration.render_asset_group(:widget_assets)
76
+ end
77
+
78
+ test 'script tag asset group renders, uploads to shopify and creates new script tag' do
79
+ stub_api_request(:put, "#{@shop.admin_url}/assets.json", 'widget_store/assets/create_script_tag_js')
80
+ stub_api_request(:get, "#{@shop.admin_url}/script_tags.json", 'widget_store/assets/get_script_tags_empty')
81
+ stub_api_request(:post, "#{@shop.admin_url}/script_tags.json", 'widget_store/assets/create_script_tag')
82
+ @widget_configuration.render_asset_group(:script_tag_assets)
83
+ end
84
+
85
+ test 'script tag asset group renders, uploads to shopify and updates existing script tag' do
86
+ stub_api_request(:put, "#{@shop.admin_url}/assets.json", 'widget_store/assets/create_script_tag_js')
87
+ stub_api_request(:get, "#{@shop.admin_url}/script_tags.json", 'widget_store/assets/get_script_tags_preexisting')
88
+ stub_api_request(:put, "#{@shop.admin_url}/script_tags/38138886.json", 'widget_store/assets/update_script_tag')
89
+ @widget_configuration.render_asset_group(:script_tag_assets)
90
+ end
91
+
92
+ private
93
+
94
+ # Return an asset fixture as a string.
95
+ def asset_fixture(path)
96
+ filename = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'fixtures', 'assets', "#{path}")
97
+ File.read(filename)
98
+ end
99
+
100
+ end
@@ -5,7 +5,7 @@ module DiscoApp::Test
5
5
  if method == :get
6
6
  stub_request(method, endpoint)
7
7
  .to_return(status: 200, body: api_fixture("#{fixture_name}_response").to_json)
8
- elsif method == :post
8
+ elsif method == :post or method == :put
9
9
  stub_request(method, endpoint)
10
10
  .with(body: api_fixture("#{fixture_name}_request").to_json)
11
11
  .to_return(status: 201, body: api_fixture("#{fixture_name}_response").to_json)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disco_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin Ballard
@@ -220,6 +220,20 @@ dependencies:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
222
  version: 2.1.5
223
+ - !ruby/object:Gem::Dependency
224
+ name: render_anywhere
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: 0.0.12
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: 0.0.12
223
237
  - !ruby/object:Gem::Dependency
224
238
  name: sqlite3
225
239
  requirement: !ruby/object:Gem::Requirement
@@ -389,10 +403,12 @@ files:
389
403
  - app/jobs/disco_app/app_uninstalled_job.rb
390
404
  - app/jobs/disco_app/concerns/app_installed_job.rb
391
405
  - app/jobs/disco_app/concerns/app_uninstalled_job.rb
406
+ - app/jobs/disco_app/concerns/render_asset_group_job.rb
392
407
  - app/jobs/disco_app/concerns/shop_update_job.rb
393
408
  - app/jobs/disco_app/concerns/subscription_changed_job.rb
394
409
  - app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb
395
410
  - app/jobs/disco_app/concerns/synchronise_webhooks_job.rb
411
+ - app/jobs/disco_app/render_asset_group_job.rb
396
412
  - app/jobs/disco_app/shop_job.rb
397
413
  - app/jobs/disco_app/shop_update_job.rb
398
414
  - app/jobs/disco_app/subscription_changed_job.rb
@@ -403,6 +419,7 @@ files:
403
419
  - app/models/disco_app/concerns/app_settings.rb
404
420
  - app/models/disco_app/concerns/plan.rb
405
421
  - app/models/disco_app/concerns/plan_code.rb
422
+ - app/models/disco_app/concerns/renders_assets.rb
406
423
  - app/models/disco_app/concerns/shop.rb
407
424
  - app/models/disco_app/concerns/subscription.rb
408
425
  - app/models/disco_app/concerns/synchronises.rb
@@ -522,7 +539,13 @@ files:
522
539
  - test/dummy/app/jobs/products_delete_job.rb
523
540
  - test/dummy/app/jobs/products_update_job.rb
524
541
  - test/dummy/app/models/disco_app/shop.rb
542
+ - test/dummy/app/models/js_configuration.rb
525
543
  - test/dummy/app/models/product.rb
544
+ - test/dummy/app/models/widget_configuration.rb
545
+ - test/dummy/app/views/assets/script_tag.js.erb
546
+ - test/dummy/app/views/assets/test.js.erb
547
+ - test/dummy/app/views/assets/widget.js.erb
548
+ - test/dummy/app/views/assets/widget.scss.erb
526
549
  - test/dummy/app/views/home/index.html.erb
527
550
  - test/dummy/bin/bundle
528
551
  - test/dummy/bin/rails
@@ -554,11 +577,28 @@ files:
554
577
  - test/dummy/config/routes.rb
555
578
  - test/dummy/config/secrets.yml
556
579
  - test/dummy/db/migrate/20160307182229_create_products.rb
580
+ - test/dummy/db/migrate/20160530160739_create_asset_models.rb
557
581
  - test/dummy/db/schema.rb
558
582
  - test/dummy/public/404.html
559
583
  - test/dummy/public/422.html
560
584
  - test/dummy/public/500.html
561
585
  - test/dummy/public/favicon.ico
586
+ - test/fixtures/api/widget_store/assets/create_script_tag_js_request.json
587
+ - test/fixtures/api/widget_store/assets/create_script_tag_js_response.json
588
+ - test/fixtures/api/widget_store/assets/create_script_tag_request.json
589
+ - test/fixtures/api/widget_store/assets/create_script_tag_response.json
590
+ - test/fixtures/api/widget_store/assets/create_test_js_request.json
591
+ - test/fixtures/api/widget_store/assets/create_test_js_response.json
592
+ - test/fixtures/api/widget_store/assets/create_widget_js_request.json
593
+ - test/fixtures/api/widget_store/assets/create_widget_js_response.json
594
+ - test/fixtures/api/widget_store/assets/create_widget_scss_request.json
595
+ - test/fixtures/api/widget_store/assets/create_widget_scss_response.json
596
+ - test/fixtures/api/widget_store/assets/get_script_tags_empty_request.json
597
+ - test/fixtures/api/widget_store/assets/get_script_tags_empty_response.json
598
+ - test/fixtures/api/widget_store/assets/get_script_tags_preexisting_request.json
599
+ - test/fixtures/api/widget_store/assets/get_script_tags_preexisting_response.json
600
+ - test/fixtures/api/widget_store/assets/update_script_tag_request.json
601
+ - test/fixtures/api/widget_store/assets/update_script_tag_response.json
562
602
  - test/fixtures/api/widget_store/charges/activate_application_charge_request.json
563
603
  - test/fixtures/api/widget_store/charges/activate_application_charge_response.json
564
604
  - test/fixtures/api/widget_store/charges/activate_recurring_application_charge_request.json
@@ -577,21 +617,25 @@ files:
577
617
  - test/fixtures/api/widget_store/charges/get_pending_recurring_application_charge_response.json
578
618
  - test/fixtures/api/widget_store/shop.json
579
619
  - test/fixtures/api/widget_store/webhooks.json
620
+ - test/fixtures/assets/test.js
580
621
  - test/fixtures/disco_app/application_charges.yml
581
622
  - test/fixtures/disco_app/plan_codes.yml
582
623
  - test/fixtures/disco_app/plans.yml
583
624
  - test/fixtures/disco_app/recurring_application_charges.yml
584
625
  - test/fixtures/disco_app/shops.yml
585
626
  - test/fixtures/disco_app/subscriptions.yml
627
+ - test/fixtures/js_configurations.yml
586
628
  - test/fixtures/products.yml
587
629
  - test/fixtures/webhooks/app_uninstalled.json
588
630
  - test/fixtures/webhooks/product_created.json
589
631
  - test/fixtures/webhooks/product_deleted.json
590
632
  - test/fixtures/webhooks/product_updated.json
633
+ - test/fixtures/widget_configurations.yml
591
634
  - test/integration/synchronises_test.rb
592
635
  - test/jobs/disco_app/app_installed_job_test.rb
593
636
  - test/jobs/disco_app/app_uninstalled_job_test.rb
594
637
  - test/models/disco_app/plan_test.rb
638
+ - test/models/disco_app/renders_assets_test.rb
595
639
  - test/models/disco_app/session_test.rb
596
640
  - test/models/disco_app/shop_test.rb
597
641
  - test/models/disco_app/subscription_test.rb
@@ -649,7 +693,14 @@ test_files:
649
693
  - test/dummy/app/helpers/application_helper.rb
650
694
  - test/dummy/app/models/disco_app/shop.rb
651
695
  - test/dummy/app/models/product.rb
696
+ - test/dummy/app/models/widget_configuration.rb
697
+ - test/dummy/app/models/js_configuration.rb
698
+ - test/dummy/app/views/assets/script_tag.js.erb
699
+ - test/dummy/app/views/assets/widget.scss.erb
700
+ - test/dummy/app/views/assets/test.js.erb
701
+ - test/dummy/app/views/assets/widget.js.erb
652
702
  - test/dummy/app/views/home/index.html.erb
703
+ - test/dummy/db/migrate/20160530160739_create_asset_models.rb
653
704
  - test/dummy/db/migrate/20160307182229_create_products.rb
654
705
  - test/dummy/db/schema.rb
655
706
  - test/dummy/config/locales/en.yml
@@ -676,6 +727,22 @@ test_files:
676
727
  - test/dummy/config/database.yml
677
728
  - test/dummy/config/database.gitlab-ci.yml
678
729
  - test/dummy/config/application.rb
730
+ - test/fixtures/api/widget_store/assets/create_test_js_response.json
731
+ - test/fixtures/api/widget_store/assets/create_widget_js_response.json
732
+ - test/fixtures/api/widget_store/assets/create_test_js_request.json
733
+ - test/fixtures/api/widget_store/assets/update_script_tag_request.json
734
+ - test/fixtures/api/widget_store/assets/create_script_tag_response.json
735
+ - test/fixtures/api/widget_store/assets/create_script_tag_js_response.json
736
+ - test/fixtures/api/widget_store/assets/create_widget_scss_request.json
737
+ - test/fixtures/api/widget_store/assets/update_script_tag_response.json
738
+ - test/fixtures/api/widget_store/assets/create_script_tag_js_request.json
739
+ - test/fixtures/api/widget_store/assets/create_script_tag_request.json
740
+ - test/fixtures/api/widget_store/assets/get_script_tags_preexisting_response.json
741
+ - test/fixtures/api/widget_store/assets/create_widget_scss_response.json
742
+ - test/fixtures/api/widget_store/assets/get_script_tags_preexisting_request.json
743
+ - test/fixtures/api/widget_store/assets/get_script_tags_empty_response.json
744
+ - test/fixtures/api/widget_store/assets/get_script_tags_empty_request.json
745
+ - test/fixtures/api/widget_store/assets/create_widget_js_request.json
679
746
  - test/fixtures/api/widget_store/webhooks.json
680
747
  - test/fixtures/api/widget_store/charges/create_application_charge_response.json
681
748
  - test/fixtures/api/widget_store/charges/create_second_recurring_application_charge_response.json
@@ -694,6 +761,9 @@ test_files:
694
761
  - test/fixtures/api/widget_store/charges/create_second_recurring_application_charge_request.json
695
762
  - test/fixtures/api/widget_store/charges/activate_application_charge_request.json
696
763
  - test/fixtures/api/widget_store/shop.json
764
+ - test/fixtures/assets/test.js
765
+ - test/fixtures/widget_configurations.yml
766
+ - test/fixtures/js_configurations.yml
697
767
  - test/fixtures/disco_app/plan_codes.yml
698
768
  - test/fixtures/disco_app/shops.yml
699
769
  - test/fixtures/disco_app/application_charges.yml
@@ -723,5 +793,6 @@ test_files:
723
793
  - test/models/disco_app/shop_test.rb
724
794
  - test/models/disco_app/session_test.rb
725
795
  - test/models/disco_app/subscription_test.rb
796
+ - test/models/disco_app/renders_assets_test.rb
726
797
  - test/services/disco_app/charges_service_test.rb
727
798
  - test/services/disco_app/subscription_service_test.rb