Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add contextual component for using individual Stripe elements #64

Merged
merged 4 commits into from
Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
});
});