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

Snapshot testing agains fixture triggers an error #202

Closed
blackholegalaxy opened this issue Nov 6, 2018 · 12 comments
Closed

Snapshot testing agains fixture triggers an error #202

blackholegalaxy opened this issue Nov 6, 2018 · 12 comments

Comments

@blackholegalaxy
Copy link
Contributor

blackholegalaxy commented Nov 6, 2018

When snapshot testing a component, we encountered an error:

GlobalLoaderComponent › snaps
    TypeError: Method get TypedArray.prototype.length called on incompatible receiver [object Object]
        at Uint8Array.get length [as length] (<anonymous>)

Tested component

global-loader.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'global-loader',
  template: `
    <div class="slds-spinner_container slds-is-fixed">
      <div role="status" class="slds-spinner slds-spinner_medium">
        <span class="slds-assistive-text">{{'common.loading' | translate}}</span>
        <div class="slds-spinner__dot-a"></div>
        <div class="slds-spinner__dot-b"></div>
      </div>
    </div>
  `,
})
export class GlobalLoaderComponent {
  @Input() public firstTime = true;
}

Testing files

translate-pipe.mock

import { PipeTransform, Pipe } from '@angular/core';

@Pipe({ name: 'translate' })
export class TranslatePipeMock implements PipeTransform {
  public transform(value: string, ...params: any[]): string {
    let translation: string = 'translated ' + value;

    if (params && params.length > 0) {
      translation += ' ' + JSON.stringify(params[0]);
    }

    return translation;
  }
}

global-loader.component.spec.ts

import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import {
  async,
  ComponentFixture,
  TestBed
} from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';

import { GlobalLoaderComponent } from './global-loader.component';
import { TranslatePipeMock } from './translate-pipe.mock';

type CompilerOptions = Partial<{
  providers: any[];
  useJit: boolean;
  preserveWhitespaces: boolean;
}>;
export type ConfigureFn = (testBed: typeof TestBed) => void;

export const configureTests = (
  configure: ConfigureFn,
  compilerOptions: CompilerOptions = {}
) => {
  const compilerConfig: CompilerOptions = {
    preserveWhitespaces: false,
    ...compilerOptions
  };

  const configuredTestBed = TestBed.configureCompiler(compilerConfig);

  configure(configuredTestBed);

  return configuredTestBed.compileComponents().then(() => configuredTestBed);
};

describe('GlobalLoaderComponent', () => {
  let fixture: ComponentFixture<GlobalLoaderComponent>;
  let component: GlobalLoaderComponent;

  beforeEach(async(() => {
    const configure: ConfigureFn = testBed => {
      testBed.configureTestingModule({
        declarations: [GlobalLoaderComponent, TranslatePipeMock],
        imports: [NoopAnimationsModule],
        schemas: [NO_ERRORS_SCHEMA]
      });
    };

    configureTests(configure).then(testBed => {
      fixture = testBed.createComponent(GlobalLoaderComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    });
  }));

  it('should create the app', async(() => {
    const app = component;
    expect(app).toBeTruthy();
  }));

  it('snaps', () => {
    expect(fixture).toMatchSnapshot();
  });
});

Sometimes it even produces a memory error and stops jest --watch

<--- Last few GCs --->

[7594:0x103000000]  1413180 ms: Mark-sweep 1395.1 (1425.4) -> 1394.8 (1425.9) MB, 1548.5 / 0.1 ms  (average mu = 0.058, current mu = 0.003) allocation failure scavenge might not succeed
[7594:0x103000000]  1414548 ms: Mark-sweep 1395.4 (1425.9) -> 1395.0 (1425.9) MB, 1362.3 / 0.1 ms  (average mu = 0.031, current mu = 0.004) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x202b6b75c01d]
    1: StubFrame [pc: 0x202b6b75d390]
Security context: 0x36b46351e681 <JSObject>
    2: printComplexValue(aka printComplexValue) [0x36b4073ba8f9] [/Users/Dev/project/node_modules/pretty-format/build/index.js:~176] [pc=0x202b6bbc0ec0](this=0x36b4333826f1 <undefined>,val=0x36b49a4f42d9 <Module map = 0x36b496e4f7d9>,config=0x36b43d8b1ab9 <Object map = 0x36b470eb4451>,indentation=0x36b4...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x10003a08d node::Abort() [/usr/local/bin/node]
 2: 0x10003a297 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
 3: 0x1001d2455 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 4: 0x10059d6d2 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
 5: 0x1005a01a5 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/usr/local/bin/node]
 6: 0x10059c04f v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
 7: 0x10059a224 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
 8: 0x1005a6aac v8::internal::Heap::AllocateRawWithLigthRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
 9: 0x1005a6b2f v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
10: 0x1005764b4 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
11: 0x1007fe234 v8::internal::Runtime_AllocateInNewSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
12: 0x202b6b75c01d
sh: line 1:  7594 Abort trap: 6           jest --watch

Useful information

  • Testing against expect(fixture.debugElement.nativeElement).toMatchSnapshot(); works
  • Testing agains expect(component).toMatchSnapshot(); works
  • Removing Translate pipe in template and translate pipe mock doesn't work more

Dependencies

