diff --git a/packages/operators/CHANGELOG.md b/packages/operators/CHANGELOG.md index db4a411..8811fb4 100644 --- a/packages/operators/CHANGELOG.md +++ b/packages/operators/CHANGELOG.md @@ -1,5 +1,17 @@ # Project Changelog +# [@rxjs-collection/operators-v1.0.13-beta.1](https://github.com/basics/rxjs-collection/compare/@rxjs-collection/operators-v1.0.12...@rxjs-collection/operators-v1.0.13-beta.1) (2024-11-27) + + +### Bug Fixes + +* **operators:** added error test case ([8495596](https://github.com/basics/rxjs-collection/commit/84955962d3f6bc50a6fe7e47bafaf0bcc686c231)) +* **operators:** cleanup ([236fb2e](https://github.com/basics/rxjs-collection/commit/236fb2e6119c4e6911cf4ec7deed9afffe6cbb04)) +* **operators:** log test ([14bcad4](https://github.com/basics/rxjs-collection/commit/14bcad4549391af15ec8486ecd4c6303d2ac372c)) +* **operators:** more readable test data ([5edeb7c](https://github.com/basics/rxjs-collection/commit/5edeb7c73d542401c92f9f30f16ac3ebe3de7088)) +* **operators:** refactored log ([345487e](https://github.com/basics/rxjs-collection/commit/345487e7f8aa0072c728d726a7a8517fae154330)) +* **operators:** strip datetimeisostring from log output ([d26ab18](https://github.com/basics/rxjs-collection/commit/d26ab186cfbc91c3e1afc7237198475192049822)) + # [@rxjs-collection/operators-v1.0.12](https://github.com/basics/rxjs-collection/compare/@rxjs-collection/operators-v1.0.11...@rxjs-collection/operators-v1.0.12) (2024-11-26) diff --git a/packages/operators/package.json b/packages/operators/package.json index d95372b..2b9137d 100644 --- a/packages/operators/package.json +++ b/packages/operators/package.json @@ -1,6 +1,6 @@ { "name": "@rxjs-collection/operators", - "version": "1.0.12", + "version": "1.0.13-beta.1", "description": "rxjs operators", "license": "MIT", "contributors": [ diff --git a/packages/operators/src/cache.test.js b/packages/operators/src/cache.test.js index 6496b70..b20f9f9 100644 --- a/packages/operators/src/cache.test.js +++ b/packages/operators/src/cache.test.js @@ -1,6 +1,7 @@ +import { mockResponse } from '#mocks/response.js'; import { map } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; -import { beforeEach, describe, expect, test } from 'vitest'; +import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; import { cache } from './cache'; import { log } from './log'; @@ -8,14 +9,22 @@ import { log } from './log'; describe('cache', () => { let testScheduler; + beforeAll(async () => { + global.Response = mockResponse(); + }); + beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected)); }); + afterAll(() => { + vi.restoreAllMocks(); + }); + test('default', () => { const expectedVal = { - a: new Response('initial', { status: 200 }), - b: new Response('updated', { status: 200 }) + a: new Response('initial'), + b: new Response('updated') }; const triggerVal = [expectedVal.a, expectedVal.b]; @@ -24,8 +33,8 @@ describe('cache', () => { const stream = cold('a', { a: () => triggerVal.shift() }).pipe( map(fn => fn()), log('operators:cache:default:input'), - cache({ ttl: 2 }) - // log('operators:cache:default:output') + cache({ ttl: 2 }), + log('operators:cache:default:output') ); const unsubA = '-^!'; diff --git a/packages/operators/src/log.js b/packages/operators/src/log.js index efa2dc2..7bef0cd 100644 --- a/packages/operators/src/log.js +++ b/packages/operators/src/log.js @@ -1,32 +1,36 @@ import { bgGreen } from 'ansi-colors'; import debug from 'debug'; -import { connectable, finalize, Subject, tap } from 'rxjs'; +import { connectable, finalize, Observable, Subject } from 'rxjs'; -import { pipeWhen } from './when'; - -export const enableLog = tag => { - debug.enable(tag); -}; +export const enableLog = tag => debug.enable(tag); export const log = tag => { const logger = debug(tag); logger.log = global.console.log.bind(console); const error = debug(`${tag}:error`); - return source => - source.pipe( - pipeWhen( - () => debug.enabled(tag), - tap({ - subscribe: () => logger('subscribed'), - unsubscribe: () => logger('unsubscribed'), - finalize: () => logger('finalize'), - next: val => logger(val), - error: err => error(err), - complete: () => logger(bgGreen.bold('complete!')) - }) - ) - ); + if (debug.enabled(tag)) { + return source => { + return new Observable(observer => { + return source.subscribe({ + next: val => { + logger(val); + observer.next(val); + }, + error: err => { + error(err); + observer.error(err); + }, + complete: () => { + logger(bgGreen.bold('complete!')); + observer.complete(); + } + }); + }); + }; + } + + return source => source; }; export const logResult = (tag, observable) => { @@ -40,33 +44,3 @@ export const logResult = (tag, observable) => { ).connect(); }); }; - -// export const log = tag => { -// var logger = debug(tag); -// logger.log = global.console.log.bind(console); -// var error = debug(`${tag}:error`); - -// if (debug.enabled(tag)) { -// return source => -// new Observable(observer => { -// source.subscribe({ -// subscribe: () => logger('subscribed'), -// unsubscribe: () => logger('unsubscribed'), -// finalize: () => logger('finalize'), -// next: val => { -// logger(val); -// observer.next(val); -// }, -// error: err => { -// error(err); -// observer.error(err); -// }, -// complete: () => { -// logger(bgGreen.bold('complete!')); -// observer.complete(); -// } -// }); -// }); -// } -// return source => source; -// }; diff --git a/packages/operators/src/log.test.js b/packages/operators/src/log.test.js index 4a2866f..4b4aeb1 100644 --- a/packages/operators/src/log.test.js +++ b/packages/operators/src/log.test.js @@ -1,11 +1,93 @@ -import { describe, test } from 'vitest'; +import { from, map } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; +import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest'; + +import { enableLog, log, logResult } from './log'; describe('log', () => { + let testScheduler; + + beforeEach(() => { + testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected)); + }); + + afterAll(() => { + vi.restoreAllMocks(); + }); + test('default', () => { - //TODO: add test + const expectedVal = { + a: 'content a', + b: 'content b', + c: 'content c' + }; + + const triggerVal = { + a: () => expectedVal.a, + b: () => expectedVal.b, + c: () => expectedVal.c, + d: () => { + throw new Error('custom error'); + } + }; + + const expected = [ + ' operators:log:default content a', + ' operators:log:default content b', + ' operators:log:default content c' + ]; + + const actual = []; + vi.spyOn(console, 'log').mockImplementation(v => { + actual.push(replaceDateTimeISOString(stripAnsiCodes(v))); + return v; + }); + + enableLog('operators:log:default'); + testScheduler.run(({ cold, expectObservable, flush }) => { + const stream = cold('a-b-c-d|', triggerVal).pipe( + map(v => v()), + log('operators:log:default') + ); + expectObservable(stream).toBe('a-b-c-#', expectedVal, new Error('custom error')); + flush(); + expect(actual).deep.equal(expected); + }); }); - test('logResult', () => { - //TODO: add test + test('logResult', async () => { + const actual = []; + vi.spyOn(console, 'log').mockImplementation(v => { + actual.push(replaceDateTimeISOString(stripAnsiCodes(v))); + return v; + }); + + const expectedVal = [ + ' operators:log:result content a', + ' operators:log:result content b', + ' operators:log:result content c', + ' operators:log:result complete!' + ]; + + const triggerVal = ['content a', 'content b', 'content c']; + + enableLog('operators:log:result'); + await logResult('operators:log:result', from(triggerVal)); + expect(actual).deep.equal(expectedVal); }); }); + +const stripAnsiCodes = str => { + return str.replace( + // eslint-disable-next-line security/detect-unsafe-regex, no-control-regex + /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, + '' + ); +}; + +const replaceDateTimeISOString = str => { + return str.replace( + /^[0-9]{4}-((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[469]|11)-(0[1-9]|[12][0-9]|30)|(02)-(0[1-9]|[12][0-9]))T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])\.[0-9]{3}Z/, + ' ' + ); +}; diff --git a/packages/operators/src/request/autoPagination.test.js b/packages/operators/src/request/autoPagination.test.js index 365f63b..088bc53 100644 --- a/packages/operators/src/request/autoPagination.test.js +++ b/packages/operators/src/request/autoPagination.test.js @@ -28,11 +28,11 @@ describe('auto pagination', () => { const { autoPagination } = await import('./autoPagination'); const expectedVal = { - a: { value: 'a', next: 'b' }, - b: { value: 'b', next: 'c' }, - c: { value: 'c', next: 'd' }, - d: { value: 'd', next: 'e' }, - e: { value: 'e', next: null } + a: { value: 'content a', next: 'b' }, + b: { value: 'content b', next: 'c' }, + c: { value: 'content c', next: 'd' }, + d: { value: 'content d', next: 'e' }, + e: { value: 'content e', next: null } }; const triggerVal = { diff --git a/packages/operators/src/request/concurrentRequest.test.js b/packages/operators/src/request/concurrentRequest.test.js index aeb1595..bc0fc57 100644 --- a/packages/operators/src/request/concurrentRequest.test.js +++ b/packages/operators/src/request/concurrentRequest.test.js @@ -27,12 +27,20 @@ describe('concurrent request', () => { test('default', async () => { const { concurrentRequest } = await import('./concurrentRequest'); + const expectedVal = { + a: 'content a', + b: 'content b', + c: 'content c', + d: 'content d', + e: 'content e' + }; + const triggerVal = { - a: { t: 2, v: new Response('a') }, - b: { t: 5, v: new Response('b') }, - c: { t: 1, v: new Response('c') }, - d: { t: 3, v: new Response('d') }, - e: { t: 4, v: new Response('e') } + a: { t: 2, v: new Response(expectedVal.a) }, + b: { t: 5, v: new Response(expectedVal.b) }, + c: { t: 1, v: new Response(expectedVal.c) }, + d: { t: 3, v: new Response(expectedVal.d) }, + e: { t: 4, v: new Response(expectedVal.e) } }; testScheduler.run(({ cold, expectObservable }) => { @@ -43,7 +51,7 @@ describe('concurrent request', () => { resolveText(), log('operators:request:concurrent:output') ) - ).toBe('---a--c-(bd)--(e|)'); + ).toBe('---a--c-(bd)--(e|)', expectedVal); }); }); }); diff --git a/packages/operators/src/request/lazyPagination.test.js b/packages/operators/src/request/lazyPagination.test.js index 3533313..5d97ce1 100644 --- a/packages/operators/src/request/lazyPagination.test.js +++ b/packages/operators/src/request/lazyPagination.test.js @@ -38,11 +38,11 @@ describe('lazy pagination', () => { }; const expectedVal = { - a: { value: '1' }, - b: { value: '2' }, - c: { value: '3' }, - d: { value: '4' }, - e: { value: '5' } + a: { value: 'content a' }, + b: { value: 'content b' }, + c: { value: 'content c' }, + d: { value: 'content d' }, + e: { value: 'content e' } }; const responseVal = { diff --git a/packages/operators/src/retry.test.js b/packages/operators/src/retry.test.js index 7dbe3cd..d797f5c 100644 --- a/packages/operators/src/retry.test.js +++ b/packages/operators/src/retry.test.js @@ -1,6 +1,6 @@ import { map } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; -import { beforeEach, describe, expect, test } from 'vitest'; +import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest'; import { log } from './log'; import { retryWhenRequestError } from './retry'; @@ -12,6 +12,10 @@ describe('request retry', () => { testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected)); }); + afterAll(() => { + vi.restoreAllMocks(); + }); + test('2x error -> 1x success', () => { const expectedVal = { a: new Response('', { status: 500 }), diff --git a/packages/operators/src/when.test.js b/packages/operators/src/when.test.js index bd8e6b9..6525a96 100644 --- a/packages/operators/src/when.test.js +++ b/packages/operators/src/when.test.js @@ -1,6 +1,6 @@ import { map } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; -import { beforeEach, describe, expect, test } from 'vitest'; +import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest'; import { log } from './log'; import { pipeWhen } from './when'; @@ -12,6 +12,10 @@ describe('when', () => { testScheduler = new TestScheduler((actual, expected) => expect(actual).deep.equal(expected)); }); + afterAll(() => { + vi.restoreAllMocks(); + }); + test('default', () => { const triggerVal = { a: 1,