diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 028990b..841cbca 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -48,7 +48,6 @@ jobs: - ubuntu-latest node: - 14.x - - 12.x steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.nycrc.yml b/.nycrc.yml index 5ffcf51..459cdee 100644 --- a/.nycrc.yml +++ b/.nycrc.yml @@ -10,7 +10,9 @@ require: - source-map-support/register exclude: - '**/*.spec.ts' + - node_modules/**/* - build/**/* + - 'projects/**/test-util/**/*' - test/**/* sourceMap: true instrument: true diff --git a/package.json b/package.json index 3af4b3a..518700f 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "devDependencies": { "@alorel-personal/conventional-changelog-alorel": "^2.1.3", "@alorel/commons-array-types": "^1.1.0", + "@alorel/commons-obj": "^1.0.2", "@alorel/eslint-config-base": "^1.0.17", "@alorel/eslint-config-typescript": "^1.0.17", "@alorel/rollup-plugin-copy": "^1.0.2", @@ -48,12 +49,14 @@ "@semantic-release/github": "^7.1.1", "@semantic-release/npm": "^7.0.6", "@types/chai": "^4.2.12", + "@types/chai-as-promised": "^7.1.3", "@types/jsdom": "^16.2.4", "@types/mocha": "^8.0.3", "@types/node": "^14.11.2", "@typescript-eslint/eslint-plugin": "^4.2.0", "@typescript-eslint/parser": "^4.2.0", "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", "cross-env": "^7.0.2", "del-cli": "^3.0.1", "doctoc": "^1.4.0", diff --git a/projects/core/index.spec.ts b/projects/core/index.spec.ts deleted file mode 100644 index 785ae72..0000000 --- a/projects/core/index.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import {JSDOM} from 'jsdom'; -import type {Mockttp} from 'mockttp'; -import {getLocal} from 'mockttp'; -import {rxAjax} from './lib/rxAjax'; -import type {RxAjax} from './types/RxAjax'; - -describe('tmp', () => { - let baseAjax: RxAjax; - let server: Mockttp = null as any; - before(() => { - const {window: {XMLHttpRequest}} = new JSDOM('').window; - baseAjax = rxAjax({ - createXHR: () => { - const req = new XMLHttpRequest(); - req.withCredentials = false; - - return req; - } - }); - server = getLocal(); - - return server.start(); - }); - - after(() => server?.stop()); - - it('Summin', async () => { - await server.get('/potat') - // eslint-disable-next-line @typescript-eslint/no-magic-numbers - .thenReply(200, JSON.stringify({potato: 'salad'}), {'access-control-allow-origin': '*'}); - const url = server.urlFor('/potat'); - console.log('potat url', url); - - const rsp = await baseAjax.getJSON(url).toPromise(); - - console.log({rsp}); - }); -}); diff --git a/projects/core/lib/makeRequest.spec.ts b/projects/core/lib/makeRequest.spec.ts new file mode 100644 index 0000000..a2ff92f --- /dev/null +++ b/projects/core/lib/makeRequest.spec.ts @@ -0,0 +1,61 @@ +import {expect} from 'chai'; +import type {Mockttp} from 'mockttp'; +import {RSP_HEADERS, setUpMockServer} from '../test-util/MockServer'; +import {testAjaxOpts} from '../test-util/testAjax'; +import type {UnprocessedResponse} from '../types/Response'; +import {makeRequest} from './makeRequest'; + +/* eslint-disable @typescript-eslint/no-magic-numbers */ + +describe('makeRequest', function () { + + describe('Successful response', () => { + let server: Mockttp; + let url: string; + let rsp: UnprocessedResponse; + + setUpMockServer(true, v => (server = v)); + before(async () => { + await server.get('/success').thenJson(200, {su: 'ccess'}, RSP_HEADERS); + url = server.urlFor('/success'); + rsp = await makeRequest({...testAjaxOpts, preAsync: [], url}).toPromise(); + }); + + it('Ok should be true', () => { + expect(rsp.ok).to.eq(true); + }); + + it('Original request should contain custom props', () => { + expect(rsp.response.request).to.haveOwnProperty('preAsync'); + }); + + it('Should have json response', () => { + expect(rsp.response.response).to.deep.eq({su: 'ccess'}); + }); + }); + + describe('Error response', () => { + let server: Mockttp; + let url: string; + let rsp: UnprocessedResponse; + + setUpMockServer(true, v => (server = v)); + before(async () => { + await server.get('/fail').thenJson(420, {fai: 'lure'}, RSP_HEADERS); + url = server.urlFor('/fail'); + rsp = await makeRequest({...testAjaxOpts, postAsync: [], url}).toPromise(); + }); + + it('Ok should be true', () => { + expect(rsp.ok).to.eq(false); + }); + + it('Original request should contain custom props', () => { + expect(rsp.response.request).to.haveOwnProperty('postAsync'); + }); + + it('Should have json response', () => { + expect(rsp.response.response).to.deep.eq({fai: 'lure'}); + }); + }); +}); diff --git a/projects/core/lib/merge.spec.ts b/projects/core/lib/merge.spec.ts new file mode 100644 index 0000000..c42b83e --- /dev/null +++ b/projects/core/lib/merge.spec.ts @@ -0,0 +1,55 @@ +import {expect} from 'chai'; +import {identity, noop, of} from 'rxjs'; +import type {RxAjaxOptions as Opt} from '../types/Options'; +import {merge} from './merge'; + +/* eslint-disable @typescript-eslint/no-magic-numbers */ + +describe('merge', function () { + describe('headers', () => { + it('Should omit if absent in both defaults and custom', () => { + const d: Opt = {url: '/foo'}; + const c: Opt = {withCredentials: true}; + expect(merge(d, c)).to.deep.eq({url: '/foo', withCredentials: true}); + }); + + it('Should merge if it has custom headers', () => { + const d: Opt = {headers: {foo: 'bar'}}; + const c: Opt = {headers: {qux: 'baz'}}; + expect(merge(d, c)).to.deep.eq({headers: {foo: 'bar', qux: 'baz'}}); + }); + + it('Shouldn\'t change reference of using defaults', () => { + const d: Opt = {headers: {}}; + const c: Opt = {url: '/'}; + expect(merge(d, c).headers).to.eq(d.headers); + }); + }); + + describe('arrays', () => { + it('Should omit if absent on both', () => { + expect(merge({}, {})).to.deep.eq({}); + }); + + it('Should reuse default instance', () => { + const d: Opt = {pre: [identity]}; + expect(merge(d, {}).pre).to.eq(d.pre); + }); + + it('Should reuse custom instance', () => { + const d: Opt = {post: [identity as any]}; + expect(merge({}, d).post).to.eq(d.post); + }); + + it('Should concat and dedupe', () => { + const d: Opt = {postAsync: [identity, noop] as any[]}; + const c: Opt = {postAsync: [noop, of] as any[]}; + const {postAsync} = merge(d, c); + + expect(postAsync).to.have.lengthOf(3, 'length'); + expect(postAsync![0]).to.eq(identity, '[identity]'); + expect(postAsync![1]).to.eq(noop, '[noop]'); + expect(postAsync![2]).to.eq(of, '[of]'); + }); + }); +}); diff --git a/projects/core/lib/merge.ts b/projects/core/lib/merge.ts index fdfca30..a4a8650 100644 --- a/projects/core/lib/merge.ts +++ b/projects/core/lib/merge.ts @@ -37,8 +37,11 @@ export function merge(defaults: RxAjaxOptions, custom: RxAjaxOptions): RxAjaxOpt } = custom; const out: RxAjaxOptions = {...defaults, ...restCustom}; - if (defaults.headers || headersCustom) { - out.headers = {...defaults.headers, ...headersCustom}; + if (headersCustom) { + out.headers = { + ...out.headers, + ...headersCustom + }; } mergeProp(out, 'pre', defaults.pre, preCustom); mergeProp(out, 'preAsync', defaults.preAsync, preCustomAsync); diff --git a/projects/core/lib/middleware/applyAsyncPreMiddleware.ts b/projects/core/lib/middleware/applyAsyncPreMiddleware.ts index 90220c4..0dd1fb7 100644 --- a/projects/core/lib/middleware/applyAsyncPreMiddleware.ts +++ b/projects/core/lib/middleware/applyAsyncPreMiddleware.ts @@ -1,6 +1,6 @@ import type {MonoTypeOperatorFunction as MonoOp, Observable} from 'rxjs'; import {of} from 'rxjs'; -import {last, switchMap} from 'rxjs/operators'; +import {switchMap} from 'rxjs/operators'; import type {RxAjaxOptions, RxAjaxPostAsyncHook} from '../../types/Options'; /** @internal */ @@ -12,8 +12,7 @@ export function applyAsyncPreMiddleware(opts: RxAjaxOptions): null | Observable< const src$ = of(opts); const args: Array> = (preAsync as RxAjaxPostAsyncHook[]) - .map(switchMap) - .concat(last()); + .map(switchMap); return src$.pipe.apply(src$, args); // eslint-disable-line prefer-spread } diff --git a/projects/core/lib/middleware/applyPostAsyncMiddleware.ts b/projects/core/lib/middleware/applyPostAsyncMiddleware.ts index 953d8d3..91cd869 100644 --- a/projects/core/lib/middleware/applyPostAsyncMiddleware.ts +++ b/projects/core/lib/middleware/applyPostAsyncMiddleware.ts @@ -1,28 +1,16 @@ -import type {MonoTypeOperatorFunction as MonoOp, Observable} from 'rxjs'; -import {from, of} from 'rxjs'; -import {last, switchMap} from 'rxjs/operators'; +import type {MonoTypeOperatorFunction as MonoOp} from 'rxjs'; +import {pipe} from 'rxjs'; +import {switchMap} from 'rxjs/operators'; import type {RxAjaxOptions} from '../../types/Options'; +import type {RxAjaxPostAsyncHook} from '../../types/Options'; import type {UnprocessedResponse} from '../../types/Response'; /** @internal */ export function applyPostAsyncMiddleware( - idx: number, middleware: Required['postAsync'] ): MonoOp> { - return switchMap( - function applyPostMiddlewareExecutor(response: UnprocessedResponse): Observable> { - if (response.stop) { - return of(response); - } + const pipes = (middleware as RxAjaxPostAsyncHook[]) + .map((mid): MonoOp> => switchMap(mid)); - const pipes: Array> = [last()]; - if (middleware[idx + 1]) { - pipes[1] = applyPostAsyncMiddleware(idx + 1, middleware); - } - - const src$ = from(middleware[idx](response)); - - return src$.pipe.apply(src$, pipes) as Observable>; // eslint-disable-line prefer-spread - } - ); + return pipe.apply(null, pipes as any[]) as MonoOp>; // eslint-disable-line prefer-spread } diff --git a/projects/core/lib/middleware/applyPostMiddleware.ts b/projects/core/lib/middleware/applyPostMiddleware.ts index 90fede2..f9a10bd 100644 --- a/projects/core/lib/middleware/applyPostMiddleware.ts +++ b/projects/core/lib/middleware/applyPostMiddleware.ts @@ -9,16 +9,9 @@ export function applyPostMiddleware( ): MonoTypeOperatorFunction> { return map( function applyPostMiddlewareExecutor(rsp: UnprocessedResponse): UnprocessedResponse { - if (rsp.stop) { - return rsp; - } - let out = rsp; for (let i = 0; i < middleware.length; i++) { out = middleware[i](out); - if (out.stop) { - break; - } } return out; diff --git a/projects/core/lib/rxAjax.spec.ts b/projects/core/lib/rxAjax.spec.ts new file mode 100644 index 0000000..48a35bb --- /dev/null +++ b/projects/core/lib/rxAjax.spec.ts @@ -0,0 +1,133 @@ +import type {Obj} from '@alorel/commons-obj'; +import * as chai from 'chai'; +import * as promiseChai from 'chai-as-promised'; +import type {Mockttp} from 'mockttp'; +import type {Observable} from 'rxjs'; +import {of} from 'rxjs'; +import {RSP_HEADERS, setUpMockServer, setUpRequestDebugger} from '../test-util/MockServer'; +import {testAjax} from '../test-util/testAjax'; +import type {RxAjaxOptions} from '../types/Options'; +import type {RxAjaxResponse, UnprocessedResponse} from '../types/Response'; +import type {RxAjax} from '../types/RxAjax'; + +/* eslint-disable @typescript-eslint/no-magic-numbers */ + +describe('rxAjax', function () { + const expect = chai.use(promiseChai).expect; + + describe('middleware', () => { + let server: Mockttp; + setUpMockServer(true, v => (server = v)); + before(setUpRequestDebugger(() => server)); + + it('Should apply middleware', async () => { + const url = server.urlFor('/test-middleware'); + const ob$ = testAjax.getJSON(url, { + post: [ + (rsp): UnprocessedResponse => ({ + ...rsp, + response: { + ...rsp.response, + customProp: 'is-set' + } as unknown as any + }) + ], + postAsync: [ + (rsp: UnprocessedResponse) => of>({ + ...rsp, + ok: true, + response: { + ...rsp.response, + status: 420 + } as unknown as RxAjaxResponse + }) + ], + pre: [ + (req): RxAjaxOptions => ({ + ...req, + headers: { + ...req.body, + 'content-type': 'potatoes' + } + }) + ], + preAsync: [ + (req): Observable => of({ + ...req, + method: 'DELETE' + }) + ] + }); + + const rsp$ = (await ob$.toPromise()) as RxAjaxResponse & Obj; + const {response: {method, headers}, status, customProp} = rsp$; + + + expect(status).to.eq(420, 'Status'); + expect(method).to.eq('DELETE', 'method'); + expect(headers['content-type']).to.eq('potatoes', 'sent headers'); + expect(customProp).to.eq('is-set', 'customProp'); + + return {headers, method, status}; + }); + }); + + describe('request methods', () => { + let server: Mockttp; + setUpMockServer(true, v => (server = v)); + before(setUpRequestDebugger(() => server)); + + const bodyMethods: Array = ['patch', 'post', 'put']; + const nonBodymethods: Array = ['get', 'delete']; + + for (const meth of bodyMethods) { + it(`Should make ${meth.toUpperCase()} requests`, async () => { + const url = server.urlFor(`/meth-${meth}`); + const body = {[Math.random().toString()]: Math.random()}; + const p$: Promise = testAjax[meth as 'post'].call(null, url, body).toPromise(); + const {response: rsp} = await p$; + + expect(rsp.method).to.eq(meth.toUpperCase(), 'Method'); + expect(rsp.path).to.eq(`/meth-${meth}`, 'Path'); + expect(rsp.body.json).to.deep.eq(body); + }); + } + + for (const meth of nonBodymethods) { + it(`Should make ${meth.toUpperCase()} requests`, async () => { + const url = server.urlFor(`/meth-${meth}`); + const p$: Promise = testAjax[meth as 'get'].call(null, url).toPromise(); + const {response: rsp} = await p$; + + expect(rsp.method).to.eq(meth.toUpperCase(), 'Method'); + expect(rsp.path).to.eq(`/meth-${meth}`, 'Path'); + }); + } + }); + + describe('extend', () => { + let server: Mockttp; + setUpMockServer(true, v => (server = v)); + + it('Should extend settings', async () => { + const b = testAjax.extend({method: 'delete', url: '/delete'}); + + await server.anyRequest() + .thenCallback(req => { + if (req.path === '/delete' && ['OPTIONS', 'DELETE'].includes(req.method)) { + return { + headers: RSP_HEADERS, + status: 200 + }; + } + + return {status: 404}; + }); + + await b(server.urlFor('/delete')).toPromise(); + + expect(1).to.eq(1); + }); + }); + +}); diff --git a/projects/core/lib/rxAjax.ts b/projects/core/lib/rxAjax.ts index c963842..d31b1e3 100644 --- a/projects/core/lib/rxAjax.ts +++ b/projects/core/lib/rxAjax.ts @@ -2,7 +2,7 @@ import type {Observable} from 'rxjs'; import {of, throwError} from 'rxjs'; import {AjaxError} from 'rxjs/ajax'; import {switchMap} from 'rxjs/operators'; -import type {RxAjaxOptions, RxAjaxRequestOptions} from '../types/Options'; +import type {RxAjaxOptions} from '../types/Options'; import type {RxAjaxResponse, UnprocessedResponse} from '../types/Response'; import type {RxAjax} from '../types/RxAjax'; import {makeRequest} from './makeRequest'; @@ -37,14 +37,14 @@ function innerExecutor(mergedOpts: RxAjaxOptions): Observable Observable ): RxAjax['post'] { return function rxAjaxBodyMethodExecutor(url, body, opts) { @@ -61,31 +61,27 @@ export function rxAjax(defaults: RxAjaxOptions = {}): RxAjax return innerExecutor(merge(defaults, mergeableOptions)); } - rxAjaxExecutor.extend = function extend(opts: RxAjaxRequestOptions): RxAjax { - return rxAjax(merge(defaults, opts)); - }; - const ext: Pick, Props> = { delete(url, opts) { - return rxAjaxExecutor({...opts, method: 'delete', url}); + return rxAjaxExecutor({...opts, method: 'DELETE', url}); }, extend(opts) { return rxAjax(merge(defaults, opts)); }, get(url, opts) { - return rxAjaxExecutor({...opts, method: 'get', url}); + return rxAjaxExecutor({...opts, method: 'GET', url}); }, getJSON(url, opts) { return rxAjaxExecutor({ ...opts, - method: 'get', + method: 'GET', responseType: 'json', url }); }, - patch: makeBodyMethod('patch', rxAjaxExecutor), - post: makeBodyMethod('post', rxAjaxExecutor), - put: makeBodyMethod('put', rxAjaxExecutor) + patch: makeBodyMethod('PATCH', rxAjaxExecutor), + post: makeBodyMethod('POST', rxAjaxExecutor), + put: makeBodyMethod('PUT', rxAjaxExecutor) }; return Object.assign(rxAjaxExecutor, ext); diff --git a/projects/core/package.json b/projects/core/package.json index 472044c..e70cf2e 100644 --- a/projects/core/package.json +++ b/projects/core/package.json @@ -4,6 +4,7 @@ "description": "Utility wrapper for rxjs' ajax function", "dependencies": { "@alorel/commons-array-types": "^1.0.0", + "@alorel/commons-obj": "^1.0.2", "tslib": "^2.0.0 || ^1.11.0" }, "peerDependencies": { @@ -27,4 +28,4 @@ "access": "public", "registry": "https://npm.pkg.github.com" } -} \ No newline at end of file +} diff --git a/projects/core/test-util/MockServer.ts b/projects/core/test-util/MockServer.ts new file mode 100644 index 0000000..2c7f2ca --- /dev/null +++ b/projects/core/test-util/MockServer.ts @@ -0,0 +1,39 @@ +import type {MockedEndpoint, Mockttp} from 'mockttp'; +import {getLocal} from 'mockttp'; + +export const RSP_HEADERS = {'access-control-allow-origin': '*'}; + +export function setUpMockServer(once: boolean, setter: (v: Mockttp) => void): void { + let server: Mockttp = null as any; + const bf = async () => { + server = getLocal(); + await server.start(); + setter(server); + }; + const af = () => { + const stop$ = server?.stop(); + setter(server = null as any); + + return stop$; + }; + + if (once) { + before(bf); + after(af); + } else { + beforeEach(bf); + afterEach(af); + } +} + +export function setUpRequestDebugger(getServer: () => Mockttp): () => Promise { + return () => getServer().anyRequest() + .thenCallback(({method, path, headers, body}) => ({ + body: JSON.stringify({body, headers, method, path}), + headers: { + ...RSP_HEADERS, + 'content-type': 'application/json' + }, + status: 200 + })); +} diff --git a/projects/core/test-util/testAjax.ts b/projects/core/test-util/testAjax.ts new file mode 100644 index 0000000..848aa8e --- /dev/null +++ b/projects/core/test-util/testAjax.ts @@ -0,0 +1,11 @@ +import {JSDOM} from 'jsdom'; +import {rxAjax} from '../lib/rxAjax'; +import type {RxAjaxOptions} from '../types/Options'; + +const {window: {XMLHttpRequest}} = new JSDOM(''); + +export const testAjaxOpts: RxAjaxOptions = { + createXHR: () => new XMLHttpRequest(), + headers: {'content-type': 'application/json'} +}; +export const testAjax = rxAjax(testAjaxOpts); diff --git a/projects/core/types/Options.ts b/projects/core/types/Options.ts index f9f9480..8fcc86e 100644 --- a/projects/core/types/Options.ts +++ b/projects/core/types/Options.ts @@ -1,4 +1,5 @@ import type {Arrayish} from '@alorel/commons-array-types'; +import type {Obj} from '@alorel/commons-obj'; import type {ObservableInput} from 'rxjs'; import type {AjaxRequest} from 'rxjs/ajax'; import type {UnprocessedResponse} from './Response'; @@ -6,7 +7,9 @@ import type {UnprocessedResponse} from './Response'; export type RxAjaxPostAsyncHook = (request: UnprocessedResponse) => ObservableInput>; -export interface RxAjaxOptions extends AjaxRequest { +export interface RxAjaxOptions extends Omit { + headers?: Obj; + post?: Arrayish<((request: UnprocessedResponse) => UnprocessedResponse)>; postAsync?: Arrayish; diff --git a/projects/core/types/Response.ts b/projects/core/types/Response.ts index 817942c..916144c 100644 --- a/projects/core/types/Response.ts +++ b/projects/core/types/Response.ts @@ -2,20 +2,14 @@ import type {AjaxResponse} from 'rxjs/ajax'; import type {RxAjaxErrorResponse} from './Error'; import type {RxAjaxOptions} from './Options'; -interface BaseUnprocessedResponse { - ok: boolean; - - stop?: true; -} - -export interface UnprocessedSuccessResponse extends BaseUnprocessedResponse{ +export interface UnprocessedSuccessResponse { ok: true; response: RxAjaxResponse; } -export interface UnprocessedErrorResponse extends BaseUnprocessedResponse{ +export interface UnprocessedErrorResponse { ok: false; response: RxAjaxErrorResponse; diff --git a/projects/core/types/RxAjax.ts b/projects/core/types/RxAjax.ts index 82fa135..0674ab3 100644 --- a/projects/core/types/RxAjax.ts +++ b/projects/core/types/RxAjax.ts @@ -5,7 +5,7 @@ import type {RxAjaxResponse} from './Response'; export interface RxAjax { delete(url: string, opts?: RxAjaxRequestOptions): Observable>; - extend(opts: RxAjaxRequestOptions): RxAjax; + extend(opts: RxAjaxOptions): RxAjax; get(url: string, opts?: RxAjaxRequestOptions): Observable>; diff --git a/yarn.lock b/yarn.lock index cd420b2..303ebd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,13 @@ __metadata: languageName: node linkType: hard +"@alorel/commons-obj@npm:^1.0.2": + version: 1.0.2 + resolution: "@alorel/commons-obj@npm:1.0.2::__archiveUrl=https%3A%2F%2Fnpm.pkg.github.com%2Fdownload%2F%40alorel%2Fcommons-obj%2F1.0.2%2F7b504d0ff6580347d8ed4a4ce22b72e464f1fd11802bed4689a36785d16022b2" + checksum: 2/bb71acb3a3d7afa972952bb18ea7a713cdc58eca2c1bbfabd304014bdec98647370b5a326a563f3576f2c5d40be9eb5b4a87e03dd93e157e2114e9d2f32776b3 + languageName: node + linkType: hard + "@alorel/eslint-config-base@npm:^1.0.17": version: 1.0.17 resolution: "@alorel/eslint-config-base@npm:1.0.17::__archiveUrl=https%3A%2F%2Fnpm.pkg.github.com%2Fdownload%2F%40alorel%2Feslint-config-base%2F1.0.17%2F0cd00f7cc51881f31cf552fb4944779e1bd38426816ee479bae829e9e9491d11" @@ -111,6 +118,7 @@ __metadata: dependencies: "@alorel-personal/conventional-changelog-alorel": ^2.1.3 "@alorel/commons-array-types": ^1.1.0 + "@alorel/commons-obj": ^1.0.2 "@alorel/eslint-config-base": ^1.0.17 "@alorel/eslint-config-typescript": ^1.0.17 "@alorel/rollup-plugin-copy": ^1.0.2 @@ -125,12 +133,14 @@ __metadata: "@semantic-release/github": ^7.1.1 "@semantic-release/npm": ^7.0.6 "@types/chai": ^4.2.12 + "@types/chai-as-promised": ^7.1.3 "@types/jsdom": ^16.2.4 "@types/mocha": ^8.0.3 "@types/node": ^14.11.2 "@typescript-eslint/eslint-plugin": ^4.2.0 "@typescript-eslint/parser": ^4.2.0 chai: ^4.2.0 + chai-as-promised: ^7.1.1 cross-env: ^7.0.2 del-cli: ^3.0.1 doctoc: ^1.4.0 @@ -911,7 +921,16 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:^4.2.12": +"@types/chai-as-promised@npm:^7.1.3": + version: 7.1.3 + resolution: "@types/chai-as-promised@npm:7.1.3" + dependencies: + "@types/chai": "*" + checksum: 2/71f383b20c556bf227b4e117f721fb7d92dcdaeefe7c352b301d59e0eca9dc2c72538c0f2829da62ba06b2c26002a730c5b7137b43aaac76f7c9ff8fdc9847f2 + languageName: node + linkType: hard + +"@types/chai@npm:*, @types/chai@npm:^4.2.12": version: 4.2.12 resolution: "@types/chai@npm:4.2.12" checksum: 2/5dc6d541d748dbf95e0f0b1a39177e0bd8b37f143307cce6a93baf3d6cb44fead65fddb582ce9397aa14b1a76117e5d398fa322f92182074b7d53e5d2f669a19 @@ -2044,6 +2063,17 @@ __metadata: languageName: node linkType: hard +"chai-as-promised@npm:^7.1.1": + version: 7.1.1 + resolution: "chai-as-promised@npm:7.1.1" + dependencies: + check-error: ^1.0.2 + peerDependencies: + chai: ">= 2.1.2 < 5" + checksum: 2/747b85b679f8decdbb83f249883519ea5d4de055f2502fb830db28175af1e4f02a6a8c505d6edce1f2cf28c5512d5e3666db92906b80e77fca30b37c3e5cd360 + languageName: node + linkType: hard + "chai@npm:^4.2.0": version: 4.2.0 resolution: "chai@npm:4.2.0"