"dependencies": {
    "@agm/core": "1.0.0-beta.5",
    "@angular/animations": "6.1.10",
    "@angular/cdk": "6.4.7",
    "@angular/common": "6.1.10",
    "@angular/compiler": "6.1.10",
    "@angular/core": "6.1.10",
    "@angular/forms": "6.1.10",
    "@angular/http": "6.1.10",
    "@angular/material": "6.4.7",
    "@angular/material-moment-adapter": "6.4.7",
    "@angular/platform-browser": "6.1.10",
    "@angular/platform-browser-dynamic": "6.1.10",
    "@angular/router": "6.1.10",
    "@ngrx/effects": "6.1.1",
    "@ngrx/router-store": "6.1.1",
    "@ngrx/store": "6.1.1",
    "@ngrx/store-devtools": "6.1.1",
    "@ngx-translate/core": "10.0.2",
    "@ngx-translate/http-loader": "3.0.1",
    "@ngx-utils/cookies": "3.0.2",
    "@salesforce-ux/design-system": "2.6.2",
    "@swimlane/ngx-charts": "9.0.0",
    "classlist.js": "1.1.20150312",
    "core-js": "2.5.7",
    "fast-luhn": "1.0.3",
    "file-saver": "1.3.8",
    "formdata-polyfill": "3.0.12",
    "hammerjs": "^2.0.8",
    "lodash": "4.17.11",
    "moment": "2.22.2",
    "ng-lightning": "2.0.1",
    "ngx-cookie-service": "1.0.10",
    "ngx-extended-pdf-viewer": "0.9.4",
    "ngx-infinite-scroll": "6.0.1",
    "ngx-moment": "3.1.0",
    "primeicons": "1.0.0",
    "primeng": "6.1.5",
    "qs": "6.5.2",
    "rxjs": "6.2.2",
    "rxjs-compat": "6.2.2",
    "sanitize.css": "8.0.0",
    "svg-sprite": "1.5.0",
    "svg4everybody": "2.1.9",
    "web-animations-js": "2.3.1",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "0.8.6",
    "@angular-devkit/build-ng-packagr": "0.8.6",
    "@angular/cli": "6.2.6",
    "@angular/compiler-cli": "6.1.10",
    "@angular/language-service": "6.1.10",
    "@angularclass/hmr": "2.1.3",
    "@types/googlemaps": "3.30.15",
    "@types/jest": "23.3.5",
    "@types/node": "8.10.17",
    "babel-jest": "23.6.0",
    "babel-preset-env": "1.7.0",
    "codelyzer": "4.4.4",
    "concurrently": "4.0.1",
    "cross-env": "5.2.0",
    "cypress": "3.1.0",
    "death": "1.1.0",
    "gulp": "3.9.1",
    "gulp-inline-source": "3.2.0",
    "gulp-zip": "4.2.0",
    "jest": "23.6.0",
    "jest-junit": "5.2.0",
    "jest-preset-angular": "6.0.1",
    "minimist": "1.2.0",
    "ng-packagr": "4.2.0",
    "ngrx-store-freeze": "0.2.4",
    "request": "2.88.0",
    "ts-node": "7.0.1",
    "tslib": "1.9.3",
    "tslint": "5.11.0",
    "typescript": "2.7.2"
  },

We tried to add Prettier and use toMatchInlineSnapshot without more success.

@blackholegalaxy
Copy link
Contributor Author

@thymikee any thoughts on that?

@thymikee
Copy link
Owner

Not quite. cc @ahnpnl

@ahnpnl
Copy link
Collaborator

ahnpnl commented Nov 22, 2018

hmm I never experience this issue. Can you try to use

TranslateModule.forRoot({
          loader: { provide: TranslateLoader, useClass: FakeLoader },
        }),

with FakeLoader is

export class FakeLoader implements TranslateLoader {
  getTranslation(lang) {
    return of(appTranslations);
  }
}

appTranslations is your .json file

@blackholegalaxy
Copy link
Contributor Author

As I said before: Removing Translate pipe in template and translate pipe mock doesn't work more. Your loader doesn't change anything.

@mhamel06
Copy link

I'm also running into the same issue. If it helps, I am using NX and the @nrwl/builders:jest builder. snapshot testing of component and native element also both work, but it hangs and runs out of memory trying to snapshot test a fixture.

@wtho
Copy link
Collaborator

wtho commented Feb 27, 2019

Does it also occur, when just that one test case is run?

If so, a minimal reproduction would be very helpful. It can also be a minimal nrwl project. If the component is quite big, try to cut it down to an error reproducing, but minimal size.

Does it only happen in watch mode?

@mhamel06
Copy link

I think I found a solution, at least for my case. After running my tests with the debug flag, I noticed the snapshotSerializers array was empty. Adding the following to my jest config solved the issue.

"snapshotSerializers": [
    "jest-preset-angular/AngularSnapshotSerializer.js",
    "jest-preset-angular/HTMLCommentSerializer.js"
  ]

@wtho
Copy link
Collaborator

wtho commented Feb 27, 2019

The jest config at the workspace root should not contain snapshot serializers, but the one for the app level should have the serializer array you posted by default. Just verified it with a newly generated nrwl app.

So it seems you had a different issue.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Sep 12, 2019

@blackholegalaxy have you figured out the solution for your issue ? Does it still occur ?

@ahnpnl ahnpnl added the 🤷‍♂️ Needs More Info waiting for more information from author of the issue label Sep 12, 2019
@Lonli-Lokli
Copy link

We observe OutOfMem in angular while using toMatchSnapshot() on a page.

Can it be related to jestjs/jest#9980 ?

@ahnpnl
Copy link
Collaborator

ahnpnl commented Nov 11, 2020

can be, toMatchSnapshot is jest feature

@ahnpnl
Copy link
Collaborator

ahnpnl commented Apr 30, 2021

Close as cannot reproduce the issue without a repo. If you are still having the issue, please provide a repo.

@ahnpnl ahnpnl closed this as completed Apr 30, 2021
@ahnpnl ahnpnl added closed due to inactivity - can be reopened later and removed 🤷‍♂️ Needs More Info waiting for more information from author of the issue labels Apr 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants