Skip to content

Commit

Permalink
Merge pull request #573 from recurly/fix-hosted-field-reset-on-configure
Browse files Browse the repository at this point in the history
Fixes HostedFields reset on re-configuration preceding initialization
  • Loading branch information
dbrudner authored Jan 13, 2020
2 parents a8f31ee + cb40a80 commit 42c06f6
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
8 changes: 7 additions & 1 deletion lib/recurly.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,17 @@ export class Recurly extends Emitter {
// do not match chosen selectors, reset
let reset = (
this.hostedFields
&& this.readyState > 1
&& this.readyState > 0
&& !this.hostedFields.integrityCheck(this.config.fields)
);

if (reset) {
// If we are between states 1 and 2, we must abandon the advancement listeners
if (this.readyState === 1) {
this.off('hostedFields:ready');
this.off('hostedFields:state:change');
this.off('hostedField:submit');
}
this.readyState = 0;
this.hostedFields.destroy();
}
Expand Down
2 changes: 0 additions & 2 deletions lib/recurly/hosted-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export class HostedFields extends Emitter {
this.fields = [];
this.errors = [];
this.initQueue = [];
this.readyState = 0;
this.recurly = recurly;
this.configure(recurly.sanitizedConfig);
this.inject();
Expand Down Expand Up @@ -115,7 +114,6 @@ export class HostedFields extends Emitter {
debug('destroying HostedFields');
this.off();
this.ready = false;
this.readyState = 0;
this.fields.forEach(field => field.destroy());
if (this.bus) this.bus.remove(this);
this.fields = [];
Expand Down
50 changes: 49 additions & 1 deletion test/recurly.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import assert from 'assert';
import { initRecurly } from './support/helpers';
import { applyFixtures } from './support/fixtures';
import { initRecurly, nextTick, testBed } from './support/helpers';
import { isAUid } from './support/matchers';
import { Recurly } from '../lib/recurly';
import CheckoutPricing from '../lib/recurly/pricing/checkout';
Expand Down Expand Up @@ -74,6 +75,53 @@ describe('Recurly', function () {
recurly.configure({ publicKey: 'test-2' });
assert.strictEqual(!!~recurly.bus.recipients.indexOf(stub), true);
});

describe('when hostedFields are not finished initializing', function () {
applyFixtures();

this.ctx.fixture = 'multipleForms';

it('resets hostedFields and abandons the prior listeners', function (done) {
const { recurly, sandbox } = this;
const readyStub = sandbox.stub();
sandbox.spy(recurly, 'off');
assert.strictEqual(recurly.readyState, 0);
initRecurly(recurly, {
fields: {
number: { selector: '#number-1' },
month: { selector: '#month-1' },
year: { selector: '#year-1' },
cvv: { selector: '#cvv-1' }
}
});
assert.strictEqual(recurly.readyState, 1);
assert(recurly.off.notCalled);
recurly.configure({
fields: {
number: { selector: '#number-2' },
month: { selector: '#month-2' },
year: { selector: '#year-2' },
cvv: { selector: '#cvv-2' }
}
});
assert.strictEqual(recurly.readyState, 1);
recurly.on('hostedFields:ready', readyStub);

recurly.ready(() => {
// perform on next tick to allow the ready callback stack to proceed to the stub
nextTick(() => {
assert.strictEqual(recurly.readyState, 2);
assert(readyStub.calledOnce);
assert.strictEqual(testBed().querySelectorAll('#test-form-1 iframe').length, 0);
assert.strictEqual(testBed().querySelectorAll('#test-form-2 iframe').length, 4);
assert(recurly.off.calledWithExactly('hostedFields:ready'));
assert(recurly.off.calledWithExactly('hostedFields:state:change'));
assert(recurly.off.calledWithExactly('hostedField:submit'));
done();
});
});
});
});
});
});

Expand Down

0 comments on commit 42c06f6

Please sign in to comment.