Skip to content

Commit

Permalink
Merge pull request #64 from code-corps/issue49
Browse files Browse the repository at this point in the history
Add contextual component for using individual Stripe elements
  • Loading branch information
st-h authored Sep 3, 2019
2 parents b0bbcd3 + ecda8b6 commit 1e0be18
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 10 deletions.
57 changes: 49 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ ENV.stripe = {

### Mocking the Stripe API

You can configure the Stripe API to be mocked instead of loaded from `https://js.stripe.com/v3/`. This is useful for testing.
You can configure the Stripe API to be mocked instead of loaded from `https://js.stripe.com/v3/`. This is useful for testing.

```js
ENV.stripe = {
mock: true
};
```

When enabled, a [mock Stripe object](https://github.com/code-corps/ember-stripe-elements/blob/develop/addon/utils/stripe-mock.js) will be assigned to `window.Stripe` when your app is initialized.
When enabled, a [mock Stripe object](https://github.com/code-corps/ember-stripe-elements/blob/develop/addon/utils/stripe-mock.js) will be assigned to `window.Stripe` when your app is initialized.

When using the Stripe mock in tests you will likely need to override the mock's methods according to the needs of your test like so:

Expand Down Expand Up @@ -154,13 +154,54 @@ You could handle these actions yourself, for example:

This addon gives you components that match the different [Element types](https://stripe.com/docs/elements/reference#element-types):

- `{{stripe-card}}` - `card` (recommended) A flexible single-line input that collects all necessary card details.
- `{{stripe-card-number}}` - `cardNumber` The card number.
- `{{stripe-card-expiry}}` - `cardExpiry` The card's expiration date.
- `{{stripe-card-cvc}}` - `cardCvc` The card's CVC number.
- `{{stripe-postal-code}}` - `postalCode` the ZIP/postal code.
Stripe recommends using the their `card` element - a flexible single-line input that collects all necessary card details.
The `{{stripe-card}}` component provides this input.

### Block usage with `options`
Additionally Stripe provides the following elements, which you can use to build your own form to collect card details:

- `cardNumber`: the card number.
- `cardExpiry`: the card's expiration date.
- `cardCvc`: the card's CVC number.
- `postalCode`: the ZIP/postal code.

These are provided via our `{{stripe-elements}}` contextual component, which yields sub-components for each element type:

```hbs
{{#stripe-elements as |elements|}}
{{elements.cardNumber}}
{{elements.cardExpiry}}
{{elements.cardCvc}}
{{elements.postalCode}}
{{/stripe-elements}}
```

> The `{{stripe-elements}}` component is a tagless component, so does not have any classes etc on it.
### Elements Options

The `{{stripe-elements}}` contextual component ensures all the individual elements are created from
the same [Stripe Elements object](https://stripe.com/docs/stripe-js/reference#the-elements-object).

If you want to pass options to the Stripe Elements object, pass them to the `{{stripe-elements}}`
contextual component. For example, when using the single-line `card` element:

```hbs
{{#stripe-elements options=elementOptions as |elements|}}
{{elements.card options=cardOptions}}
{{/stripe-elements}}
```

Or when creating your own form:

```hbs
{{#stripe-elements options=elementsOptions as |elements|}}
{{elements.cardNumber options=cardNumberOptions}}
{{elements.cardExpiry}}
{{elements.cardCvc}}
{{/stripe-elements}}
```

### Block usage with element `options`

In addition to the simple usage above, like `{{stripe-card}}`, you can also yield to a block, which will yield both an `stripeError` object and [the `stripeElement` itself](https://stripe.com/docs/elements/reference#the-element).

Expand Down
11 changes: 9 additions & 2 deletions addon/components/stripe-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ export default Component.extend({
type: null, // Set in components that extend from `stripe-element`

stripev3: service(),
elements: computed(function() {
return get(this, 'stripev3.elements')();

elements: computed({
get() {
return get(this, 'stripev3.elements')();
},

set(key, value) {
return value;
}
}),

didInsertElement() {
Expand Down
17 changes: 17 additions & 0 deletions addon/components/stripe-elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Component from '@ember/component';
import layout from '../templates/components/stripe-elements';
import { inject as service } from '@ember/service';
import { get, set } from '@ember/object';

export default Component.extend({
stripe: service('stripev3'),
tagName: '',
layout,

init() {
this._super(...arguments);
let options = get(this, 'options') || {};
let elements = get(this, 'stripe').elements(options);
set(this, 'elements', elements);
}
});
17 changes: 17 additions & 0 deletions addon/templates/components/stripe-elements.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{yield (hash
card=(component "stripe-card"
elements=elements
)
cardNumber=(component "stripe-card-number"
elements=elements
)
cardExpiry=(component "stripe-card-expiry"
elements=elements
)
cardCvc=(component "stripe-card-cvc"
elements=elements
)
postalCode=(component "stripe-postal-code"
elements=elements
)
)}}
1 change: 1 addition & 0 deletions app/components/stripe-elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ember-stripe-elements/components/stripe-elements';
58 changes: 58 additions & 0 deletions tests/integration/components/stripe-elements-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import StripeMock from 'ember-stripe-elements/utils/stripe-mock';
import StripeService from 'dummy/services/stripev3';
import env from 'dummy/config/environment';

module('Integration | Component | stripe-elements', function(hooks) {
setupRenderingTest(hooks);

hooks.beforeEach(function() {
window.Stripe = StripeMock;
const config = {
mock: true,
publishableKey: env.stripe.publishableKey,
};

this.owner.register(
'service:stripev3',
StripeService.create({ config }),
{ instantiate: false }
);
});

test('it renders single-line element', async function (assert) {
await render(hbs`
{{#stripe-elements as |elements|}}
{{elements.card}}
{{/stripe-elements}}
`);

assert.ok(find('.ember-stripe-card > [role="mount-point"]'));
});

test('it renders individual elements', async function (assert) {
await render(hbs`
{{#stripe-elements as |elements|}}
{{elements.cardNumber}}
{{elements.cardExpiry}}
{{elements.cardCvc}}
{{elements.postalCode}}
{{/stripe-elements}}
`);

let tests = [
'card-number',
'card-expiry',
'card-cvc',
'postal-code'
];

do {
let el = tests.shift();
assert.ok(find(`.ember-stripe-${el} > [role="mount-point"]`), el);
} while(tests.length);
});
});

0 comments on commit 1e0be18

Please sign in to comment.