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

[CI-3342] Pass section to getRecommendationPods #197

Merged
merged 7 commits into from
Apr 25, 2024
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
28 changes: 28 additions & 0 deletions spec/src/modules/recommendations.js
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,34 @@ describe('ConstructorIO - Recommendations', () => {
});
});

it('Should build requestURL with query params when parameters are passed', (done) => {
const { recommendations } = new ConstructorIO({
...validOptions,
fetch: async (reqUrl) => ({ ok: true, json: async () => reqUrl }),
Copy link
Contributor

@stanlp1 stanlp1 Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on not overriding fetch here, actually sending a request?

While this is arguably better, closer to what a unit test should be, the rest of the tests all send requests, so I'm wondering if we should stick with that.

But tbh, doens't matter too much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this specific case I'm just trying to test that the request url gets built correctly, and not as concerned with the response. I can add an extra test that sends the request with these parameters for coverage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both approaches are fine but let's test the live request like Stanley mentioned. We can either

  1. Not override fetch and check both the request url and response in this test
  2. Leave this test as is and create a new test that's using actual fetch and hitting the API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the test 👍. I think it's good to have both just to make sure the parameter is getting added to the url as expected, at least while we have this hacky workaround with parameters/network parameters

});

recommendations.getRecommendationPods({ section: 'test-section' }).then((res) => {
expect(res).to.contain('section=test-section');

done();
});
});

it('Should successfully send request when parameters are passed', (done) => {
const { recommendations } = new ConstructorIO({
...validOptions,
fetch: fetchSpy,
});

recommendations.getRecommendationPods({ section: 'Products' }).then((res) => {
expect(res).to.be.an('object');
expect(res).to.have.property('pods');
expect(res).to.have.property('total_count');

done();
});
});

it('Should pass the correct custom headers passed in global networkParameters', (done) => {
const { recommendations } = new ConstructorIO({
...validOptions,
Expand Down
2 changes: 0 additions & 2 deletions src/modules/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,6 @@ class Catalog {
return fetch(requestUrl, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
...helpers.createAuthHeader(this.options),
},
signal,
Expand Down Expand Up @@ -1485,7 +1484,6 @@ class Catalog {
return fetch(requestUrl, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
VincentGalloro marked this conversation as resolved.
Show resolved Hide resolved
...helpers.createAuthHeader(this.options),
},
signal,
Expand Down
31 changes: 27 additions & 4 deletions src/modules/recommendations.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,15 @@ class Recommendations {
* Get all recommendation pods
*
* @function getRecommendationPods
* @param {object} [parameters] - Parameters relevant to the network request
* @param {string} [parameters.section] - Recommendations section
* @param {object} [networkParameters] - Parameters relevant to the network request
* @param {number} [networkParameters.timeout] - Request timeout (in milliseconds)
* @returns {Promise}
* @example
* constructorio.recommendations.getRecommendationPods();
*/
getRecommendationPods(networkParameters = {}) {
getRecommendationPods(parameters = {}, networkParameters = {}) {
const {
apiKey,
serviceUrl,
Expand All @@ -214,17 +216,38 @@ class Recommendations {
const controller = new AbortController();
const { signal } = controller;
const headers = {};
const requestUrl = `${serviceUrl}/v1/recommendation_pods?key=${apiKey}`;
const url = `${serviceUrl}/v1/recommendation_pods`;

Object.assign(headers, helpers.combineCustomHeaders(this.options, networkParameters));
// For backwards compatibility we allow only "networkParameters" to be passed, meaning "parameters" should be
// copied to networkParameters. If both parameters and networkParameters are passed we leave them as is
let parsedNetworkParameters = networkParameters;
if (parameters.timeout || parameters.headers) {
parsedNetworkParameters = parameters;
}

const { section } = parameters;

let queryParams = {
key: apiKey,
};

if (section) {
queryParams.section = section;
}

Object.assign(headers, helpers.combineCustomHeaders(this.options, parsedNetworkParameters));

// Append security token as 'x-cnstrc-token' if available
if (this.options.securityToken && typeof this.options.securityToken === 'string') {
headers['x-cnstrc-token'] = this.options.securityToken;
}

// Handle network timeout if specified
helpers.applyNetworkTimeout(this.options, networkParameters, controller);
helpers.applyNetworkTimeout(this.options, parsedNetworkParameters, controller);

queryParams = helpers.cleanParams(queryParams);
const queryString = qs.stringify(queryParams, { indices: false });
const requestUrl = `${url}?${queryString}`;

return fetch(requestUrl, { headers: { ...headers, ...helpers.createAuthHeader(this.options) }, signal })
.then((response) => {
Expand Down
Loading