Table of contents
Sometimes, instead of using debugger
keyword, you'll just want to display the values in the console. When using RxJS you'll probably use quick&dirty tap(value => console.log(value))
. There's nothing wrong with it, but it can be done a little nicer and manageable. I'll create a custom RxJS operator to achieve this.
Setup
Requirements: Node, npm, npx
Install dependencies
npm i jest@29 @types/jest@29 ts-jest rxjs typescript
Init ts-jest
npx ts-jest config:init
logValue operator
This operator uses the native tap
operator to call the console.log()
. Simple as that.
import { MonoTypeOperatorFunction } from 'rxjs';
import { tap } from 'rxjs/operators';
export function logValue<T>(): MonoTypeOperatorFunction<T> {
return tap((value: T): void => {
console.log(value);
});
}
So why use it anyway? There are a couple of advantages:
easily find usages of this operator instead of searching the whole project for
console.log
stringeasily replace
console.log
with any other logging mechanismeasily add some logic to enable/disable logging (i.e. use environment variable)
less code and ease of use
Test it
The test performs the following operations:
spies on
console.log
methodemits single and multiple values in the stream
tests the number of calls and the arguments of the spy
import { from, of } from 'rxjs';
import { logValue } from './log-value.operator';
describe('Test logValue operator', () => {
let spy: jest.SpyInstance;
beforeEach(() => {
spy = jest.spyOn(console, 'log');
});
afterEach(() => {
spy.mockClear();
});
describe('Test single logValue call', () => {
beforeEach(() => {
of('the string').pipe(logValue()).subscribe();
});
it('should call console.log once', () => {
expect(console.log).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenNthCalledWith(1, 'the string');
});
});
describe('Test multiple logValue calls', () => {
beforeEach(() => {
const data = [1, 2, 3, 4, 5];
from(data).pipe(logValue()).subscribe();
});
it('should call console.log 5 times', () => {
expect(console.log).toHaveBeenCalledTimes(5);
expect(console.log).toHaveBeenNthCalledWith(1, 1);
expect(console.log).toHaveBeenNthCalledWith(2, 2);
expect(console.log).toHaveBeenNthCalledWith(3, 3);
expect(console.log).toHaveBeenNthCalledWith(4, 4);
expect(console.log).toHaveBeenNthCalledWith(5, 5);
});
});
});
Run npx jest
and check the results. By default, you'll get some console.log
outputs on the screen, but the final result should be similar to:
PASS src/log-value.operator.spec.ts
Test logValue operator
Test single logValue call
✓ should call console.log once
Test multiple logValue calls
✓ should call console.log 5 times
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total