angular-redux / store

Angular 2+ bindings for Redux
MIT License
1.34k stars 205 forks source link

not understanding how to test subscription side effects #566

Open arkD opened 4 years ago

arkD commented 4 years ago

This is a...

What toolchain are you using for transpilation/bundling?

Environment

NodeJS Version: 10.16.0 Typescript Version: 3.2.4 Angular Version: 7 @angular-redux/store version: 9 @angular/cli version: (if applicable) 7.3 OS: windows

Link to repo showing the issus

(optional, but helps a lot) private sorry

The Problem:

I don't understand and hours of investigation and research so far have not helped I have an encoded cache store with default values. I want to test my component theme is updated correctly from the store and get more complex from there.

here is a snippet:

  @select() theme$: Observable<IAppTheme>;
  theme: IAppTheme;

  constructor(public overlay: OverlayContainer,
              public acts: Actions) {
    this.theme$.subscribe((theme: IAppTheme) => {
      this.setTheme(theme.product.name); // this function changes a bunch of css based on the theme and uses the theme name to call the right css classes
      this.theme = theme; // this makes it easier and a lot less ugly in the html then using | async everywhere
    });
  }

  ngOnInit(): void {
    this.acts.installTheme(this.theme); // this is an Action that updates the theme,  it is there because its annoying to switch themes to see changes every time I made changes to them.
  }

I would like to use my store's defaults, not create a mock if possible to test this

The Test:

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    router = TestBed.get(Router);
    component = fixture.componentInstance;
    redux = TestBed.get(NgRedux);
    de = fixture.debugElement;

    fixture.detectChanges();
  });

  it('should update theme through subscription in init', fakeAsync(() => {
    expect(component.theme).toBeUndefined(); // passes
    component.ngOnInit();
    fixture.detectChanges();
    flushMicrotasks();
    fixture.whenStable().then(() =>
      expect(component.theme).toBeUndefined(); // passes but not what I want
      // expect(component.theme.name).toBe('default'); // what I want to pass
    );
  }));

not sure if it is obvious but I have no idea how to get the observable to complete so I get something other than undefined.

The Question

It is clear to me that I don't understand the testing environment, as it appears the store behaves differently? how can I test this?

arkD commented 4 years ago

ok after looking at your documentation again, I realized I was over complicating this so I did this instead:

  it('should update theme through subscription in init', (done: DoneFn) => {
    const themeStub: Subject<IAppTheme> = MockNgRedux.getSelectorStub<IAppTheme, IAppTheme>('theme');
    themeStub.next(THEME_INIT_STATE);
    themeStub.complete();
    component.theme$.subscribe((actual: IAppTheme) => {
      expect(component.theme).toBe('default');
      done();
    });
  });

but I still don't understand why I can't just get this from my native store using like my app does every time it runs? do I need to run configureStore or include my StoreModule? I tried including my store module before but it had problems with my encryption/decryption transforms