Skip to content

Commit 8088a00

Browse files
authored
Merge pull request #18 from code-corps/add-tests
Add tests
2 parents 545f9ae + 3b524fc commit 8088a00

File tree

17 files changed

+335
-25
lines changed

17 files changed

+335
-25
lines changed

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ A simple Ember wrapper for [Stripe Elements](https://stripe.com/docs/elements).
1919

2020
## Features
2121

22-
- Inject `<script src="https://js.stripe.com/v3/"></script>` into your application's `<head>` tag
22+
- Inject `<script src="https://js.stripe.com/v3/"></script>` into your application's `<body>`
2323
- Initialize `Stripe` with your publishable key
2424
- Inject a `stripev3` service into your controllers so you can use:
2525
- [`stripe.createToken(element[, options])`](https://stripe.com/docs/elements/reference#stripe-create-token)
@@ -47,6 +47,33 @@ ENV.stripe = {
4747
};
4848
```
4949

50+
### Lazy loading
51+
52+
You can configure Stripe.js to lazy load when you need it.
53+
54+
```js
55+
ENV.stripe = {
56+
lazyLoad: true
57+
};
58+
```
59+
60+
When enabled, Stripe.js will not be loaded until you call the `load()` function on the service. It's best to call this function in a route's `beforeModel` hook.
61+
62+
```js
63+
// subscription page route
64+
65+
import Route from '@ember/routing/route';
66+
import { inject as service } from '@ember/service';
67+
68+
export default Route.extend({
69+
stripe: service('stripev3'),
70+
71+
beforeModel() {
72+
return this.get('stripe').load();
73+
}
74+
});
75+
```
76+
5077
## Components
5178

5279
### Basics

addon/services/stripev3.js

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,53 @@
11
/* global Stripe */
2-
import EmberError from '@ember/error';
3-
import { getOwner } from '@ember/application';
42
import Service from '@ember/service';
53
import { setProperties } from '@ember/object';
4+
import { readOnly } from '@ember/object/computed';
5+
import { resolve } from 'rsvp';
6+
import loadScript from 'ember-stripe-elements/utils/load-script';
67

78
export default Service.extend({
9+
config: null,
10+
didConfigure: false,
11+
didLoad: false,
12+
13+
lazyLoad: readOnly('config.lazyLoad'),
14+
mock: readOnly('config.mock'),
15+
publishableKey: readOnly('config.publishableKey'),
16+
817
init() {
918
this._super(...arguments);
1019

11-
const config = getOwner(this).resolveRegistration('config:environment');
20+
let lazyLoad = this.get('lazyLoad');
21+
let mock = this.get('mock');
1222

13-
if (!config.stripe && !config.stripe.publishableKey) {
14-
throw new EmberError('StripeService: Missing Stripe key, please set `ENV.stripe.publishableKey` in config.environment.js');
23+
if (!lazyLoad || mock) {
24+
this.configure();
1525
}
26+
},
27+
28+
load() {
29+
let lazyLoad = this.get('lazyLoad');
30+
let mock = this.get('mock');
31+
let shouldLoad = lazyLoad && !mock
32+
33+
let doLoad = shouldLoad ? loadScript("https://js.stripe.com/v3/") : resolve();
34+
35+
return doLoad.then(() => {
36+
this.configure();
37+
this.set('didLoad', true);
38+
});
39+
},
1640

17-
let { elements, createToken, createSource, retrieveSource, paymentRequest } = new Stripe(config.stripe.publishableKey);
18-
setProperties(this, { elements, createToken, createSource, retrieveSource, paymentRequest });
41+
configure() {
42+
let didConfigure = this.get('didConfigure');
43+
44+
if (!didConfigure) {
45+
let publishableKey = this.get('publishableKey');
46+
47+
let { elements, createToken, createSource, retrieveSource, paymentRequest } = new Stripe(publishableKey);
48+
setProperties(this, { elements, createToken, createSource, retrieveSource, paymentRequest });
49+
50+
this.set('didConfigure', true);
51+
}
1952
}
2053
});

addon/utils/load-script.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { run } from '@ember/runloop';
2+
import RSVP from 'rsvp';
3+
4+
/*
5+
* loadScript will load a JavaScript asset. Subsequent load
6+
* calls with a already requested URL will just chain off the
7+
* already existing promise.
8+
*/
9+
10+
let loadedScripts = {};
11+
12+
export default function loadScript(url) {
13+
let promise = loadedScripts[url];
14+
15+
if (!promise) {
16+
promise = new RSVP.Promise((resolve, reject) => {
17+
let element = document.createElement('script');
18+
element.type = 'text/javascript';
19+
element.async = false;
20+
element.addEventListener('load', () => {
21+
run(() => {
22+
resolve();
23+
});
24+
}, false);
25+
element.addEventListener('error', () => {
26+
let error = new Error(`Could not load script ${url}`);
27+
run(() => {
28+
reject(error);
29+
});
30+
}, false);
31+
32+
element.src = url;
33+
34+
let firstScript = document.getElementsByTagName('script')[0];
35+
firstScript.parentNode.insertBefore(element, firstScript);
36+
});
37+
38+
loadedScripts[url] = promise;
39+
}
40+
41+
return promise;
42+
}

addon/utils/stripe-mock.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
let StripeMock = function(publishableKey) {
2+
this.publishableKey = publishableKey;
3+
}
4+
5+
StripeMock.prototype.elements = function() {
6+
return {
7+
create: function() {
8+
return {
9+
mount: function() {},
10+
on: function() {},
11+
unmount: function() {}
12+
}
13+
}
14+
};
15+
}
16+
StripeMock.prototype.createToken = function() {}
17+
StripeMock.prototype.createSource = function() {}
18+
StripeMock.prototype.retrieveSource = function() {}
19+
StripeMock.prototype.paymentRequest = function() {}
20+
21+
export default StripeMock;

app/initializers/ember-stripe-elements.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import EmberError from '@ember/error';
22
import config from '../config/environment';
3+
import StripeMock from 'ember-stripe-elements/utils/stripe-mock';
34

45
export function initialize() {
56
const application = arguments[1] || arguments[0];
7+
let stripeConfig = config.stripe || {};
68

7-
application.register('config:ember-stripe-elements', config, { instantiate: false });
9+
application.register('config:stripe', stripeConfig, { instantiate: false });
10+
application.inject('service:stripev3', 'config', 'config:stripe');
811

9-
if (!config.stripe && !config.stripe.publishableKey) {
10-
throw new EmberError('StripeService: Missing Stripe key, please set `ENV.stripe.publishableKey` in config.environment.js');
12+
if (!stripeConfig.publishableKey) {
13+
throw new Ember.Error("stripev3: Missing Stripe key, please set `ENV.stripe.publishableKey` in config.environment.js");
14+
}
15+
16+
if (typeof FastBoot !== 'undefined' || stripeConfig.mock) {
17+
window.Stripe = StripeMock;
1118
}
1219
}
1320

index.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44
module.exports = {
55
name: 'ember-stripe-elements',
66

7-
contentFor(type) {
8-
if (type === 'head') {
7+
contentFor(type, config) {
8+
let stripeConfig = config.stripe || {};
9+
10+
var lazyLoad = stripeConfig.lazyLoad;
11+
var mock = stripeConfig.mock;
12+
13+
if (type === 'body' && !lazyLoad && !mock) {
914
return '<script type="text/javascript" src="https://js.stripe.com/v3/"></script>';
1015
}
1116
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"ember-disable-prototype-extensions": "^1.1.2",
4343
"ember-export-application-global": "^2.0.0",
4444
"ember-load-initializers": "^1.0.0",
45+
"ember-qunit-assert-helpers": "^0.2.1",
4546
"ember-resolver": "^4.0.0",
4647
"ember-sinon": "^1.0.1",
4748
"ember-sinon-qunit": "1.4.1",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { module, test } from 'ember-qunit';
2+
import config from 'dummy/config/environment';
3+
import startApp from '../helpers/start-app';
4+
5+
module('Acceptance | Publishable Key');
6+
7+
test('it throws an error if config.stripe.publishableKey is not set', function(assert) {
8+
let originalKey = config.stripe.publishableKey;
9+
config.stripe.publishableKey = undefined;
10+
11+
assert.expectAssertion(function() {
12+
startApp();
13+
}, /Missing Stripe key/);
14+
15+
config.stripe.publishableKey = originalKey;
16+
});

tests/dummy/app/routes/application.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
import Route from '@ember/routing/route';
2+
import { inject as service } from '@ember/service';
23

3-
export default Route.extend();
4+
export default Route.extend({
5+
stripe: service('stripev3'),
6+
7+
beforeModel() {
8+
return this.get('stripe').load();
9+
}
10+
});

tests/dummy/config/environment.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = function(environment) {
2525
};
2626

2727
ENV.stripe = {
28+
lazyLoad: true,
2829
publishableKey: process.env.STRIPE_PUBLISHABLE_KEY || 'pk_thisIsATestKey'
2930
};
3031

0 commit comments

Comments
 (0)