Skip to content

Commit 39689da

Browse files
[NO-REF] - introduce pia http module
1 parent 31b056e commit 39689da

6 files changed

Lines changed: 529 additions & 1 deletion

File tree

spec/src/modules/pia.js

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
/* eslint-disable no-unused-expressions, import/no-unresolved */
2+
const dotenv = require('dotenv');
3+
const chai = require('chai');
4+
const chaiAsPromised = require('chai-as-promised');
5+
const sinon = require('sinon');
6+
const sinonChai = require('sinon-chai');
7+
const fs = require('fs');
8+
const helpers = require('../../mocha.helpers');
9+
const jsdom = require('../utils/jsdom-global');
10+
let ConstructorIO = require('../../../test/constructorio'); // eslint-disable-line import/extensions
11+
12+
chai.use(chaiAsPromised);
13+
chai.use(sinonChai);
14+
dotenv.config();
15+
16+
const piaApiKey = process.env.TEST_PIA_REQUEST_API_KEY;
17+
const clientVersion = 'cio-mocha';
18+
const bundled = process.env.BUNDLED === 'true';
19+
const skipNetworkTimeoutTests = process.env.SKIP_NETWORK_TIMEOUT_TESTS === 'true';
20+
const bundledDescriptionSuffix = bundled ? ' - Bundled' : '';
21+
22+
describe(`ConstructorIO - Pia${bundledDescriptionSuffix}`, () => {
23+
const validItemId = '149100215';
24+
const validQuestion = 'What material is this made of?';
25+
const jsdomOptions = { url: 'http://localhost' };
26+
let fetchSpy;
27+
let cleanup;
28+
29+
if (bundled) {
30+
jsdomOptions.src = fs.readFileSync(`./dist/constructorio-client-javascript-${process.env.PACKAGE_VERSION}.js`, 'utf-8');
31+
}
32+
33+
beforeEach(() => {
34+
cleanup = jsdom(jsdomOptions);
35+
global.CLIENT_VERSION = clientVersion;
36+
window.CLIENT_VERSION = clientVersion;
37+
fetchSpy = sinon.spy(fetch);
38+
39+
if (bundled) {
40+
ConstructorIO = window.ConstructorioClient;
41+
}
42+
});
43+
44+
afterEach(() => {
45+
delete global.CLIENT_VERSION;
46+
delete window.CLIENT_VERSION;
47+
cleanup();
48+
49+
fetchSpy = null;
50+
});
51+
52+
describe('getSuggestedQuestions', () => {
53+
it('Should return a result provided a valid apiKey and itemId', () => {
54+
const { pia } = new ConstructorIO({
55+
apiKey: piaApiKey,
56+
fetch: fetchSpy,
57+
});
58+
59+
return pia.getSuggestedQuestions(validItemId).then((res) => {
60+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
61+
62+
expect(res).to.have.property('questions').to.be.an('array');
63+
expect(res.questions.length).to.be.greaterThan(0);
64+
expect(res.questions[0]).to.have.property('value').to.be.a('string');
65+
expect(fetchSpy).to.have.been.called;
66+
expect(requestedUrlParams).to.have.property('key');
67+
expect(requestedUrlParams).to.have.property('i');
68+
expect(requestedUrlParams).to.have.property('s');
69+
expect(requestedUrlParams).to.have.property('c').to.equal(clientVersion);
70+
expect(requestedUrlParams).to.have.property('_dt');
71+
expect(requestedUrlParams).to.have.property('item_id').to.equal(validItemId);
72+
});
73+
});
74+
75+
it('Should return a result provided a valid apiKey, itemId and variationId', () => {
76+
const variationId = 'variation-123';
77+
const { pia } = new ConstructorIO({
78+
apiKey: piaApiKey,
79+
fetch: fetchSpy,
80+
});
81+
82+
return pia.getSuggestedQuestions(validItemId, { variationId }).then(() => {
83+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
84+
85+
expect(requestedUrlParams).to.have.property('variation_id').to.equal(variationId);
86+
});
87+
});
88+
89+
it('Should return a result provided a valid apiKey, itemId and numResults', () => {
90+
const numResults = 2;
91+
const { pia } = new ConstructorIO({
92+
apiKey: piaApiKey,
93+
fetch: fetchSpy,
94+
});
95+
96+
return pia.getSuggestedQuestions(validItemId, { numResults }).then((res) => {
97+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
98+
99+
expect(res).to.have.property('questions').to.be.an('array');
100+
expect(requestedUrlParams).to.have.property('num_results').to.equal(numResults.toString());
101+
});
102+
});
103+
104+
it('Should return a result provided a valid apiKey, itemId and user id', () => {
105+
const userId = 'user-id';
106+
const { pia } = new ConstructorIO({
107+
apiKey: piaApiKey,
108+
fetch: fetchSpy,
109+
userId,
110+
});
111+
112+
return pia.getSuggestedQuestions(validItemId).then(() => {
113+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
114+
115+
expect(requestedUrlParams).to.have.property('ui').to.equal(userId);
116+
});
117+
});
118+
119+
it('Should return a result provided a valid apiKey, itemId and segments', () => {
120+
const segments = ['foo', 'bar'];
121+
const { pia } = new ConstructorIO({
122+
apiKey: piaApiKey,
123+
fetch: fetchSpy,
124+
segments,
125+
});
126+
127+
return pia.getSuggestedQuestions(validItemId).then(() => {
128+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
129+
130+
expect(requestedUrlParams).to.have.property('us').to.deep.equal(segments);
131+
});
132+
});
133+
134+
it('Should be rejected if no itemId is provided', () => {
135+
const { pia } = new ConstructorIO({
136+
apiKey: piaApiKey,
137+
fetch: fetchSpy,
138+
});
139+
140+
return expect(pia.getSuggestedQuestions(null)).to.eventually.be.rejected;
141+
});
142+
143+
it('Should be rejected if an invalid apiKey is provided', () => {
144+
const { pia } = new ConstructorIO({
145+
apiKey: 'invalidKey',
146+
fetch: fetchSpy,
147+
});
148+
149+
return expect(pia.getSuggestedQuestions(validItemId)).to.eventually.be.rejected;
150+
});
151+
152+
if (!skipNetworkTimeoutTests) {
153+
it('Should be rejected when network request timeout is provided and reached', () => {
154+
const { pia } = new ConstructorIO({
155+
apiKey: piaApiKey,
156+
fetch: fetchSpy,
157+
});
158+
159+
return expect(pia.getSuggestedQuestions(validItemId, {}, { timeout: 20 })).to.eventually.be.rejectedWith('This operation was aborted');
160+
});
161+
162+
it('Should be rejected when global network request timeout is provided and reached', () => {
163+
const { pia } = new ConstructorIO({
164+
apiKey: piaApiKey,
165+
fetch: fetchSpy,
166+
networkParameters: { timeout: 20 },
167+
});
168+
169+
return expect(pia.getSuggestedQuestions(validItemId)).to.eventually.be.rejectedWith('This operation was aborted');
170+
});
171+
}
172+
});
173+
174+
describe('getAnswerResults', () => {
175+
it('Should return a result provided a valid apiKey, itemId and question', () => {
176+
const { pia } = new ConstructorIO({
177+
apiKey: piaApiKey,
178+
fetch: fetchSpy,
179+
});
180+
181+
return pia.getAnswerResults(validItemId, validQuestion).then((res) => {
182+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
183+
184+
expect(res).to.have.property('qna_result_id').to.be.a('string');
185+
expect(res).to.have.property('value').to.be.a('string');
186+
expect(fetchSpy).to.have.been.called;
187+
expect(requestedUrlParams).to.have.property('key');
188+
expect(requestedUrlParams).to.have.property('i');
189+
expect(requestedUrlParams).to.have.property('s');
190+
expect(requestedUrlParams).to.have.property('c').to.equal(clientVersion);
191+
expect(requestedUrlParams).to.have.property('_dt');
192+
expect(requestedUrlParams).to.have.property('item_id').to.equal(validItemId);
193+
});
194+
});
195+
196+
it('Should return a result provided a valid apiKey, itemId, question and variationId', () => {
197+
const variationId = 'variation-123';
198+
const { pia } = new ConstructorIO({
199+
apiKey: piaApiKey,
200+
fetch: fetchSpy,
201+
});
202+
203+
return pia.getAnswerResults(validItemId, validQuestion, { variationId }).then(() => {
204+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
205+
206+
expect(requestedUrlParams).to.have.property('variation_id').to.equal(variationId);
207+
});
208+
});
209+
210+
it('Should return a result provided a valid apiKey, itemId, question and user id', () => {
211+
const userId = 'user-id';
212+
const { pia } = new ConstructorIO({
213+
apiKey: piaApiKey,
214+
fetch: fetchSpy,
215+
userId,
216+
});
217+
218+
return pia.getAnswerResults(validItemId, validQuestion).then(() => {
219+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
220+
221+
expect(requestedUrlParams).to.have.property('ui').to.equal(userId);
222+
});
223+
});
224+
225+
it('Should return a result provided a valid apiKey, itemId, question and segments', () => {
226+
const segments = ['foo', 'bar'];
227+
const { pia } = new ConstructorIO({
228+
apiKey: piaApiKey,
229+
fetch: fetchSpy,
230+
segments,
231+
});
232+
233+
return pia.getAnswerResults(validItemId, validQuestion).then(() => {
234+
const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy);
235+
236+
expect(requestedUrlParams).to.have.property('us').to.deep.equal(segments);
237+
});
238+
});
239+
240+
it('Should be rejected if no itemId is provided', () => {
241+
const { pia } = new ConstructorIO({
242+
apiKey: piaApiKey,
243+
fetch: fetchSpy,
244+
});
245+
246+
return expect(pia.getAnswerResults(null, validQuestion)).to.eventually.be.rejected;
247+
});
248+
249+
it('Should be rejected if no question is provided', () => {
250+
const { pia } = new ConstructorIO({
251+
apiKey: piaApiKey,
252+
fetch: fetchSpy,
253+
});
254+
255+
return expect(pia.getAnswerResults(validItemId, null)).to.eventually.be.rejected;
256+
});
257+
258+
it('Should be rejected if an invalid apiKey is provided', () => {
259+
const { pia } = new ConstructorIO({
260+
apiKey: 'invalidKey',
261+
fetch: fetchSpy,
262+
});
263+
264+
return expect(pia.getAnswerResults(validItemId, validQuestion)).to.eventually.be.rejected;
265+
});
266+
267+
if (!skipNetworkTimeoutTests) {
268+
it('Should be rejected when network request timeout is provided and reached', () => {
269+
const { pia } = new ConstructorIO({
270+
apiKey: piaApiKey,
271+
fetch: fetchSpy,
272+
});
273+
274+
return expect(pia.getAnswerResults(validItemId, validQuestion, {}, { timeout: 20 })).to.eventually.be.rejectedWith('This operation was aborted');
275+
});
276+
277+
it('Should be rejected when global network request timeout is provided and reached', () => {
278+
const { pia } = new ConstructorIO({
279+
apiKey: piaApiKey,
280+
fetch: fetchSpy,
281+
networkParameters: { timeout: 20 },
282+
});
283+
284+
return expect(pia.getAnswerResults(validItemId, validQuestion)).to.eventually.be.rejectedWith('This operation was aborted');
285+
});
286+
}
287+
});
288+
});

src/constructorio.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const helpers = require('./utils/helpers');
1212
const { default: packageVersion } = require('./version');
1313
const Quizzes = require('./modules/quizzes');
1414
const Agent = require('./modules/agent');
15+
const Pia = require('./modules/pia');
1516
const Assistant = require('./modules/assistant');
1617

1718
// Compute package version string
@@ -65,6 +66,7 @@ class ConstructorIO {
6566
* @property {object} tracker - Interface to {@link module:tracker}
6667
* @property {object} quizzes - Interface to {@link module:quizzes}
6768
* @property {object} agent - Interface to {@link module:agent}
69+
* @property {object} pia - Interface to {@link module:pia}
6870
* @property {object} assistant - Interface to {@link module:assistant} @deprecated This property is deprecated and will be removed in a future version. Use the agent property instead.
6971
* @returns {class}
7072
*/
@@ -149,6 +151,7 @@ class ConstructorIO {
149151
this.tracker = new Tracker(this.options);
150152
this.quizzes = new Quizzes(this.options);
151153
this.agent = new Agent(this.options);
154+
this.pia = new Pia(this.options);
152155
this.assistant = new Assistant(this.options);
153156

154157
// Dispatch initialization event

0 commit comments

Comments
 (0)