mardi 25 juin 2019

Testing RXJS custom pipes

I have a custom pipe, that is only a collection of multiple pipes. I, however, would like to test the code.

export type AnnotatedResponse<T> = T & {
    awaitingNewValues: boolean;
    failed: boolean;
};

function merge<T>(
    original: T,
    awaitingNewValues: boolean,
    failed: boolean,
): AnnotatedResponse<T> {
    return Object.assign({},
        original,
        { awaitingNewValues, failed },
    );
}

export function annotateAwaiting<I, T extends {}>(
    initialValue: T,
    toAnnotate: (input: I) => Observable<T>,
): (source: Observable<I>) => Observable<AnnotatedResponse<T>> {
    return (source: Observable<I>) => {
        let lastValue: T = initialValue;
        return source.pipe(
            switchMap(input => concat(
                of(merge(lastValue, true, false)),
                toAnnotate(input).pipe(
                    take(1),
                    map(result => {
                        lastValue = result;
                        return merge(result, false, false);
                    }),
                    catchError(() => {
                        return of(merge(lastValue, false, true));
                    }),
                ),
            )),
            finalize(() => {
                //  Free reference to prevent memory leaks
                lastValue = undefined as any;
            }),
        );
    };
}

The test

fdescribe('annotateAwaiting$', () => {
    let subject: Subject<string>;
    let annotated: Observable<AnnotatedResponse<{ letter: string }>>;
    let response: Subject<Error | { letter: string }>;

    beforeEach(() => {
        subject = new Subject<string>();
        response = new Subject();
        annotated = subject.pipe(
            annotateAwaiting(
                { letter: '' },
                letter => response.pipe(
                    take(1),
                    map(val => {
                        if (val instanceof Error) {
                            throw val;
                        } else {
                            return val;
                        }
                    }),
                ),
            ),
            shareReplay(1),
        );
    });

    afterEach(() => {
        subject.complete();
        response.complete();
    });

    it('should emit immediately', () => {
        let i = 0;
        subject.next('a');
        annotated.pipe(
            take(1),
        ).subscribe(obj => {    //  Runs
            expect(obj.awaitingNewValues).toBe(true);
            expect(obj.failed).toBe(false);
            expect(obj.letter).toBe('');
            i++;
        });

        expect(i).toBe(1);

        response.next({ letter: 'a'});
        annotated.pipe(
            take(1),
        ).subscribe(obj => {    //  Doesn't run (neither async)
            expect(obj.awaitingNewValues).toBe(false);
            expect(obj.failed).toBe(false);
            expect(obj.letter).toBe('a');
            i++;
        });

        expect(i).toBe(2);
    });
});

What am I missing? Why it doesn't seem to run at all?

Aucun commentaire:

Enregistrer un commentaire