diff --git a/lib/smartcar-error.js b/lib/smartcar-error.js index 45a96d8..6ce82c5 100644 --- a/lib/smartcar-error.js +++ b/lib/smartcar-error.js @@ -37,6 +37,10 @@ class SmartcarError extends Error { super(`${body.type}:${body.code} - ${body.description}`); } + if (headers['retry-after']) { + this.retryAfter = headers['retry-after']; + } + this.statusCode = status; this.requestId = body.requestId || headers['sc-request-id']; if (typeof body.resolution === 'string') { diff --git a/test/end-to-end/helpers/index.js b/test/end-to-end/helpers/index.js index 83914f6..ca8e9a8 100644 --- a/test/end-to-end/helpers/index.js +++ b/test/end-to-end/helpers/index.js @@ -78,19 +78,33 @@ helpers.runAuthFlow = async function( .build(); await driver.get(authUrl); + // Preamble - await driver.findElement(By.css('button#continue-button')).click(); + const continueButton = await driver.wait( + until.elementLocated( + By.css('button#continue-button'), + ), + ); + await continueButton.click(); // Brand Selector - await driver - .findElement(By.css(`button.brand-selector-button[data-make="${brand}"]`)) - .click(); + const brandButton = await driver.wait( + until.elementLocated( + By.css(`button#${brand.toUpperCase()}.brand-list-item`), + ), + ); + brandButton.click(); // Login + const signInButton = await driver.wait( + until.elementLocated( + By.id('sign-in-button'), + ), + ); email = email || `${uuid()}@email.com`; await driver.findElement(By.css('input[id=username]')).sendKeys(email); await driver.findElement(By.css('input[id=password')).sendKeys('password'); - await driver.findElement(By.css('button[id=sign-in-button]')).click(); + await signInButton.click(); // Permissions await driver.sleep(5000); diff --git a/test/unit/lib/vehicle.js b/test/unit/lib/vehicle.js index 6600463..baf286b 100644 --- a/test/unit/lib/vehicle.js +++ b/test/unit/lib/vehicle.js @@ -296,3 +296,16 @@ test('request - override non-sc headers', async function(t) { t.is(response.body.distance, 10); t.is(response.meta.requestId, 'requestId'); }); + +test('request - rate limit ', async function(t) { + const retryAfter = new Date().valueOf(); + t.context.n = nock( + `https://api.smartcar.com/v${vehicle.version}/vehicles/${VID}`, + ) + .matchHeader('Authorization', `Bearer ${TOKEN}`) + .get('/odometer') + .reply(429, {error: 'RATE_LIMIT'}, {'retry-after': retryAfter}); + + const error = await t.throwsAsync(vehicle.odometer()); + t.is(error.retryAfter, String(retryAfter)); +});