# RxJS log value pipe

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

```shell
npm i jest@29 @types/jest@29 ts-jest rxjs typescript
```

Init `ts-jest`

```shell
npx ts-jest config:init
```

# logValue operator

This operator uses the native `tap` operator to call the `console.log()`. Simple as that.

```typescript
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` string
    
* easily replace `console.log` with any other logging mechanism
    
* easily 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` method
    
* emits single and multiple values in the stream
    
* tests the number of calls and the arguments of the spy
    

```typescript
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:

```shell
 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
```
