-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added circleCI pipeline * Added circleCI pipeline * Added the capture responses functionalities * Fixed npm vulnerabilities * Updated examples and docs * Removed double copyright header * 2.5.0 * CaptureResponse.js - Added check for null headers and null location in captureResponse constructor - Simplified location set in constructor captureResponse.spec.js - Added tests for constructor's conditions - Moved hardcoded values to variables (local and from responses.js) * - Fixed tests - Updated documentation - The capture job information are now fetched by appending the capture job ID to 'API_URL/capture/' - Added more tests for the capture job polling - renamed the capture job polling function - Applied linter * Fixed example with full possibility * Updated mock time to push `pollForTheCaptureToFinish` to its limit (it resolves just before the last try) * Updated version * Update test/helper/responses.js Co-authored-by: larizgoitia <iker@evrythng.com> Co-authored-by: larizgoitia <iker@evrythng.com>
- Loading branch information
1 parent
885e4c2
commit f528631
Showing
13 changed files
with
337 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
version: 2.1 | ||
jobs: | ||
build: | ||
docker: | ||
- image: node:14-alpine | ||
steps: | ||
- checkout | ||
- run: | ||
name: 'Install dependencies' | ||
command: 'npm ci' | ||
- run: | ||
name: 'Build SDK' | ||
command: 'npm run build' | ||
- run: | ||
name: 'Audit dependencies' | ||
command: 'npm audit' | ||
- run: | ||
name: 'Run tests' | ||
command: 'npm test' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/** | ||
* (c) Copyright Reserved EVRYTHNG Limited 2021. All rights reserved. | ||
* Use of this material is subject to license. | ||
* Copying and unauthorised use of this material strictly prohibited. | ||
*/ | ||
|
||
import request from '../../request/request'; | ||
import { timer } from '../../utils/utils'; | ||
|
||
export default class CaptureResponse { | ||
/** | ||
* You can only provide an already existing CaptureResponse | ||
* via Object | ||
* @param {Object} [captureResponse] - The object that will be used to create the epcisHeader | ||
* entity | ||
*/ | ||
constructor(captureResponse) { | ||
if (!captureResponse) { | ||
throw new Error('A capture response must be provided to the constructor'); | ||
} | ||
if (!captureResponse.headers) { | ||
throw new Error('A capture response must have headers'); | ||
} | ||
if (!captureResponse.headers.get('location')) { | ||
throw new Error('A capture response must have a location property in the headers'); | ||
} | ||
this.location = captureResponse.headers.get('location'); | ||
this.fetched = null; | ||
} | ||
|
||
/** | ||
* Getter for the location | ||
* @return {string} | ||
*/ | ||
getLocation() { | ||
return this.location; | ||
} | ||
|
||
/** | ||
* Getter for the running property | ||
* @return {boolean} | ||
*/ | ||
getRunningStatus() { | ||
if (!this.fetched) throw new Error('The capture job needs to be fetched to get the running status'); | ||
return this.running; | ||
} | ||
|
||
/** | ||
* Getter for the success property | ||
* @return {boolean} | ||
*/ | ||
getSuccessStatus() { | ||
if (!this.fetched) throw new Error('The capture job needs to be fetched to get the success status'); | ||
return this.success; | ||
} | ||
|
||
/** | ||
* Getter for the errors property | ||
* @return {Array<string>} | ||
*/ | ||
getErrors() { | ||
if (!this.fetched) throw new Error('The capture job needs to be fetched to get the errors'); | ||
return this.errors; | ||
} | ||
|
||
/** | ||
* Getter for the error file property | ||
* @return {Object} | ||
*/ | ||
getErrorFile() { | ||
if (!this.fetched) throw new Error('The capture job needs to be fetched to get the error file'); | ||
return this.errorFile; | ||
} | ||
|
||
async getCaptureJob(options = {}) { | ||
const captureId = this.location.split('/').pop(); | ||
const endpoint = `capture/${captureId}`; | ||
const res = await request(endpoint, options); | ||
const json = await res.json(); | ||
|
||
this.success = json.success; | ||
this.errors = json.errors; | ||
this.running = json.running; | ||
this.errorFile = json.errorFile; | ||
this.fetched = true; | ||
|
||
return json; | ||
} | ||
|
||
/** | ||
* Fetch the capture job information until the running field is equal to false. Stop trying after | ||
* [nbRetry] tries. | ||
* @param {number} nbRetry - how much time should it fetch the capture job until aborted | ||
* @param {number} delay - the delay between each call, in ms (2000 by default) | ||
* @param {Object} options - the request options | ||
* @returns {Promise<void>} | ||
*/ | ||
async pollForTheCaptureToFinish(nbRetry = 5, delay = 2000, options = {}) { | ||
let tries = 0; | ||
|
||
/* eslint-disable no-await-in-loop */ | ||
do { | ||
if (tries !== 0) { | ||
await timer(delay); | ||
} | ||
|
||
await this.getCaptureJob(options); | ||
tries += 1; | ||
} while (tries < nbRetry && this.running); | ||
/* eslint-enable no-await-in-loop */ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/** | ||
* (c) Copyright Reserved EVRYTHNG Limited 2021. All rights reserved. | ||
* Use of this material is subject to license. | ||
* Copying and unauthorised use of this material strictly prohibited. | ||
*/ | ||
|
||
import { expect } from 'chai'; | ||
import { CaptureResponse } from '../../src'; | ||
import * as sdk from '../../src'; | ||
import { | ||
mockCaptureJobIsFinished, mockCaptureJobIsNotFinished, prepare, tearDown, | ||
} from '../helper/apiMock'; | ||
import setup from '../../src/setup'; | ||
import settings from '../../src/settings'; | ||
import responses from '../helper/responses'; | ||
|
||
const initialSettings = { ...settings }; | ||
|
||
let req; | ||
|
||
const locationTestValue = 'capture/CAPTURE_JOB_ID'; | ||
const captureResponse = { headers: new Map() }; | ||
captureResponse.headers.set('location', locationTestValue); | ||
|
||
describe('Unit tests: Capture response', () => { | ||
beforeEach((done) => { | ||
prepare(); | ||
done(); | ||
}); | ||
|
||
afterEach((done) => { | ||
setup(initialSettings); | ||
if (req) { | ||
req.then(() => tearDown(done)).catch(done.fail); | ||
} else { | ||
done(); | ||
} | ||
}); | ||
|
||
it('constructor should create a valid capture reponse', async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
expect(cr.getLocation()).to.be.equal(locationTestValue); | ||
}); | ||
|
||
it('constructor should throw when passing a null object', async () => { | ||
const error = 'A capture response must be provided to the constructor'; | ||
expect(() => new CaptureResponse()).to.throw(error); | ||
}); | ||
|
||
it('constructor should throw when passing an object without headers', async () => { | ||
const error = 'A capture response must have headers'; | ||
expect(() => new CaptureResponse({})).to.throw(error); | ||
}); | ||
|
||
it('constructor should throw when passing an object without location', async () => { | ||
const error = 'A capture response must have a location property'; | ||
const wrongCaptureResponse = { headers: new Map() }; | ||
wrongCaptureResponse.headers.set('test', 'test'); | ||
expect(() => new CaptureResponse(wrongCaptureResponse)).to.throw(error); | ||
}); | ||
|
||
it('should create a valid capture reponse', async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
expect(cr.getLocation()).to.be.equal(locationTestValue); | ||
}); | ||
|
||
it('should throw when passing a wrong object', async () => { | ||
const error = 'A capture response must be provided to the constructor'; | ||
expect(() => new CaptureResponse()).to.throw(error); | ||
}); | ||
|
||
it('should not be able to access capture job field before fetching them', async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
expect(() => cr.getErrors()).to.throw('The capture job needs to be fetched to get the errors'); | ||
expect(() => cr.getErrorFile()).to.throw('The capture job needs to be fetched to get the error file'); | ||
expect(() => cr.getSuccessStatus()).to.throw('The capture job needs to be fetched to get the success status'); | ||
expect(() => cr.getRunningStatus()).to.throw('The capture job needs to be fetched to get the running status'); | ||
}); | ||
|
||
it('should fetch the capture job information', async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
const res = await cr.getCaptureJob(); | ||
expect(res).to.be.deep.equal(responses.captureJob); | ||
}); | ||
|
||
it('should automatically update the information', async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
await cr.getCaptureJob(); | ||
expect(cr.getErrors()).to.be.deep.equal([]); | ||
expect(cr.getSuccessStatus()).to.be.deep.equal(true); | ||
expect(cr.getRunningStatus()).to.be.deep.equal(false); | ||
}); | ||
|
||
it('should wait for the capture job to be complete (when result is available on the first try)', async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
await cr.pollForTheCaptureToFinish(5, 2000); | ||
expect(cr.getRunningStatus()).to.be.equal(false); | ||
}); | ||
|
||
it("should wait for the capture job to be complete (when result isn't available on the first try)", async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
// we mock the capture result to 'running' | ||
mockCaptureJobIsNotFinished(); | ||
// we mock the capture result to 'success' in 250ms | ||
mockCaptureJobIsFinished(350); | ||
await cr.pollForTheCaptureToFinish(5, 100); | ||
expect(cr.getRunningStatus()).to.be.equal(false); | ||
}); | ||
|
||
it("should wait for the capture job to be complete (when result isn't available after all tries)", async () => { | ||
const cr = new sdk.CaptureResponse(captureResponse); | ||
// we mock the capture result to 'running' | ||
mockCaptureJobIsNotFinished(); | ||
// we mock the capture result to 'success' in 250ms | ||
mockCaptureJobIsFinished(600); | ||
await cr.pollForTheCaptureToFinish(5, 100); | ||
expect(cr.getRunningStatus()).to.be.equal(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.