UNPKG

@opra/testing

Version:

Opra testing package

212 lines (211 loc) 7.91 kB
import '../expect-extend/index.js'; import { updateErrorMessage } from '@jsopen/objects'; import { MimeTypes } from '@opra/common'; import colors from 'ansi-colors'; import { expect } from 'expect'; import { ApiExpectBase } from './api-expect-base.js'; import { ApiExpectCollection } from './api-expect-collection.js'; import { ApiExpectError } from './api-expect-error.js'; import { ApiExpectObject } from './api-expect-object.js'; import { ApiExpectOperationResult } from './api-expect-operation-result.js'; /** * Main entry point for API assertions. * * @class ApiExpect */ export class ApiExpect extends ApiExpectBase { /** * Asserts that the request was successful (status code 200-399). * * @param status Optional expected status code. * @returns The current ApiExpect instance. * @throws {@link Error} if the assertion fails. */ toSuccess(status) { let msg = ''; try { msg += `Status code do not match. `; if (status) { expect(this.response.status).toEqual(status); } else { expect(this.response.status).toBeGreaterThanOrEqual(200); expect(this.response.status).toBeLessThan(400); } } catch (e) { e.message = "Request didn't succeeded as expected. " + msg + '\n\n' + e.message; const issues = this._parseBodyErrors(this.response.body?.errors); if (issues) e.message += '\n\n' + issues; else e.message += '\n\nbody: ' + this.response.body; if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(e, this.toSuccess); else updateErrorMessage(e, e.message); throw e; } return this; } /** * Asserts that the request failed (status code 400-599). * * @param status Optional expected status code. * @returns An {@link ApiExpectError} instance. * @throws {@link Error} if the assertion fails. */ toFail(status) { let msg = ''; try { msg += `Status code do not match. `; if (status) { expect(this.response.status).toEqual(status); } else { expect(this.response.status).toBeGreaterThanOrEqual(400); expect(this.response.status).toBeLessThanOrEqual(599); } } catch (e) { e.message = "Request didn't failed as expected. " + msg + '\n\n' + e.message + '\n\nbody: ' + this.response.body; if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(e, this.toFail); else updateErrorMessage(e, e.message); throw e; } return new ApiExpectError(this.response); } /** * Asserts that the API returned a Collection. * * @returns An {@link ApiExpectCollection} instance. * @throws {@link Error} if the assertion fails. */ toReturnCollection() { let msg = ''; try { msg = 'Content-Type header value is not valid. '; expect(this.response.contentType).toEqual('application/opra.response+json'); msg = 'Type of response "body" is not valid. '; expect(typeof this.response.body).toEqual('object'); msg = 'Type of "payload" is not an Array. '; const payload = this.response.body.payload; expect(Array.isArray(payload) ? 'array' : typeof payload).toEqual('array'); } catch (e) { e.message = "Api didn't returned a Collection. " + msg + '\n\n' + e.message + '\n\nbody: ' + this.response.body; const issues = this._parseBodyErrors(this.response.body?.errors); if (issues) e.message += '\n\n' + issues; if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(e, this.toReturnCollection); else updateErrorMessage(e, e.message); throw e; } return new ApiExpectCollection(this.response); } /** * Asserts that the API returned an Object. * * @param contentType Optional expected Content-Type header value. * @returns An {@link ApiExpectObject} instance. * @throws {@link Error} if the assertion fails. */ toReturnObject(contentType) { let msg = ''; try { msg = 'Content-Type header value is not valid. '; expect(this.response.contentType).toEqual(contentType || MimeTypes.opra_response_json); msg = 'Type of response "body" is not valid. '; expect(typeof this.response.body).toEqual('object'); msg = 'Type of "payload" is not an Object. '; const payload = this.response.body.payload; expect(typeof payload).toEqual('object'); } catch (e) { e.message = "Api didn't returned an Object. " + msg + '\n\n' + e.message + '\n\nbody: ' + this.response.body; if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(e, this.toReturnObject); else updateErrorMessage(e, e.message); throw e; } return new ApiExpectObject(this.response); } /** * Asserts that the API returned an OperationResult. * * @returns An {@link ApiExpectOperationResult} instance. * @throws {@link Error} if the assertion fails. */ toReturnOperationResult() { let msg = ''; try { msg = 'Content-Type header value is not valid. '; expect(this.response.contentType).toEqual(MimeTypes.opra_response_json); msg = 'Type of response "body" is not valid. '; expect(typeof this.response.body).toEqual('object'); msg = 'The response has payload. '; const payload = this.response.body.payload; expect(typeof payload).toEqual('undefined'); } catch (e) { e.message = "Api didn't returned a OperationResult. " + msg + '\n\n' + e.message + '\n\nbody: ' + this.response.body; if (msg) e.message = msg + '\n\n' + e.message; const issues = this._parseBodyErrors(this.response.body?.errors); if (issues) e.message += '\n\n' + issues; if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(e, this.toReturnOperationResult); else updateErrorMessage(e, e.message); throw e; } return new ApiExpectOperationResult(this.response); } _parseBodyErrors(errors) { if (Array.isArray(errors)) { let out = ''; errors.forEach((issue, i) => { const stack = Array.isArray(issue.stack) ? issue.stack.join('\n') : issue.stack; out += colors.yellow(errors.length > 1 ? `Error [${i}]: ` : 'Error: ') + issue.message + '\n' + (stack ? ' ' + stack.substring(stack.indexOf('at ')) + '\n' : ''); }); return out; } } }