ngxs-labs / select-snapshot

🌊 Flexibile decorator that allows to get a snapshot of the state
MIT License
42 stars 4 forks source link

Unit test: store.reset() has not effect in v3.0.0 #116

Open XavierDupessey opened 2 years ago

XavierDupessey commented 2 years ago

I'm submitting a...


[x] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => https://github.com/ngxs/store/blob/master/CONTRIBUTING.md
[ ] Other... Please describe:

Current behavior

I updated @ngxs-labs/select-snapshot from 1.2.0 to 3.0.0. I noticed a change in unit tests:

Let's take as an example this very simple component that uses @SelectSnapshot():

// sample.component.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { AccessSelectors } from '@app/shared/access/access.selectors';
import { Access } from '@app/shared/clients/audience-experience-api.client';
import { SelectSnapshot } from '@ngxs-labs/select-snapshot';

@Component({
  template: '',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SampleComponent {
  @SelectSnapshot(AccessSelectors.access) readonly access!: Set<Access>;

  targetMethod(): void {
    if (this.access.has(Access.ViewBudget)) {
      console.log('User has access');
    } else {
      console.log('User has NOT access');
    }
  }
}

And test it:

// sample.component.spec.ts
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { ExceptionService } from '@app/shared/exception/exception.service';
import { ExceptionServiceMock } from '@app/shared/exception/exception.service.mock';
import { NgxsSelectSnapshotModule } from '@ngxs-labs/select-snapshot';
import { NgxsModule, Store } from '@ngxs/store';
import { ngxsConfig } from '@testing/external-dependencies/ngxs-config';
import { noop } from 'lodash';
import { SampleComponent } from './sample.component';
import { AccessState } from './shared/access/access.state';
import { Access } from './shared/clients/audience-experience-api.client';

describe('SampleComponent', () => {
  let component: SampleComponent;
  let store: Store;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [SampleComponent],
      imports: [HttpClientTestingModule, NgxsSelectSnapshotModule, NgxsModule.forRoot([AccessState], ngxsConfig)],
      providers: [{ provide: ExceptionService, useClass: ExceptionServiceMock }],
    });

    component = TestBed.createComponent(SampleComponent).componentInstance;
    store = TestBed.inject(Store);
  });

  afterEach(() => jest.clearAllMocks());

  describe('targetMethod', () => {
    it('should log if access', () => {
      // Arrange
      store.reset({ access: { allAccess: new Set([Access.ViewBudget]) } });
      jest.spyOn(console, 'log').mockImplementation(noop);

      // Act
      component.targetMethod();

      // Assert
      expect(console.log).toHaveBeenCalledTimes(1);
      expect(console.log).toHaveBeenCalledWith('User has access');
    });

    it('should log if NO access', () => {
      // Arrange
      store.reset({ access: { allAccess: new Set() } });
      jest.spyOn(console, 'log').mockImplementation(noop);

      // Act
      component.targetMethod();

      // Assert
      expect(console.log).toHaveBeenCalledTimes(1);
      expect(console.log).toHaveBeenCalledWith('User has NOT access');
    });
  });
});

In the test, I use store.reset() to change the content of the state.

With @ngxs-labs/select-snapshot v1.2.0, the tests pass. With v3.0.0, they fail:

 FAIL  src/app/sample.component.spec.ts
  SampleComponent
    targetMethod
      √ should log if access (109 ms)
      × should log if NO access (30 ms)

  ● SampleComponent › targetMethod › should log if NO access

    expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: "User has NOT access"
    Received: "User has access"

    Number of calls: 1

      52 |       // Assert
      53 |       expect(console.log).toHaveBeenCalledTimes(1);
    > 54 |       expect(console.log).toHaveBeenCalledWith('User has NOT access');
         |                           ^
      55 |     });
      56 |   });
      57 | });

      at it (src/app/sample.component.spec.ts:54:27)

I tried to call TestBed.createComponent() after store.reset() and to call detectChanges() on the component fixture, without success.

Is it a bug or I am missing something?

Environment

Libs:
- @angular/core version: 11.2.14
- @ngxs/store version: 3.7.3
vanmxpx commented 1 year ago

Faces the same problem. Found that this change on line breaks behavior with TestBed modules. Pull request #105 It caches first injected Store when TestBed creates new Store in every test cycle. So you get the values from the past store.

VerzCar commented 1 year ago

Can someone please approve the open PR or otherwise show some workaround?

rbeier commented 11 months ago

+1

faskan commented 10 months ago

+1

stockmind commented 2 months ago

Stumbled upon this issue myself yesterday. Had to rely on jest.spyOn to override the selector. Can https://github.com/ngxs-labs/select-snapshot/pull/154 be reviewed and merged as it apparently fix the issue? @arturovt @vanmxpx i see https://github.com/ngxs-labs/select-snapshot/pull/152 is still open, can it be closed to avoid confusion?

markwhitfeld commented 2 months ago

I have merged PR #154. @arturovt could you do a release for this?