From 68857902afe8b8a64cee80a6d6fc3dbc695857e5 Mon Sep 17 00:00:00 2001 From: vishnu Date: Thu, 25 Sep 2025 10:03:48 +0530 Subject: [PATCH 1/5] add new api --- spec/src/modules/quizzes.js | 98 +++++++++++++++++++++++++++++++++++++ src/modules/quizzes.js | 45 +++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/spec/src/modules/quizzes.js b/spec/src/modules/quizzes.js index fb0ea02f..7e1c0c00 100644 --- a/spec/src/modules/quizzes.js +++ b/spec/src/modules/quizzes.js @@ -49,6 +49,104 @@ describe(`ConstructorIO - Quizzes${bundledDescriptionSuffix}`, () => { fetchSpy = null; }); + describe('getQuizAllQuestions', () => { + it('Should return a result provided a valid apiKey and quizId', () => { + const { quizzes } = new ConstructorIO({ + apiKey: quizApiKey, + fetch: fetchSpy, + }); + + return quizzes.getQuizAllQuestions(validQuizId).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(res).to.have.property('quiz_version_id').to.be.an('string'); + expect(res).to.have.property('questions').to.be.an('array'); + expect(res.questions[0].id).to.equal(1); + expect(res.total_questions).to.equal(1); + expect(fetchSpy).to.have.been.called; + expect(requestedUrlParams).to.have.property('key'); + expect(requestedUrlParams).to.have.property('i'); + expect(requestedUrlParams).to.have.property('s'); + expect(requestedUrlParams).to.have.property('c').to.equal(clientVersion); + expect(requestedUrlParams).to.have.property('_dt'); + }); + }); + + it('Should return a result provided a valid apiKey, quizId and section', () => { + const section = 'Products'; + const { quizzes } = new ConstructorIO({ + apiKey: quizApiKey, + fetch: fetchSpy, + }); + + return quizzes.getQuizAllQuestions(validQuizId, { section }).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(res).to.have.property('quiz_version_id').to.be.an('string'); + expect(res).to.have.property('questions').to.be.an('array'); + expect(fetchSpy).to.have.been.called; + expect(requestedUrlParams).to.have.property('section').to.equal(section); + }); + }); + + it('Should return a result provided a valid apiKey, quizId and quizVersionId', () => { + const { quizzes } = new ConstructorIO({ + apiKey: quizApiKey, + fetch: fetchSpy, + }); + + return quizzes.getQuizAllQuestions(validQuizId).then((initialResponse) => { + const quizVersionId = initialResponse.quiz_version_id; + + return quizzes.getQuizAllQuestions(validQuizId, { quizVersionId }).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(res).to.have.property('questions').to.be.an('array'); + expect(res).to.have.property('quiz_version_id').to.be.an('string').to.equal(quizVersionId); + expect(res.total_questions).to.equal(1); + expect(fetchSpy).to.have.been.called; + expect(requestedUrlParams).to.have.property('quiz_version_id').to.equal(quizVersionId); + }); + }); + }); + + it('Should error when fetching quiz questions with an invalid quizId', () => { + const { quizzes } = new ConstructorIO({ + apiKey: quizApiKey, + fetch: fetchSpy, + }); + + return expect(quizzes.getQuizAllQuestions('invalidQuizId')).to.eventually.be.rejected; + }); + + it('Should error when fetching quiz questions with no quizId', () => { + const { quizzes } = new ConstructorIO({ + apiKey: quizApiKey, + fetch: fetchSpy, + }); + + return expect(quizzes.getQuizAllQuestions(null)).to.eventually.be.rejected; + }); + + it('Should error when fetching quiz questions with an invalid apiKey', () => { + const { quizzes } = new ConstructorIO({ + apiKey: 'invalidKey', + fetch: fetchSpy, + }); + + return expect(quizzes.getQuizAllQuestions(validQuizId)).to.eventually.be.rejected; + }); + + it('Should be rejected if an invalid quizVersionId is provided', () => { + const { quizzes } = new ConstructorIO({ + apiKey: quizApiKey, + fetch: fetchSpy, + }); + + return expect(quizzes.getQuizAllQuestions(validQuizId, { quizVersionId: 'foo' })).to.eventually.be.rejected; + }); + }); + describe('getQuizNextQuestion', () => { it('Should return a result provided a valid apiKey and quizId', () => { const { quizzes } = new ConstructorIO({ diff --git a/src/modules/quizzes.js b/src/modules/quizzes.js index 51b88786..51c50b77 100644 --- a/src/modules/quizzes.js +++ b/src/modules/quizzes.js @@ -263,6 +263,51 @@ class Quizzes { throw new Error('getQuizResultsConfig response data is malformed'); }); } + + /** + * Retrieves configuration for the results page of a particular quiz + * + * @function getQuizAllQuestions + * @description Retrieve all questions for a particular quiz from Constructor.io API + * @param {string} quizId - The identifier of the quiz + * @param {string} parameters - Additional parameters + * @param {string} [parameters.section] - Product catalog section + * @param {string} [parameters.quizVersionId] - Version identifier for the quiz. Version ID will be returned with the first request and it should be passed with subsequent requests. More information can be found: https://docs.constructor.com/reference/configuration-quizzes + * @param {object} [networkParameters] - Parameters relevant to the network request + * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) + * @returns {Promise} + * @example + * constructorio.quizzes.getQuizResultsConfig('quizId', { + * quizVersionId: '123', + * }); + */ + getQuizAllQuestions(quizId, parameters, networkParameters = {}) { + let requestUrl; + const { fetch } = this.options; + const controller = new AbortController(); + const { signal } = controller; + + try { + requestUrl = createQuizUrl(quizId, parameters, this.options, 'all_questions'); + } catch (e) { + return Promise.reject(e); + } + + // Handle network timeout if specified + helpers.applyNetworkTimeout(this.options, networkParameters, controller); + + return fetch(requestUrl, { signal }) + .then(helpers.convertResponseToJson) + .then((json) => { + if (json.quiz_version_id) { + this.eventDispatcher.queue('quizzes.getQuizAllQuestions.completed', json); + + return json; + } + + throw new Error('getQuizAllQuestions response data is malformed'); + }); + } } module.exports = Quizzes; From 030ac96d0f75db90223da7487ab80667fa92a286 Mon Sep 17 00:00:00 2001 From: vishnu Date: Thu, 25 Sep 2025 10:58:16 +0530 Subject: [PATCH 2/5] fix --- src/modules/quizzes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/quizzes.js b/src/modules/quizzes.js index 51c50b77..0e33453a 100644 --- a/src/modules/quizzes.js +++ b/src/modules/quizzes.js @@ -277,7 +277,7 @@ class Quizzes { * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} * @example - * constructorio.quizzes.getQuizResultsConfig('quizId', { + * constructorio.quizzes.getQuizAllQuestions('quizId', { * quizVersionId: '123', * }); */ From bdd85014f5692fb88c7b87919e02e1cac9d951e8 Mon Sep 17 00:00:00 2001 From: Enes Kutay SEZEN Date: Thu, 25 Sep 2025 11:16:33 -0500 Subject: [PATCH 3/5] Update src/modules/quizzes.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/modules/quizzes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/quizzes.js b/src/modules/quizzes.js index 0e33453a..d8fda2de 100644 --- a/src/modules/quizzes.js +++ b/src/modules/quizzes.js @@ -265,7 +265,7 @@ class Quizzes { } /** - * Retrieves configuration for the results page of a particular quiz + * Retrieves all questions for a particular quiz * * @function getQuizAllQuestions * @description Retrieve all questions for a particular quiz from Constructor.io API From 22d68b01133453f1a0d5b1c2358a72966fccb3b6 Mon Sep 17 00:00:00 2001 From: vishnu Date: Sun, 28 Sep 2025 16:30:40 +0530 Subject: [PATCH 4/5] update type --- src/modules/quizzes.js | 2 +- src/types/quizzes.d.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/modules/quizzes.js b/src/modules/quizzes.js index 0e33453a..e3e0ed36 100644 --- a/src/modules/quizzes.js +++ b/src/modules/quizzes.js @@ -270,7 +270,7 @@ class Quizzes { * @function getQuizAllQuestions * @description Retrieve all questions for a particular quiz from Constructor.io API * @param {string} quizId - The identifier of the quiz - * @param {string} parameters - Additional parameters + * @param {object} parameters - Additional parameters * @param {string} [parameters.section] - Product catalog section * @param {string} [parameters.quizVersionId] - Version identifier for the quiz. Version ID will be returned with the first request and it should be passed with subsequent requests. More information can be found: https://docs.constructor.com/reference/configuration-quizzes * @param {object} [networkParameters] - Parameters relevant to the network request diff --git a/src/types/quizzes.d.ts b/src/types/quizzes.d.ts index fccb725c..98e546df 100644 --- a/src/types/quizzes.d.ts +++ b/src/types/quizzes.d.ts @@ -68,6 +68,14 @@ export interface NextQuestionResponse extends Record { total_questions: number; } +export interface AllQuestionsResponse extends Record { + questions: Question[]; + quiz_version_id?: string; + quiz_id?: string; + quiz_session_id?: string; + total_questions: number; +} + export interface QuizResultsResponse extends Record { request?: { filters?: Record; From 626e049fe4e573dc0cfde66ac580948b2179d44e Mon Sep 17 00:00:00 2001 From: vishnu Date: Tue, 30 Sep 2025 09:47:47 +0530 Subject: [PATCH 5/5] added documentation --- src/modules/quizzes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/quizzes.js b/src/modules/quizzes.js index 2b5d4f45..24e2f1d7 100644 --- a/src/modules/quizzes.js +++ b/src/modules/quizzes.js @@ -273,6 +273,7 @@ class Quizzes { * @param {object} parameters - Additional parameters * @param {string} [parameters.section] - Product catalog section * @param {string} [parameters.quizVersionId] - Version identifier for the quiz. Version ID will be returned with the first request and it should be passed with subsequent requests. More information can be found: https://docs.constructor.com/reference/configuration-quizzes + * @param {string} [parameters.quizSessionId] - Session identifier for the quiz. Session ID will be returned with the first request or with getQuizResultsConfig and it should be passed with subsequent requests. More information can be found: https://docs.constructor.com/reference/configuration-quizzes * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise}