Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Test fails if executed independently '__ngContext__={[Function Number]}' vs '__ngContext__="0"' #3811

Closed
jones1008 opened this issue Oct 12, 2022 · 7 comments · Fixed by #3830
Assignees
Labels
bug Something isn't working released v14.3.0

Comments

@jones1008
Copy link

Description of the bug

from https://stackoverflow.com/q/73307975/7987318:

I'm currently facing a strange behavior on my Angular (14) shallow rendering snapshots in unit tests (Jest 28).

Sometimes my snapshot tests are failing, depending if I run them individually or as bundle. The reason of failure is the difference between ngContext={[Function Number]} and ngContext="0".

// hello.component.ts
import {Component, Input} from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>`
})
export class HelloComponent  {
  @Input()
  name: string;
}
// hello.component.spec.ts
describe('HelloComponent', () => {
  beforeEach(() => {
    return MockBuilder(HelloComponent, AppModule);
  });

  it('should render component correctly with Joe', () => {
    const fixture = MockRender(HelloComponent, {name: 'Joe'});
    expect(fixture).toMatchSnapshot()
  });

  it('should render component correctly with other name', () => {
    const fixture = MockRender(HelloComponent, {name: 'Jane'});
    expect(fixture).toMatchSnapshot()
  });
});

An example of the bug

reproduction steps

First clone my reproduction repo: https://github.com/jones1008/ng-mocks-snapshot-test-bug

To reproduce the bug follow these steps:

npm install
npm run test
npm run single-test-fail

See that when running npm run test the tests pass, and when running npm run single-test-fail the test fails with the following error:

 FAIL  src/app/components/hello.component.spec.ts
  HelloComponent
    ✕ should render component correctly with other name (66 ms)
    ○ skipped should render component correctly with Joe

  ● HelloComponent › should render component correctly with other name

    expect(received).toMatchSnapshot()

    Snapshot name: `HelloComponent should render component correctly with other name 1`

    - Snapshot  - 1
    + Received  + 1

    @@ -1,7 +1,7 @@
      <mock-render
    -   __ngContext__={[Function Number]}
    +   __ngContext__="0"
      >
        <hello>
          <h1>
            Hello Jane!
          </h1>

      15 |   it('should render component correctly with other name', () => {
      16 |     const fixture = MockRender(HelloComponent, {name: 'Jane'});
    > 17 |     expect(fixture).toMatchSnapshot()
         |                     ^
      18 |   });
      19 | });
      20 |

      at src/app/components/hello.component.spec.ts:17:21

Notes:

  • npm run single-test-fail executes jest -t 'HelloComponent should render component correctly with other name' and therefore the second test in the hello-component.spec.ts file
  • npm run single-test-fail executes jest -t 'HelloComponent should render component correctly with Joe' and therefore the first test in the hello-component.spec.ts file. Strangely this test passes!
  • I couldn't make a StackBlitz because I was getting some StackBlitz-related error when executing npm run test
@jones1008 jones1008 added the bug Something isn't working label Oct 12, 2022
@satanTime
Copy link
Member

Hi @jones1008,

thank you for the report.

However, it looks like an issue in Angular or jest, but not in ng-mocks.
The next test without ng-mocks fails in the same way:

import {HelloComponent} from "./hello.component";
import {TestBed} from "@angular/core/testing";

describe('HelloComponent', () => {
  beforeEach(() => TestBed.configureTestingModule({
    declarations: [HelloComponent],
  }).compileComponents());

  it('should render component correctly with Joe', () => {
    const fixture = TestBed.createComponent(HelloComponent);
    fixture.componentInstance.name = 'Joe';
    fixture.detectChanges();
    expect(fixture).toMatchSnapshot()
  });

  it('should render component correctly with other name', () => {
    const fixture = TestBed.createComponent(HelloComponent);
    fixture.componentInstance.name = 'Jane';
    fixture.detectChanges();
    expect(fixture).toMatchSnapshot()
  });
});

It looks like, the very first call of TestBed.createComponent uses a pure number, whereas the second and following use it as a Number object.

I would suggest to report the issue to Angular / jest, not sure which of them convert the number to an object.

@satanTime
Copy link
Member

satanTime commented Oct 13, 2022

I assume the problem is that in their code they detect 0 as false and don't execute the code which converts the primitive to an object. and 2nd and other tests which have context 1+, are detected as true and the conversion is happening for them.

I would expect that 0 should also be processed as 1 and others, it's just the index of the current context.

@satanTime
Copy link
Member

It looks like, I found a way to remove __ngContext__ from the final snapshot.

Could you check if it works well in your project?
The build: ng-mocks.zip

@jones1008
Copy link
Author

@satanTime Yes this works!

Does it make sense to ship this fix? Do we need __ngContext__ in our snapshot files? Is it maybe even good if we remove it?

Also when you ship this, all the snapshot tests that were setup with ng-mocks will fail. So is this a breaking change?

@satanTime
Copy link
Member

Nice! I'm glad to hear that.

I wouldn't expect a need of __ngContext__, it's an internal attribute for angular core and its value shouldn't influence on your tests.

I'll ship it as it is with a note that __ngContext__ will be removed from snapshots and it might require to update them.

@jones1008
Copy link
Author

Great! Thanks for the quick answers and fix!

satanTime added a commit to satanTime/ng-mocks that referenced this issue Oct 13, 2022
…te anymore help-me-mom#3811

NOTE: If you use jest snapshots it might require to update them and remove the `__ngContext__` attribute from `mock-render` nodes.
satanTime added a commit to satanTime/ng-mocks that referenced this issue Oct 13, 2022
…te anymore help-me-mom#3811

NOTE: If you use jest snapshots it might require to update them and remove the `__ngContext__` attribute from `mock-render` nodes.
@satanTime
Copy link
Member

v14.3.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released v14.3.0
Projects
None yet
2 participants