Skip to content
Open
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
103 changes: 34 additions & 69 deletions spec/src/modules/tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2663,14 +2663,14 @@ describe(`ConstructorIO - Tracker${bundledDescriptionSuffix}`, () => {
});
}

it('Should limit number of customer_ids to 100 when using item_ids', (done) => {
it('Should send all items when more than 100 items are provided', (done) => {
const { tracker } = new ConstructorIO({
apiKey: testApiKey,
fetch: fetchSpy,
...requestQueueOptions,
});
const itemIDs = [...Array(1000).keys()];
const formattedItems = itemIDs.slice(0, 100).map((i) => ({ item_id: String(i) }));
const itemIDs = [...Array(150).keys()];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The array size of 150 works, but it is arbitrary and does not document why 150 was chosen (it is just "greater than 100"). Consider using a named constant or at least a comment like // deliberately over the old 100-item cap to make the intent obvious to future readers, especially since the old tests used 1000 which made the intent equally clear.

const formattedItems = itemIDs.map((i) => ({ item_id: String(i) }));
const parameters = {
...requiredParameters,
item_ids: itemIDs,
Expand All @@ -2681,39 +2681,8 @@ describe(`ConstructorIO - Tracker${bundledDescriptionSuffix}`, () => {

// Request
expect(fetchSpy).to.have.been.called;
expect(bodyParams).to.have.property('result_count').to.equal(parameters.numResults);
expect(bodyParams).to.have.property('items').to.deep.equal(formattedItems);

// Response
expect(responseParams).to.have.property('method').to.equal('POST');
expect(responseParams).to.have.property('message').to.equal('ok');

done();
});

expect(tracker.trackSearchResultsLoaded(term, parameters)).to.equal(true);
});

it('Should limit number of customer_ids to 100 when using customer_ids', (done) => {
const { tracker } = new ConstructorIO({
apiKey: testApiKey,
fetch: fetchSpy,
...requestQueueOptions,
});
const customerIDs = [...Array(1000).keys()];
const formattedItems = customerIDs.slice(0, 100).map((i) => ({ item_id: String(i) }));
const parameters = {
...requiredParameters,
item_ids: customerIDs,
};

tracker.on('success', (responseParams) => {
const bodyParams = helpers.extractBodyParamsFromFetch(fetchSpy);

// Request
expect(fetchSpy).to.have.been.called;
expect(bodyParams).to.have.property('result_count').to.equal(parameters.numResults);
expect(bodyParams).to.have.property('items').to.deep.equal(formattedItems);
expect(bodyParams.items).to.have.lengthOf(150);

// Response
expect(responseParams).to.have.property('method').to.equal('POST');
Expand Down Expand Up @@ -6095,6 +6064,36 @@ describe(`ConstructorIO - Tracker${bundledDescriptionSuffix}`, () => {
expect(tracker.trackBrowseResultsLoaded(Object.assign(requiredParameters, optionalParameters))).to.equal(true);
});

it('Should send all items when more than 100 items are provided', (done) => {
const { tracker } = new ConstructorIO({
apiKey: testApiKey,
fetch: fetchSpy,
...requestQueueOptions,
});
const items = [...Array(150).keys()].map((i) => ({ item_id: i.toString() }));
const parameters = {
...requiredParameters,
items,
};

tracker.on('success', (responseParams) => {
const requestParams = helpers.extractBodyParamsFromFetch(fetchSpy);

// Request
expect(fetchSpy).to.have.been.called;
expect(requestParams).to.have.property('items').to.deep.equal(items);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: In the new trackBrowseResultsLoaded test, items is constructed as objects with item_id keys (already snake_case), and the assertion checks deep.equal(items). This works coincidentally because helpers.toSnakeCaseKeys is a no-op on already-snake_case keys. The assertion does not exercise the camelCase→snake_case transformation path. This is a minor coverage gap — not a blocker, but worth noting since the previous deleted test (which used optionalParameters) did cover more of the function's behaviour (section, result_count, result_page, etc.).

expect(requestParams.items).to.have.lengthOf(150);

// Response
expect(responseParams).to.have.property('method').to.equal('POST');
expect(responseParams).to.have.property('message');

done();
});

expect(tracker.trackBrowseResultsLoaded(parameters)).to.equal(true);
});

it('Should throw an error when invalid parameters are provided', () => {
const { tracker } = new ConstructorIO({ apiKey: testApiKey });

Expand Down Expand Up @@ -6190,40 +6189,6 @@ describe(`ConstructorIO - Tracker${bundledDescriptionSuffix}`, () => {
});
}

it('Should limit number of items to 100', (done) => {
const { tracker } = new ConstructorIO({
apiKey: testApiKey,
fetch: fetchSpy,
...requestQueueOptions,
});
const parameters = {
...optionalParameters,
resultCount: 1000,
items: [...Array(1000).keys()].map((e) => ({ item_id: e.toString() })),
};

tracker.on('success', (responseParams) => {
const requestParams = helpers.extractBodyParamsFromFetch(fetchSpy);

// Request
expect(fetchSpy).to.have.been.called;
expect(requestParams).to.have.property('section').to.equal(parameters.section);
expect(requestParams).to.have.property('result_count').to.equal(parameters.resultCount);
expect(requestParams).to.have.property('result_page').to.equal(parameters.resultPage);
expect(requestParams).to.have.property('result_id').to.equal(parameters.resultId);
expect(requestParams).to.have.property('selected_filters').to.deep.equal(parameters.selectedFilters);
expect(requestParams).to.have.property('items').to.deep.equal(parameters.items.slice(0, 100));

// Response
expect(responseParams).to.have.property('method').to.equal('POST');
expect(responseParams).to.have.property('message');

done();
});

expect(tracker.trackBrowseResultsLoaded(Object.assign(requiredParameters, parameters))).to.equal(true);
});

it('Should not encode body parameters', (done) => {
const specialCharacters = '+[]&';
const userId = `user-id ${specialCharacters}`;
Expand Down
8 changes: 3 additions & 5 deletions src/modules/tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -733,12 +733,10 @@ class Tracker {
let transformedItems;

if (items && Array.isArray(items) && items.length !== 0) {
const trimmedItems = items.slice(0, 100);

if (typeof items[0] === 'string' || typeof items[0] === 'number') {
transformedItems = trimmedItems.map((itemId) => ({ item_id: String(itemId) }));
transformedItems = items.map((itemId) => ({ item_id: String(itemId) }));
} else {
transformedItems = trimmedItems.map((item) => helpers.toSnakeCaseKeys(item, false));
transformedItems = items.map((item) => helpers.toSnakeCaseKeys(item, false));
}
}

Expand Down Expand Up @@ -1748,7 +1746,7 @@ class Tracker {
}

if (items && Array.isArray(items)) {
bodyParams.items = items.slice(0, 100).map((item) => helpers.toSnakeCaseKeys(item, false));
bodyParams.items = items.map((item) => helpers.toSnakeCaseKeys(item, false));
}

if (analyticsTags) {
Expand Down
Loading