@financial-times/n-conversion-forms 23.0.3 → 23.0.6
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.
- package/.circleci/config.yml +4 -4
- package/__mocks__/@financial-times/o-expander.js +9 -0
- package/__mocks__/@financial-times/o-forms-input.js +11 -0
- package/__mocks__/@financial-times/o-forms.js +40 -0
- package/build-state/npm-shrinkwrap.json +81 -172
- package/components/delivery-security-instructions.spec.js +3 -3
- package/components/graduation-date.spec.js +8 -8
- package/components/payment-term.spec.js +3 -3
- package/components/position.jsx +6 -3
- package/components/position.spec.js +15 -5
- package/components/responsibility.jsx +6 -3
- package/components/responsibility.spec.js +15 -5
- package/dist/position.js +6 -2
- package/dist/responsibility.js +6 -2
- package/helpers/index.spec.js +11 -0
- package/helpers/ncf-common-data.spec.js +34 -0
- package/helpers/ncf-countries.spec.js +136 -0
- package/jest.config.js +3 -0
- package/package.json +3 -2
- package/utils/app-banner.spec.js +68 -0
- package/utils/apple-pay.spec.js +177 -0
- package/utils/billing-country.spec.js +87 -0
- package/utils/billing-postcode.spec.js +138 -0
- package/utils/company-name.spec.js +3 -7
- package/utils/country.spec.js +87 -0
- package/utils/delivery-address-type.spec.js +24 -11
- package/utils/delivery-option-messages.spec.js +3 -3
- package/utils/delivery-option.spec.js +100 -15
- package/utils/delivery-postcode.spec.js +138 -0
- package/utils/delivery-start-date.spec.js +177 -0
- package/utils/email.spec.js +210 -0
- package/utils/event-notifier.spec.js +116 -0
- package/utils/form-element.spec.js +71 -0
- package/utils/loader.spec.js +161 -0
- package/utils/password.spec.js +65 -0
- package/utils/payment-term.spec.js +198 -0
- package/utils/payment-type.spec.js +136 -0
- package/utils/postcode.spec.js +122 -0
- package/utils/salesforce.spec.js +30 -0
- package/utils/submit.spec.js +81 -0
- package/utils/tracking.spec.js +174 -0
- package/utils/validation.spec.js +234 -0
- package/utils/zuora.spec.js +249 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const EventNotifier = require('./event-notifier');
|
|
2
|
+
|
|
3
|
+
describe('Event Notifier', () => {
|
|
4
|
+
const defaults = {
|
|
5
|
+
event: 'focusin',
|
|
6
|
+
buffer: 50,
|
|
7
|
+
emitProperty: 'height',
|
|
8
|
+
watchedProperty: 'clientHeight',
|
|
9
|
+
};
|
|
10
|
+
let mockElement;
|
|
11
|
+
let alternativeWindow;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
mockElement = {
|
|
15
|
+
clientWidth: 100,
|
|
16
|
+
clientHeight: 25,
|
|
17
|
+
addEventListener: jest.fn(),
|
|
18
|
+
};
|
|
19
|
+
global.parent = {
|
|
20
|
+
postMessage: jest.fn(),
|
|
21
|
+
};
|
|
22
|
+
alternativeWindow = {
|
|
23
|
+
postMessage: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
jest.spyOn(parent, 'postMessage');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
delete global.parent;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('does not do anything if element not provided', () => {
|
|
34
|
+
EventNotifier.init();
|
|
35
|
+
expect(parent.postMessage).not.toHaveBeenCalled();
|
|
36
|
+
expect(mockElement.addEventListener).not.toHaveBeenCalled();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('does not do anything if element not valid', () => {
|
|
40
|
+
EventNotifier.init(null);
|
|
41
|
+
expect(parent.postMessage).not.toHaveBeenCalled();
|
|
42
|
+
expect(mockElement.addEventListener).not.toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('attaches an event listener of the default event to the provided element', () => {
|
|
46
|
+
EventNotifier.init(mockElement);
|
|
47
|
+
expect(mockElement.addEventListener).toHaveBeenCalledTimes(1);
|
|
48
|
+
expect(mockElement.addEventListener).toHaveBeenCalledWith(
|
|
49
|
+
defaults.event,
|
|
50
|
+
expect.anything()
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('attaches an event listener of custom event if one provided', () => {
|
|
55
|
+
const customEvent = 'something';
|
|
56
|
+
EventNotifier.init(mockElement, { event: customEvent });
|
|
57
|
+
expect(mockElement.addEventListener).toHaveBeenCalledTimes(1);
|
|
58
|
+
expect(mockElement.addEventListener).toHaveBeenCalledWith(
|
|
59
|
+
customEvent,
|
|
60
|
+
expect.anything()
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('does immediately postMessage if "notifyOnStart" is true', () => {
|
|
65
|
+
EventNotifier.init(mockElement, { notifyOnStart: true });
|
|
66
|
+
expect(parent.postMessage).toHaveBeenCalledTimes(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('does not immediately postMessage if "notifyOnStart" is false', () => {
|
|
70
|
+
EventNotifier.init(mockElement, { notifyOnStart: false });
|
|
71
|
+
expect(parent.postMessage).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('does postMessage when the event listener is triggered', () => {
|
|
75
|
+
mockElement.addEventListener = jest.fn(() => {
|
|
76
|
+
parent.postMessage();
|
|
77
|
+
});
|
|
78
|
+
EventNotifier.init(mockElement);
|
|
79
|
+
expect(parent.postMessage).toHaveBeenCalledTimes(2);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('does postMessage when the event listener is triggered even if notifyOnStart is false', () => {
|
|
83
|
+
mockElement.addEventListener = jest.fn(() => {
|
|
84
|
+
parent.postMessage();
|
|
85
|
+
});
|
|
86
|
+
EventNotifier.init(mockElement, { notifyOnStart: false });
|
|
87
|
+
expect(parent.postMessage).toHaveBeenCalledTimes(1);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('does postMessage with the element clientHeight + default buffer value as the message height property by default', () => {
|
|
91
|
+
const expectedPayload = JSON.stringify({
|
|
92
|
+
[defaults.emitProperty]:
|
|
93
|
+
mockElement[defaults.watchedProperty] + defaults.buffer,
|
|
94
|
+
});
|
|
95
|
+
EventNotifier.init(mockElement, { notifyOnStart: true });
|
|
96
|
+
expect(parent.postMessage).toHaveBeenCalledWith(expectedPayload, '*');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('can override emitted, watched and buffer properties', () => {
|
|
100
|
+
const expectedPayload = JSON.stringify({
|
|
101
|
+
width: mockElement.clientWidth + 10,
|
|
102
|
+
});
|
|
103
|
+
EventNotifier.init(mockElement, {
|
|
104
|
+
emitProperty: 'width',
|
|
105
|
+
watchedProperty: 'clientWidth',
|
|
106
|
+
buffer: 10,
|
|
107
|
+
});
|
|
108
|
+
expect(parent.postMessage).toHaveBeenCalledWith(expectedPayload, '*');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('can take an alternative window to notify', () => {
|
|
112
|
+
EventNotifier.init(mockElement, { targetWindow: alternativeWindow });
|
|
113
|
+
expect(alternativeWindow.postMessage).toHaveBeenCalledTimes(1);
|
|
114
|
+
expect(parent.postMessage).not.toHaveBeenCalled();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const FormElement = require('./form-element');
|
|
2
|
+
|
|
3
|
+
describe('FormElement', () => {
|
|
4
|
+
let formElement;
|
|
5
|
+
let document;
|
|
6
|
+
let addStub;
|
|
7
|
+
let removeStub;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
addStub = jest.fn();
|
|
11
|
+
removeStub = jest.fn();
|
|
12
|
+
document = {
|
|
13
|
+
querySelector: () => {
|
|
14
|
+
return {
|
|
15
|
+
querySelectorAll: () => {},
|
|
16
|
+
querySelector: () => {
|
|
17
|
+
return {
|
|
18
|
+
value: 'test',
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
classList: {
|
|
22
|
+
add: addStub,
|
|
23
|
+
remove: removeStub,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
formElement = new FormElement(document);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
jest.clearAllMocks();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('constructor', () => {
|
|
36
|
+
it('throws an error if document element isn not passed in', () => {
|
|
37
|
+
expect(() => {
|
|
38
|
+
new FormElement();
|
|
39
|
+
}).toThrow();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('throws an error if form element does not exist on the page', () => {
|
|
43
|
+
expect(() => {
|
|
44
|
+
document.querySelector = () => {};
|
|
45
|
+
new FormElement(document);
|
|
46
|
+
}).toThrow();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('hide', () => {
|
|
51
|
+
it('adds the ncf__hidden class', () => {
|
|
52
|
+
formElement.hide();
|
|
53
|
+
|
|
54
|
+
expect(addStub).toHaveBeenCalledWith('ncf__hidden');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('show', () => {
|
|
59
|
+
it('removes the ncf__hidden class', () => {
|
|
60
|
+
formElement.show();
|
|
61
|
+
|
|
62
|
+
expect(removeStub).toHaveBeenCalledWith('ncf__hidden');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('value', () => {
|
|
67
|
+
it('returns the value', () => {
|
|
68
|
+
expect(formElement.value()).toEqual('test');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const Loader = require('./loader');
|
|
2
|
+
|
|
3
|
+
global.document = {};
|
|
4
|
+
|
|
5
|
+
describe('Loader', () => {
|
|
6
|
+
let loader;
|
|
7
|
+
let documentStub;
|
|
8
|
+
let elementStub;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
elementStub = {
|
|
12
|
+
classList: {
|
|
13
|
+
add: jest.fn(),
|
|
14
|
+
remove: jest.fn(),
|
|
15
|
+
},
|
|
16
|
+
focus: jest.fn(),
|
|
17
|
+
insertBefore: jest.fn(),
|
|
18
|
+
removeAttribute: jest.fn(),
|
|
19
|
+
};
|
|
20
|
+
documentStub = {
|
|
21
|
+
addEventListener: jest.fn(),
|
|
22
|
+
querySelector: jest.fn(),
|
|
23
|
+
removeEventListener: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
global.document.createElement = jest.fn().mockReturnValue(elementStub);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('constructor', () => {
|
|
33
|
+
it('throws an error if nothing passed', () => {
|
|
34
|
+
expect(() => {
|
|
35
|
+
new Loader();
|
|
36
|
+
}).toThrow();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('throws an error if loader not present', () => {
|
|
40
|
+
expect(() => {
|
|
41
|
+
documentStub.querySelector.mockReturnValue(false);
|
|
42
|
+
new Loader(documentStub);
|
|
43
|
+
}).toThrow();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('constructed', () => {
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
documentStub.querySelector.mockReturnValue(elementStub);
|
|
50
|
+
loader = new Loader(documentStub);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('clearContent', () => {
|
|
54
|
+
it('cleares the content of the partial', () => {
|
|
55
|
+
loader.setContent('<div>Baz</div>');
|
|
56
|
+
loader.clearContent();
|
|
57
|
+
expect(elementStub.innerHTML).toEqual('');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('setContent', () => {
|
|
62
|
+
it('creates the title element if it does not exist yet', () => {
|
|
63
|
+
loader.$loaderContentTitle = null;
|
|
64
|
+
loader.setContent({ title: 'Hooray!' });
|
|
65
|
+
expect(elementStub.insertBefore).toHaveBeenCalledWith(
|
|
66
|
+
elementStub,
|
|
67
|
+
expect.anything()
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
it('sets the title of the partial', () => {
|
|
71
|
+
loader.setContent({ title: 'Hooray!' });
|
|
72
|
+
expect(elementStub.innerHTML).toEqual('Hooray!');
|
|
73
|
+
});
|
|
74
|
+
it('sets the content of the partial', () => {
|
|
75
|
+
loader.setContent({ content: '<div>Baz</div>' });
|
|
76
|
+
expect(elementStub.innerHTML).toEqual('<div>Baz</div>');
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('show', () => {
|
|
81
|
+
it('shows the loader', () => {
|
|
82
|
+
loader.show();
|
|
83
|
+
expect(elementStub.classList.add).toHaveBeenCalledWith(
|
|
84
|
+
loader.VISIBLE_CLASS
|
|
85
|
+
);
|
|
86
|
+
expect(elementStub.classList.remove).toHaveBeenCalledWith(
|
|
87
|
+
loader.HIDDEN_CLASS
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
it('calls setContent if content is passed', () => {
|
|
91
|
+
const content = { title: 'foo' };
|
|
92
|
+
jest.spyOn(loader, 'setContent');
|
|
93
|
+
|
|
94
|
+
loader.show(content);
|
|
95
|
+
expect(loader.setContent).toHaveBeenCalledWith(content);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('hide', () => {
|
|
100
|
+
it('hides the loader', () => {
|
|
101
|
+
loader.hide();
|
|
102
|
+
expect(elementStub.classList.add).toHaveBeenCalledWith(
|
|
103
|
+
loader.HIDDEN_CLASS
|
|
104
|
+
);
|
|
105
|
+
expect(elementStub.classList.remove).toHaveBeenCalledWith(
|
|
106
|
+
loader.VISIBLE_CLASS
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('a11y', () => {
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
documentStub.querySelector.mockReturnValue(elementStub);
|
|
115
|
+
loader = new Loader(documentStub);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('show', () => {
|
|
119
|
+
it('gives the loader the focus', () => {
|
|
120
|
+
loader.show();
|
|
121
|
+
|
|
122
|
+
expect(elementStub.tabIndex).toBe(1);
|
|
123
|
+
expect(elementStub.focus).toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('showAndPreventTabbing', () => {
|
|
128
|
+
it('intercepts tab keypresses to prevent tabbing to content underneath', () => {
|
|
129
|
+
loader.showAndPreventTabbing();
|
|
130
|
+
expect(documentStub.addEventListener).toHaveBeenCalledWith(
|
|
131
|
+
'keydown',
|
|
132
|
+
expect.objectContaining({ name: 'interceptTab' })
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('hide', () => {
|
|
138
|
+
it('removes focus from the loader', () => {
|
|
139
|
+
loader.hide();
|
|
140
|
+
|
|
141
|
+
expect(elementStub.removeAttribute).toHaveBeenCalledWith('tabindex');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('stops intercepting tab keypresses', () => {
|
|
145
|
+
loader.hide();
|
|
146
|
+
|
|
147
|
+
expect(documentStub.removeEventListener).toHaveBeenCalledWith(
|
|
148
|
+
'keydown',
|
|
149
|
+
expect.objectContaining({ name: 'interceptTab' })
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('returns focus to a previously focused element', () => {
|
|
154
|
+
loader.showAndPreventTabbing();
|
|
155
|
+
loader.hide();
|
|
156
|
+
|
|
157
|
+
expect(elementStub.focus).toHaveBeenCalled();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const Password = require('./password');
|
|
2
|
+
|
|
3
|
+
describe('Password', () => {
|
|
4
|
+
let password;
|
|
5
|
+
let document;
|
|
6
|
+
let passwordElement;
|
|
7
|
+
let checkboxElement;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
passwordElement = { type: '' };
|
|
11
|
+
checkboxElement = { addEventListener: () => {}, checked: false };
|
|
12
|
+
document = {
|
|
13
|
+
querySelector: (selector) => {
|
|
14
|
+
if (selector.indexOf('#password') !== -1) {
|
|
15
|
+
return passwordElement;
|
|
16
|
+
} else {
|
|
17
|
+
return checkboxElement;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
password = new Password(document);
|
|
22
|
+
jest.spyOn(password, 'toggleMask');
|
|
23
|
+
jest.spyOn(checkboxElement, 'addEventListener');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
jest.clearAllMocks();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('constructor', () => {
|
|
31
|
+
it('throws an error if document element is not passed in.', () => {
|
|
32
|
+
expect(() => {
|
|
33
|
+
new Password();
|
|
34
|
+
}).toThrow();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('throws an error if password element does not exist on the page', () => {
|
|
38
|
+
expect(() => {
|
|
39
|
+
document.querySelector = () => {};
|
|
40
|
+
new Password(document);
|
|
41
|
+
}).toThrow();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('registerMaskCheckbox', () => {
|
|
46
|
+
it('adds event listener to checkbox if it exists', () => {
|
|
47
|
+
new Password(document);
|
|
48
|
+
expect(checkboxElement.addEventListener).toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('toggleMask', () => {
|
|
53
|
+
it('sets the input type to text', () => {
|
|
54
|
+
passwordElement.type = 'password';
|
|
55
|
+
password.toggleMask(false);
|
|
56
|
+
expect(passwordElement.type).toEqual('text');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('sets the input type to password', () => {
|
|
60
|
+
passwordElement.type = 'text';
|
|
61
|
+
password.toggleMask(true);
|
|
62
|
+
expect(passwordElement.type).toEqual('password');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
const PaymentTerm = require('./payment-term');
|
|
2
|
+
|
|
3
|
+
describe('PaymentTerm', () => {
|
|
4
|
+
let paymentTerm;
|
|
5
|
+
let documentStub;
|
|
6
|
+
let elementStub;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
elementStub = {
|
|
10
|
+
querySelector: jest.fn(),
|
|
11
|
+
querySelectorAll: jest.fn(),
|
|
12
|
+
getAttribute: jest.fn(),
|
|
13
|
+
setAttribute: jest.fn(),
|
|
14
|
+
cloneNode: jest.fn(),
|
|
15
|
+
remove: jest.fn(),
|
|
16
|
+
insertBefore: jest.fn(),
|
|
17
|
+
parentElement: elementStub,
|
|
18
|
+
addEventListener: jest.fn(),
|
|
19
|
+
value: 'test',
|
|
20
|
+
dataset: {
|
|
21
|
+
baseAmount: 100,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
documentStub = {
|
|
25
|
+
querySelector: jest.fn(),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('constructor', () => {
|
|
34
|
+
it('throws an error if nothing passed', () => {
|
|
35
|
+
expect(() => {
|
|
36
|
+
new PaymentTerm();
|
|
37
|
+
}).toThrow();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('throws an error if field not present', () => {
|
|
41
|
+
expect(() => {
|
|
42
|
+
documentStub.querySelector.mockReturnValue(false);
|
|
43
|
+
new PaymentTerm(documentStub);
|
|
44
|
+
}).toThrow();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('constructed', () => {
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
documentStub.querySelector.mockReturnValue(elementStub);
|
|
51
|
+
paymentTerm = new PaymentTerm(documentStub);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('getSelected', () => {
|
|
55
|
+
it('throws an error if nothing selected', () => {
|
|
56
|
+
elementStub.querySelector.mockReturnValue(false);
|
|
57
|
+
expect(() => {
|
|
58
|
+
paymentTerm.getSelected();
|
|
59
|
+
}).toThrow();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns the value of the selected term', () => {
|
|
63
|
+
elementStub.querySelector.mockReturnValue(elementStub);
|
|
64
|
+
paymentTerm.getSelected();
|
|
65
|
+
expect(elementStub.getAttribute).toHaveBeenCalledWith('value');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('onChange', () => {
|
|
70
|
+
it('adds an event listener on change', () => {
|
|
71
|
+
paymentTerm.onChange();
|
|
72
|
+
expect(elementStub.addEventListener).toHaveBeenCalledWith(
|
|
73
|
+
'change',
|
|
74
|
+
expect.anything()
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('calls the callback', () => {
|
|
79
|
+
const callback = jest.fn();
|
|
80
|
+
elementStub.addEventListener = (type, callback) => callback();
|
|
81
|
+
paymentTerm.onChange(callback);
|
|
82
|
+
expect(callback).toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('updateOptions', () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
paymentTerm.getSelected = jest.fn().mockReturnValue(true);
|
|
89
|
+
elementStub.querySelector.mockReturnValue(elementStub);
|
|
90
|
+
elementStub.cloneNode.mockReturnValue(elementStub);
|
|
91
|
+
elementStub.querySelectorAll.mockReturnValue([elementStub]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('throws an error if not all terms have an update', () => {
|
|
95
|
+
expect(() => {
|
|
96
|
+
paymentTerm.updateOptions([]);
|
|
97
|
+
}).toThrow();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('replaces the price with the correct updated price', () => {
|
|
101
|
+
const priceStub = {};
|
|
102
|
+
elementStub.querySelector.mockImplementation((elementId) => {
|
|
103
|
+
return elementId === '.ncf__payment-term__price'
|
|
104
|
+
? priceStub
|
|
105
|
+
: elementStub;
|
|
106
|
+
});
|
|
107
|
+
paymentTerm.updateOptions([
|
|
108
|
+
{
|
|
109
|
+
value: 'test',
|
|
110
|
+
price: '£1.01',
|
|
111
|
+
},
|
|
112
|
+
]);
|
|
113
|
+
expect(priceStub.innerHTML).toEqual('£1.01');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('replaces the trial price with the correct updated trial price', () => {
|
|
117
|
+
const trialPriceStub = {};
|
|
118
|
+
elementStub.querySelector.mockImplementation((elementId) => {
|
|
119
|
+
return elementId === '.ncf__payment-term__trial-price'
|
|
120
|
+
? trialPriceStub
|
|
121
|
+
: elementStub;
|
|
122
|
+
});
|
|
123
|
+
paymentTerm.updateOptions([
|
|
124
|
+
{
|
|
125
|
+
value: 'test',
|
|
126
|
+
trialPrice: '£1.01',
|
|
127
|
+
},
|
|
128
|
+
]);
|
|
129
|
+
expect(trialPriceStub.innerHTML).toEqual('£1.01');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('replaces the monthly price with the correct updated monthly price', () => {
|
|
133
|
+
const monthlyPriceStub = {};
|
|
134
|
+
elementStub.querySelector.mockImplementation((elementId) => {
|
|
135
|
+
return elementId === '.ncf__payment-term__monthly-price'
|
|
136
|
+
? monthlyPriceStub
|
|
137
|
+
: elementStub;
|
|
138
|
+
});
|
|
139
|
+
paymentTerm.updateOptions([
|
|
140
|
+
{
|
|
141
|
+
value: 'test',
|
|
142
|
+
monthlyPrice: '£1.01',
|
|
143
|
+
},
|
|
144
|
+
]);
|
|
145
|
+
expect(monthlyPriceStub.innerHTML).toEqual('£1.01');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('updating base amount', () => {
|
|
149
|
+
const updatedOptions = [
|
|
150
|
+
{
|
|
151
|
+
value: 'test',
|
|
152
|
+
monthlyPrice: '£1.01',
|
|
153
|
+
amount: 500,
|
|
154
|
+
trialAmount: 1,
|
|
155
|
+
},
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
beforeEach(() => {
|
|
159
|
+
elementStub.querySelector.mockReturnValue(elementStub);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('replaces the base amount with the correct updated trial amount', () => {
|
|
163
|
+
updatedOptions[0].isTrial = true;
|
|
164
|
+
paymentTerm.updateOptions(updatedOptions);
|
|
165
|
+
expect(elementStub.setAttribute).toHaveBeenCalledWith(
|
|
166
|
+
'data-base-amount',
|
|
167
|
+
1
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('replaces the base amount with the correct updated amount', () => {
|
|
172
|
+
updatedOptions[0].isTrial = false;
|
|
173
|
+
paymentTerm.updateOptions(updatedOptions);
|
|
174
|
+
expect(elementStub.setAttribute).toHaveBeenCalledWith(
|
|
175
|
+
'data-base-amount',
|
|
176
|
+
500
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('getBaseAmount', () => {
|
|
182
|
+
it('throws an error if nothing selected', () => {
|
|
183
|
+
elementStub.querySelector.mockReturnValue(false);
|
|
184
|
+
expect(() => {
|
|
185
|
+
paymentTerm.getBaseAmount();
|
|
186
|
+
}).toThrow();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('returns base amount of the selected term', () => {
|
|
190
|
+
elementStub.dataset.baseAmount = 99;
|
|
191
|
+
elementStub.querySelector.mockReturnValue(elementStub);
|
|
192
|
+
const returnedAmount = paymentTerm.getBaseAmount();
|
|
193
|
+
expect(returnedAmount).toBe(99);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|