disco_app 0.5.6 → 0.6.0
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.
- checksums.yaml +4 -4
- data/app/assets/images/disco_app/icon.svg +1 -0
- data/app/assets/stylesheets/disco_app/{bootstrap-custom.scss → bootstrap/_custom.scss} +3 -4
- data/app/assets/stylesheets/disco_app/bootstrap/_variables.scss +872 -0
- data/app/assets/stylesheets/disco_app/disco/_buttons.scss +31 -0
- data/app/assets/stylesheets/disco_app/disco/_cards.scss +43 -0
- data/app/assets/stylesheets/disco_app/disco/_forms.scss +23 -0
- data/app/assets/stylesheets/disco_app/disco/_sections.scss +61 -0
- data/app/assets/stylesheets/disco_app/disco/_type.scss +21 -0
- data/app/assets/stylesheets/disco_app/disco/mixins/_flexbox.scss +394 -0
- data/app/assets/stylesheets/disco_app/disco_app.scss +12 -6
- data/app/controllers/disco_app/authenticated_controller.rb +1 -1
- data/app/controllers/disco_app/install_controller.rb +1 -1
- data/app/controllers/disco_app/webhooks_controller.rb +11 -9
- data/app/jobs/disco_app/app_installed_job.rb +1 -1
- data/app/jobs/disco_app/app_uninstalled_job.rb +2 -17
- data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +19 -0
- data/app/jobs/disco_app/shop_job.rb +1 -1
- data/app/jobs/disco_app/shop_update_job.rb +1 -1
- data/app/models/disco_app/concerns/plan.rb +14 -0
- data/app/models/disco_app/concerns/shop.rb +62 -0
- data/app/models/disco_app/concerns/subscription.rb +14 -0
- data/app/models/disco_app/plan.rb +3 -0
- data/app/models/disco_app/session_storage.rb +18 -0
- data/app/models/disco_app/shop.rb +2 -43
- data/app/models/disco_app/subscription.rb +3 -0
- data/app/services/disco_app/subscription_service.rb +25 -0
- data/app/services/disco_app/webhook_service.rb +30 -0
- data/app/views/disco_app/shared/_card.html.erb +16 -0
- data/app/views/disco_app/shared/_section.html.erb +17 -0
- data/{lib/generators/disco_app/templates → app}/views/layouts/embedded_app.html.erb +14 -6
- data/db/migrate/20150525000000_create_shops_if_not_existent.rb +15 -0
- data/db/migrate/20151017231302_create_disco_app_plans.rb +13 -0
- data/db/migrate/20151017232027_create_disco_app_subscriptions.rb +15 -0
- data/db/migrate/20151017234409_move_shop_to_disco_app_engine.rb +5 -0
- data/lib/disco_app/engine.rb +5 -0
- data/lib/disco_app/version.rb +1 -1
- data/lib/generators/disco_app/disco_app_generator.rb +31 -54
- data/lib/generators/disco_app/mailify/mailify_generator.rb +55 -0
- data/lib/generators/disco_app/templates/initializers/shopify_session_repository.rb +7 -0
- data/test/controllers/disco_app/install_controller_test.rb +50 -0
- data/test/controllers/disco_app/webhooks_controller_test.rb +58 -0
- data/test/controllers/home_controller_test.rb +61 -0
- data/test/dummy/app/assets/javascripts/application.js +4 -0
- data/test/dummy/app/assets/stylesheets/application.scss +5 -0
- data/test/dummy/app/controllers/application_controller.rb +1 -0
- data/test/dummy/app/controllers/home_controller.rb +7 -0
- data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +11 -0
- data/test/dummy/app/models/disco_app/shop.rb +15 -0
- data/test/dummy/app/views/home/index.html.erb +2 -0
- data/test/dummy/config/application.rb +11 -0
- data/test/dummy/config/environments/production.rb +7 -1
- data/test/dummy/config/initializers/disco_app.rb +1 -0
- data/test/dummy/config/initializers/omniauth.rb +9 -0
- data/test/dummy/config/initializers/shopify_app.rb +7 -0
- data/test/dummy/config/initializers/shopify_session_repository.rb +7 -0
- data/test/dummy/config/routes.rb +5 -1
- data/test/dummy/config/secrets.yml +2 -2
- data/test/dummy/db/schema.rb +70 -0
- data/test/fixtures/api/widget_store/shop.json +46 -0
- data/test/fixtures/disco_app/plans.yml +32 -0
- data/test/fixtures/disco_app/shops.yml +10 -0
- data/test/fixtures/disco_app/subscriptions.yml +26 -0
- data/test/fixtures/webhooks/app_uninstalled.json +46 -0
- data/test/jobs/disco_app/app_installed_job_test.rb +29 -0
- data/test/jobs/disco_app/app_uninstalled_job_test.rb +32 -0
- data/test/models/disco_app/plan_test.rb +5 -0
- data/test/models/disco_app/shop_test.rb +26 -0
- data/test/models/disco_app/subscription_test.rb +6 -0
- data/test/services/disco_app/subscription_service_test.rb +28 -0
- data/test/support/test_file_fixtures.rb +29 -0
- data/test/test_helper.rb +32 -1
- metadata +148 -30
- data/app/assets/stylesheets/disco_app/bootstrap-variables.scss +0 -12
- data/lib/generators/disco_app/templates/jobs/app_installed_job.rb +0 -2
- data/lib/generators/disco_app/templates/jobs/app_uninstalled_job.rb +0 -2
- data/lib/generators/disco_app/templates/jobs/shop_update_job.rb +0 -2
- data/lib/generators/disco_app/templates/models/shop.rb +0 -3
- data/test/dummy/README.rdoc +0 -28
- data/test/dummy/app/assets/stylesheets/application.css +0 -15
- data/test/dummy/app/views/layouts/application.html.erb +0 -14
- data/test/lib/generators/disco_app/disco_app_generator_test.rb +0 -16
- /data/{lib/generators/disco_app/templates → app}/views/layouts/application.html.erb +0 -0
- /data/{lib/generators/disco_app/templates → app}/views/sessions/new.html.erb +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DiscoApp::WebhooksControllerTest < ActionController::TestCase
|
|
4
|
+
include ActiveJob::TestHelper
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
@shop = disco_app_shops(:widget_store)
|
|
8
|
+
@routes = DiscoApp::Engine.routes
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def teardown
|
|
12
|
+
@shop = nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test 'webhook request without authentication information returns unauthorized' do
|
|
16
|
+
body = webhook_fixture('app_uninstalled')
|
|
17
|
+
post(:process_webhook, body)
|
|
18
|
+
assert_response :unauthorized
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test 'webhook request with no HMAC returns unauthorized' do
|
|
22
|
+
body = webhook_fixture('app_uninstalled')
|
|
23
|
+
@request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
|
|
24
|
+
@request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
|
|
25
|
+
post(:process_webhook, body)
|
|
26
|
+
assert_response :unauthorized
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
test 'webhook request with invalid HMAC returns unauthorized' do
|
|
30
|
+
body = webhook_fixture('app_uninstalled')
|
|
31
|
+
@request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
|
|
32
|
+
@request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
|
|
33
|
+
@request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = '0000'
|
|
34
|
+
post(:process_webhook, body)
|
|
35
|
+
assert_response :unauthorized
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test 'webhook request with valid HMAC returns OK' do
|
|
39
|
+
body = webhook_fixture('app_uninstalled')
|
|
40
|
+
@request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
|
|
41
|
+
@request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
|
|
42
|
+
@request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = DiscoApp::WebhookService.calculated_hmac(body, ShopifyApp.configuration.secret)
|
|
43
|
+
post(:process_webhook, body)
|
|
44
|
+
assert_response :ok
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
test 'app uninstalled job queued when app/uninstalled webhook arrives' do
|
|
48
|
+
body = webhook_fixture('app_uninstalled')
|
|
49
|
+
@request.headers['HTTP_X_SHOPIFY_TOPIC'] = :'app/uninstalled'
|
|
50
|
+
@request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN'] = @shop.shopify_domain
|
|
51
|
+
@request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = DiscoApp::WebhookService.calculated_hmac(body, ShopifyApp.configuration.secret)
|
|
52
|
+
|
|
53
|
+
assert_enqueued_with(job: DiscoApp::AppUninstalledJob) do
|
|
54
|
+
post(:process_webhook, body)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class HomeControllerTest < ActionController::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
@shop = disco_app_shops(:widget_store)
|
|
7
|
+
log_in_as(@shop)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def teardown
|
|
11
|
+
@shop = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'non-logged in user is redirected to the login page' do
|
|
15
|
+
log_out
|
|
16
|
+
get(:index)
|
|
17
|
+
assert_redirected_to ShopifyApp::Engine.routes.url_helpers.login_path
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test 'logged-in, never installed user is redirected to the install page' do
|
|
21
|
+
get(:index)
|
|
22
|
+
assert_redirected_to DiscoApp::Engine.routes.url_helpers.install_path
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test 'logged-in, awaiting install user is redirected to the installing page' do
|
|
26
|
+
@shop.awaiting_install!
|
|
27
|
+
get(:index)
|
|
28
|
+
assert_redirected_to DiscoApp::Engine.routes.url_helpers.installing_path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test 'logged-in, installing user is redirected to the installing page' do
|
|
32
|
+
@shop.installing!
|
|
33
|
+
get(:index)
|
|
34
|
+
assert_redirected_to DiscoApp::Engine.routes.url_helpers.installing_path
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test 'logged-in, installed user is able to access the page' do
|
|
38
|
+
@shop.installed!
|
|
39
|
+
get(:index)
|
|
40
|
+
assert_response :success
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'logged-in, awaiting uninstall user is redirected to the uninstalling page' do
|
|
44
|
+
@shop.awaiting_uninstall!
|
|
45
|
+
get(:index)
|
|
46
|
+
assert_redirected_to DiscoApp::Engine.routes.url_helpers.uninstalling_path
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
test 'logged-in, uninstalling user is redirected to the uninstalling page' do
|
|
50
|
+
@shop.uninstalling!
|
|
51
|
+
get(:index)
|
|
52
|
+
assert_redirected_to DiscoApp::Engine.routes.url_helpers.uninstalling_path
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test 'logged-in, uninstalled user is redirected to the install page' do
|
|
56
|
+
@shop.uninstalled!
|
|
57
|
+
get(:index)
|
|
58
|
+
assert_redirected_to DiscoApp::Engine.routes.url_helpers.install_path
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -10,4 +10,8 @@
|
|
|
10
10
|
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
|
11
11
|
// about supported directives.
|
|
12
12
|
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require turbolinks
|
|
16
|
+
//= require disco_app/disco_app
|
|
13
17
|
//= require_tree .
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class DiscoApp::AppUninstalledJob < DiscoApp::ShopJob
|
|
2
|
+
include DiscoApp::Concerns::AppUninstalledJob
|
|
3
|
+
|
|
4
|
+
# Extend the perform method to change the country name of the shop to
|
|
5
|
+
# 'Nowhere' on uninstallation.
|
|
6
|
+
def perform(domain, shop_data)
|
|
7
|
+
super(domain, shop_data)
|
|
8
|
+
@shop.update(country_name: 'Nowhere')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'active_utils'
|
|
2
|
+
|
|
3
|
+
class DiscoApp::Shop < ActiveRecord::Base
|
|
4
|
+
include DiscoApp::Concerns::Shop
|
|
5
|
+
|
|
6
|
+
# Extend the Shop model to return the Shop's country as an ActiveUtils country.
|
|
7
|
+
def country
|
|
8
|
+
begin
|
|
9
|
+
ActiveUtils::Country.find(country_name)
|
|
10
|
+
rescue ActiveUtils::InvalidCountryCodeError
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -7,6 +7,8 @@ require "disco_app"
|
|
|
7
7
|
|
|
8
8
|
module Dummy
|
|
9
9
|
class Application < Rails::Application
|
|
10
|
+
config.action_dispatch.default_headers['P3P'] = 'CP="Not used"'
|
|
11
|
+
config.action_dispatch.default_headers.delete('X-Frame-Options')
|
|
10
12
|
# Settings in config/environments/* take precedence over those specified here.
|
|
11
13
|
# Application configuration should go into files in config/initializers
|
|
12
14
|
# -- all .rb files in that directory are automatically loaded.
|
|
@@ -19,6 +21,15 @@ module Dummy
|
|
|
19
21
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
|
20
22
|
# config.i18n.default_locale = :de
|
|
21
23
|
|
|
24
|
+
# Set the name of the application
|
|
25
|
+
config.x.shopify_app_name = ENV['SHOPIFY_APP_NAME']
|
|
26
|
+
|
|
27
|
+
# Set the default host for absolute URL routing purposes
|
|
28
|
+
routes.default_url_options[:host] = ENV['DEFAULT_HOST']
|
|
29
|
+
|
|
30
|
+
# Explicitly prevent real charges being created by default
|
|
31
|
+
config.x.shopify_charges_real = false
|
|
32
|
+
|
|
22
33
|
# Do not swallow errors in after_commit/after_rollback callbacks.
|
|
23
34
|
config.active_record.raise_in_transactional_callbacks = true
|
|
24
35
|
end
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
Rails.application.configure do
|
|
2
2
|
# Settings specified here will take precedence over those in config/application.rb.
|
|
3
3
|
|
|
4
|
+
# Use Sidekiq as the active job backend
|
|
5
|
+
config.active_job.queue_adapter = :sidekiq
|
|
6
|
+
|
|
7
|
+
# Allow real charges in production with an ENV variable
|
|
8
|
+
config.x.shopify_charges_real = ENV['SHOPIFY_CHARGES_REAL'] == 'true'
|
|
9
|
+
|
|
4
10
|
# Code is not reloaded between requests.
|
|
5
11
|
config.cache_classes = true
|
|
6
12
|
|
|
@@ -42,7 +48,7 @@ Rails.application.configure do
|
|
|
42
48
|
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
|
43
49
|
|
|
44
50
|
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
|
45
|
-
|
|
51
|
+
config.force_ssl = true
|
|
46
52
|
|
|
47
53
|
# Use the lowest log level to ensure availability of diagnostic information
|
|
48
54
|
# when problems arise.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DiscoApp::Engine.routes.default_url_options[:host] = ENV['DEFAULT_HOST']
|
data/test/dummy/config/routes.rb
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
# if you're sharing your code publicly.
|
|
12
12
|
|
|
13
13
|
development:
|
|
14
|
-
secret_key_base:
|
|
14
|
+
secret_key_base: 0cddddfcccc53c82114d3f0c81ce603461c02d1ff661b2508e599f408416b4fe7525cfe0c91e2bf84cacc5c72daa2e6836ef2e8af05d2bb138e116713da7db24
|
|
15
15
|
|
|
16
16
|
test:
|
|
17
|
-
secret_key_base:
|
|
17
|
+
secret_key_base: fbdd6a5a671bb1d6592648b96321f95b115b25ef198cdb5147c5ad48c0a349dcd5346a6a72ac0d3c4d13dcf16bc052c7ef2ec08254f0a519b78bedb4a6bc0d96
|
|
18
18
|
|
|
19
19
|
# Do not keep production secrets in the repository,
|
|
20
20
|
# instead read values from the environment.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
|
5
|
+
#
|
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
|
7
|
+
# database schema. If you need to create the application database on another
|
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
|
11
|
+
#
|
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
|
13
|
+
|
|
14
|
+
ActiveRecord::Schema.define(version: 20151017234409) do
|
|
15
|
+
|
|
16
|
+
create_table "disco_app_plans", force: :cascade do |t|
|
|
17
|
+
t.integer "status"
|
|
18
|
+
t.string "name"
|
|
19
|
+
t.integer "charge_type"
|
|
20
|
+
t.decimal "default_price"
|
|
21
|
+
t.integer "default_trial_days"
|
|
22
|
+
t.datetime "created_at", null: false
|
|
23
|
+
t.datetime "updated_at", null: false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
create_table "disco_app_shops", force: :cascade do |t|
|
|
27
|
+
t.string "shopify_domain", null: false
|
|
28
|
+
t.string "shopify_token", null: false
|
|
29
|
+
t.datetime "created_at"
|
|
30
|
+
t.datetime "updated_at"
|
|
31
|
+
t.integer "status", default: 0
|
|
32
|
+
t.string "email"
|
|
33
|
+
t.string "country_name"
|
|
34
|
+
t.string "currency"
|
|
35
|
+
t.string "money_format"
|
|
36
|
+
t.string "money_with_currency_format"
|
|
37
|
+
t.string "domain"
|
|
38
|
+
t.string "plan_name"
|
|
39
|
+
t.integer "charge_status", default: 6
|
|
40
|
+
t.string "plan_display_name"
|
|
41
|
+
t.decimal "latitude"
|
|
42
|
+
t.decimal "longitude"
|
|
43
|
+
t.string "customer_email"
|
|
44
|
+
t.boolean "password_enabled"
|
|
45
|
+
t.string "phone"
|
|
46
|
+
t.string "primary_locale"
|
|
47
|
+
t.string "ships_to_countries"
|
|
48
|
+
t.string "timezone"
|
|
49
|
+
t.string "iana_timezone"
|
|
50
|
+
t.boolean "has_storefront"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
add_index "disco_app_shops", ["shopify_domain"], name: "index_disco_app_shops_on_shopify_domain", unique: true
|
|
54
|
+
|
|
55
|
+
create_table "disco_app_subscriptions", force: :cascade do |t|
|
|
56
|
+
t.integer "shop_id"
|
|
57
|
+
t.integer "plan_id"
|
|
58
|
+
t.integer "status"
|
|
59
|
+
t.string "name"
|
|
60
|
+
t.integer "charge_type"
|
|
61
|
+
t.decimal "price"
|
|
62
|
+
t.integer "trial_days"
|
|
63
|
+
t.datetime "created_at", null: false
|
|
64
|
+
t.datetime "updated_at", null: false
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
add_index "disco_app_subscriptions", ["plan_id"], name: "index_disco_app_subscriptions_on_plan_id"
|
|
68
|
+
add_index "disco_app_subscriptions", ["shop_id"], name: "index_disco_app_subscriptions_on_shop_id"
|
|
69
|
+
|
|
70
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shop": {
|
|
3
|
+
"id": 3788917,
|
|
4
|
+
"name": "ONE INCH ROUND ® ",
|
|
5
|
+
"email": "gavin@gavinballard.com",
|
|
6
|
+
"domain": "one-inch-round-development.myshopify.com",
|
|
7
|
+
"created_at": "2014-02-19T11:50:27-08:00",
|
|
8
|
+
"province": "Oregon",
|
|
9
|
+
"country": "US",
|
|
10
|
+
"address1": "4016 SE Division St. #A",
|
|
11
|
+
"zip": "97202",
|
|
12
|
+
"city": "Portland",
|
|
13
|
+
"source": null,
|
|
14
|
+
"phone": "5032338003",
|
|
15
|
+
"updated_at": "2015-10-07T14:35:47-07:00",
|
|
16
|
+
"customer_email": null,
|
|
17
|
+
"latitude": 45.5048,
|
|
18
|
+
"longitude": -122.621,
|
|
19
|
+
"primary_location_id": null,
|
|
20
|
+
"primary_locale": "en",
|
|
21
|
+
"country_code": "US",
|
|
22
|
+
"country_name": "United States",
|
|
23
|
+
"currency": "USD",
|
|
24
|
+
"timezone": "(GMT-08:00) Pacific Time (US & Canada)",
|
|
25
|
+
"iana_timezone": "America/Los_Angeles",
|
|
26
|
+
"shop_owner": "Gavin Ballard",
|
|
27
|
+
"money_format": "${{amount}}",
|
|
28
|
+
"money_with_currency_format": "${{amount}} USD",
|
|
29
|
+
"province_code": "OR",
|
|
30
|
+
"taxes_included": false,
|
|
31
|
+
"tax_shipping": null,
|
|
32
|
+
"county_taxes": true,
|
|
33
|
+
"plan_display_name": "affiliate",
|
|
34
|
+
"plan_name": "affiliate",
|
|
35
|
+
"myshopify_domain": "one-inch-round-development.myshopify.com",
|
|
36
|
+
"google_apps_domain": null,
|
|
37
|
+
"google_apps_login_enabled": null,
|
|
38
|
+
"money_in_emails_format": "${{amount}}",
|
|
39
|
+
"money_with_currency_in_emails_format": "${{amount}} USD",
|
|
40
|
+
"eligible_for_payments": true,
|
|
41
|
+
"requires_extra_payments_agreement": false,
|
|
42
|
+
"password_enabled": false,
|
|
43
|
+
"has_storefront": true,
|
|
44
|
+
"setup_required": false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
development:
|
|
2
|
+
status: 2
|
|
3
|
+
name: Development
|
|
4
|
+
charge_type: 0
|
|
5
|
+
default_price: 0.00
|
|
6
|
+
default_trial_days: 14
|
|
7
|
+
|
|
8
|
+
comped:
|
|
9
|
+
status: 2
|
|
10
|
+
name: Comped
|
|
11
|
+
charge_type: 0
|
|
12
|
+
default_price: 0.00
|
|
13
|
+
default_trial_days: 0
|
|
14
|
+
|
|
15
|
+
cheapo:
|
|
16
|
+
status: 1
|
|
17
|
+
name: Cheapo
|
|
18
|
+
charge_type: 0
|
|
19
|
+
default_price: 0.99
|
|
20
|
+
default_trial_days: 14
|
|
21
|
+
|
|
22
|
+
basic:
|
|
23
|
+
name: Basic
|
|
24
|
+
charge_type: 0
|
|
25
|
+
default_price: 9.99
|
|
26
|
+
default_trial_days: 14
|
|
27
|
+
|
|
28
|
+
premium:
|
|
29
|
+
name: Premium
|
|
30
|
+
charge_type: 0
|
|
31
|
+
default_price: 49.99
|
|
32
|
+
default_trial_days: 14
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
widget_store:
|
|
2
|
+
shopify_domain: widgets.myshopify.com
|
|
3
|
+
shopify_token: 00000000000000000000000000000000
|
|
4
|
+
country_name: Australia
|
|
5
|
+
|
|
6
|
+
widget_store_dev:
|
|
7
|
+
shopify_domain: widgets-dev.myshopify.com
|
|
8
|
+
shopify_token: 00000000000000000000000000000000
|
|
9
|
+
status: 3
|
|
10
|
+
country_name: Australia
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
widget_store_old:
|
|
2
|
+
shop: widget_store
|
|
3
|
+
plan: cheapo
|
|
4
|
+
status: <%= DiscoApp::Subscription.statuses[:replaced] %>
|
|
5
|
+
name: Cheapo
|
|
6
|
+
charge_type: 0
|
|
7
|
+
price: 0.99
|
|
8
|
+
trial_days: 14
|
|
9
|
+
|
|
10
|
+
widget_store:
|
|
11
|
+
shop: widget_store
|
|
12
|
+
plan: basic
|
|
13
|
+
status: <%= DiscoApp::Subscription.statuses[:active] %>
|
|
14
|
+
name: Basic
|
|
15
|
+
charge_type: 0
|
|
16
|
+
price: 9.99
|
|
17
|
+
trial_days: 14
|
|
18
|
+
|
|
19
|
+
widget_store_dev:
|
|
20
|
+
shop: widget_store_dev
|
|
21
|
+
plan: development
|
|
22
|
+
status: <%= DiscoApp::Subscription.statuses[:active] %>
|
|
23
|
+
name: Development
|
|
24
|
+
charge_type: 0
|
|
25
|
+
price: 0.00
|
|
26
|
+
trial_days: 0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shop": {
|
|
3
|
+
"id": 3788917,
|
|
4
|
+
"name": "ONE INCH ROUND ® ",
|
|
5
|
+
"email": "gavin@gavinballard.com",
|
|
6
|
+
"domain": "one-inch-round-development.myshopify.com",
|
|
7
|
+
"created_at": "2014-02-19T11:50:27-08:00",
|
|
8
|
+
"province": "Oregon",
|
|
9
|
+
"country": "US",
|
|
10
|
+
"address1": "4016 SE Division St. #A",
|
|
11
|
+
"zip": "97202",
|
|
12
|
+
"city": "Portland",
|
|
13
|
+
"source": null,
|
|
14
|
+
"phone": "5032338003",
|
|
15
|
+
"updated_at": "2015-10-07T14:35:47-07:00",
|
|
16
|
+
"customer_email": null,
|
|
17
|
+
"latitude": 45.5048,
|
|
18
|
+
"longitude": -122.621,
|
|
19
|
+
"primary_location_id": null,
|
|
20
|
+
"primary_locale": "en",
|
|
21
|
+
"country_code": "US",
|
|
22
|
+
"country_name": "United States",
|
|
23
|
+
"currency": "USD",
|
|
24
|
+
"timezone": "(GMT-08:00) Pacific Time (US & Canada)",
|
|
25
|
+
"iana_timezone": "America/Los_Angeles",
|
|
26
|
+
"shop_owner": "Gavin Ballard",
|
|
27
|
+
"money_format": "${{amount}}",
|
|
28
|
+
"money_with_currency_format": "${{amount}} USD",
|
|
29
|
+
"province_code": "OR",
|
|
30
|
+
"taxes_included": false,
|
|
31
|
+
"tax_shipping": null,
|
|
32
|
+
"county_taxes": true,
|
|
33
|
+
"plan_display_name": "affiliate",
|
|
34
|
+
"plan_name": "affiliate",
|
|
35
|
+
"myshopify_domain": "one-inch-round-development.myshopify.com",
|
|
36
|
+
"google_apps_domain": null,
|
|
37
|
+
"google_apps_login_enabled": null,
|
|
38
|
+
"money_in_emails_format": "${{amount}}",
|
|
39
|
+
"money_with_currency_in_emails_format": "${{amount}} USD",
|
|
40
|
+
"eligible_for_payments": true,
|
|
41
|
+
"requires_extra_payments_agreement": false,
|
|
42
|
+
"password_enabled": false,
|
|
43
|
+
"has_storefront": true,
|
|
44
|
+
"setup_required": false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DiscoApp::AppInstalledJobTest < ActionController::TestCase
|
|
4
|
+
include ActiveJob::TestHelper
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
@shop = disco_app_shops(:widget_store)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def teardown
|
|
11
|
+
@shop = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'app installed job performs shop update job' do
|
|
15
|
+
stub_request(:post, "#{@shop.admin_url}/webhooks.json").to_return(status: 200)
|
|
16
|
+
stub_request(:get, "#{@shop.admin_url}/shop.json").to_return(status: 200, body: api_fixture('widget_store/shop'))
|
|
17
|
+
|
|
18
|
+
# Assert the main install job can be enqueued and performed.
|
|
19
|
+
perform_enqueued_jobs do
|
|
20
|
+
DiscoApp::AppInstalledJob.perform_later(@shop.shopify_domain)
|
|
21
|
+
end
|
|
22
|
+
assert_performed_jobs 1
|
|
23
|
+
|
|
24
|
+
# Assert the update shop job was performed.
|
|
25
|
+
@shop.reload
|
|
26
|
+
assert_equal 'United States', @shop.country_name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DiscoApp::AppUninstalledJobTest < ActionController::TestCase
|
|
4
|
+
include ActiveJob::TestHelper
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
@shop = disco_app_shops(:widget_store)
|
|
8
|
+
@shop.charge_active!
|
|
9
|
+
|
|
10
|
+
perform_enqueued_jobs do
|
|
11
|
+
DiscoApp::AppUninstalledJob.perform_later(@shop.shopify_domain, {})
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def teardown
|
|
16
|
+
@shop = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test 'app uninstalled job changes shop status' do
|
|
20
|
+
assert_performed_jobs 1
|
|
21
|
+
@shop.reload
|
|
22
|
+
assert @shop.uninstalled?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test 'app uninstalled job can be extended using concerns' do
|
|
26
|
+
assert_performed_jobs 1
|
|
27
|
+
@shop.reload
|
|
28
|
+
assert @shop.charge_cancelled? # Assert base methods still called.
|
|
29
|
+
assert_equal 'Nowhere', @shop.country_name # Assert extended method called.
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DiscoApp::ShopTest < ActiveSupport::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
@shop = disco_app_shops(:widget_store)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def teardown
|
|
10
|
+
@shop = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test 'shops can be extended via concerns' do
|
|
14
|
+
assert_equal 'Australia', @shop.country.name
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'can fetch a list of all of a shops subscriptions' do
|
|
18
|
+
assert_equal 2, @shop.subscriptions.size
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test 'can fetch a shops active subscription' do
|
|
22
|
+
assert_equal 1, @shop.subscriptions.active.size
|
|
23
|
+
assert_equal disco_app_subscriptions(:widget_store), @shop.subscriptions.active.first
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DiscoApp::SubscriptionServiceTest < ActiveSupport::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
@shop = disco_app_shops(:widget_store)
|
|
7
|
+
@current_subscription = @shop.current_subscription
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def teardown
|
|
11
|
+
@shop = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
test 'subscribing to a new plan deactivates current subscription and swaps to new plan' do
|
|
15
|
+
DiscoApp::SubscriptionService.subscribe(@shop, disco_app_plans(:premium))
|
|
16
|
+
@current_subscription.reload
|
|
17
|
+
assert @current_subscription.replaced?
|
|
18
|
+
assert_equal disco_app_plans(:premium), @shop.current_subscription.plan
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test 'cancelling a plan works' do
|
|
22
|
+
DiscoApp::SubscriptionService.cancel(@shop)
|
|
23
|
+
@current_subscription.reload
|
|
24
|
+
assert @current_subscription.cancelled?
|
|
25
|
+
assert_not @shop.current_subscription
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|