RxJs/Ngrx TestSheduler с имитацией пользовательского ввода (Жасмин)

Я тестирую эффекты магазина Ngrx в угловом приложении. Одним из моих эффектов, в качестве побочного эффекта, является модал, который появляется с использованием компонента MatDialog материала.

Что я хочу сделать, так это запустить тест, в котором эффект запускается действием, которое вызывает появление диалогового окна. Затем я хочу протестировать нажатие "да / нет", а затем приступить к проверке конечного действия (или его отсутствия).

Мы используем rxjs-marbles для тестирования нашего магазина.

У RxJs не так уж много примеров, но я понял, что мне нужно использовать TestScheduler для этого типа сценария. Я не уверен, как это работает, хотя. Я провожу много исследований и не добился большого прогресса.

В принципе, как мрамор, это выглядит так:

-a-b-c

где a это начальное действие, b это щелчок пользователя в диалоговом окне, и c результат (c является необязательным, если пользователь нажимает "нет", то никакого результирующего действия не будет.

Я не прошу никого писать мой код, просто укажи мне правильное направление. Я собираюсь начать читать исходный код для TestScheduler, чтобы понять его лучше, потому что я даже не уверен, что это то, что я должен использовать в этом случае.

По сути, как можно написать такой тест, где есть наблюдаемые потоки в сочетании с моделируемым пользовательским вводом с использованием шариков?

1 ответ

Решение

Так что я понял, что поступил неправильно. Это юнит-тест, а не e2e-тест, поэтому мне не нужно тестировать определенные функции пользовательского интерфейса. Поэтому я придумал следующий тест:

it('should show a dialog, and do nothing if the user does not confirm',
      () => {
        const dialogRef = jasmine.createSpyObj('dialogRef', {
          afterClosed: of(false),
        });
        const action = new AppActions.PromptUserAction();
        matDialog.open.and.returnValue(dialogRef);

        actions = hot('a', { a: action });
        const expected = cold('', {});

        expect(effects.promptUserAction$).toBeObservable(expected);
        expect(matDialog.open).toHaveBeenCalled();
        expect(dialogRef.afterClosed).toHaveBeenCalled();
      });

Пояснения:

  • Создайте dialogRef, который будет возвращен поддельной службой MatDialog (выполняется в настройке beforeEach Angular TestBed, созданной путем предоставления объекта-шпиона следующим образом:

    {
      provide: MatDialog,
      useValue: jasmine.createSpyObj(
        'MatDialog',
        ['open'],
      ),
    },
    
  • Это заглушает метод open, и вы заметите, что вызов open делается для returnValue dialogRef, который мы затем можем использовать в качестве шпиона для возврата желаемой наблюдаемой. Довольно просто, правда.

Остальная часть теста была простой. Надеюсь, это кому-нибудь поможет - вам не обязательно имитировать щелчок, поскольку он неявно присутствует в потоке!

Другие вопросы по тегам