diff --git a/spec/src/modules/tracker.js b/spec/src/modules/tracker.js index ec358ddb..314c2fda 100644 --- a/spec/src/modules/tracker.js +++ b/spec/src/modules/tracker.js @@ -8143,6 +8143,33 @@ describe('ConstructorIO - Tracker', () => { }); }); + it('Should receive an error message when rate limited (429)', (done) => { + // Create a mock response for 429 error + fetchSpy = sinon.spy(() => Promise.resolve({ + ok: false, + status: 429, + statusText: 'Too Many Requests', + headers: new Map([['content-type', 'text/plain']]), + text: () => Promise.resolve('Too many requests'), + })); + + const { tracker } = new ConstructorIO({ + apiKey: testApiKey, + fetch: fetchSpy, + }); + + tracker.trackInputFocus(userParameters); + + tracker.on('error', (response) => { + expect(response).to.have.property('url'); + expect(response).to.have.property('method'); + expect(response).to.have.property('message'); + expect(response.message).to.not.be.undefined; + expect(response.message).to.equal('Too many requests'); + done(); + }); + }); + it('Should receive an error message when making a request to an invalid endpoint', (done) => { const { tracker } = new ConstructorIO({ apiKey: testApiKey, diff --git a/src/modules/tracker.js b/src/modules/tracker.js index 19eef80d..7dc73486 100644 --- a/src/modules/tracker.js +++ b/src/modules/tracker.js @@ -139,6 +139,7 @@ function send(url, userParameters, networkParameters, method = 'GET', body = {}) if (request) { const instance = this; + const emitError = helpers.getEmitError(instance, { url, method }); request.then((response) => { // Request was successful, and returned a 2XX status code @@ -152,26 +153,25 @@ function send(url, userParameters, networkParameters, method = 'GET', body = {}) // Request was successful, but returned a non-2XX status code else { - response.json().then((json) => { - instance.eventemitter.emit('error', { - url, - method, - message: json && json.message, + const contentType = response.headers.get('Content-Type') || ''; + + if (contentType.includes('application/json')) { + response.json().then((json) => { + emitError(json && json.message); + }).catch((error) => { + emitError(error.type); }); - }).catch((error) => { - instance.eventemitter.emit('error', { - url, - method, - message: error.type, + } else { + // If not JSON, fallback to text + response.text().then((text) => { + emitError(text || 'Unknown error message'); + }).catch((error) => { + emitError(`Error reading text: ${error.message}`); }); - }); + } } }).catch((error) => { - instance.eventemitter.emit('error', { - url, - method, - message: error.toString(), - }); + emitError(error.toString()); }); } } diff --git a/src/utils/helpers.js b/src/utils/helpers.js index 7184f960..4428e06e 100644 --- a/src/utils/helpers.js +++ b/src/utils/helpers.js @@ -134,6 +134,12 @@ const utils = { return url; }, + + getEmitError(instance, { url, method }) { + return function emitError(message) { + instance.eventemitter.emit('error', { url, method, message }); + }; + }, }; module.exports = utils;