question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Snapshot testing agains fixture triggers an error

See original GitHub issue

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.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:12
  • Comments:12 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
mhamel06commented, Feb 27, 2019

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"
  ]
1reaction
thymikeecommented, Nov 19, 2018

Not quite. cc @ahnpnl

Read more comments on GitHub >

github_iconTop Results From Across the Web

Snapshot Testing - Jest
A typical snapshot test case renders a UI component, takes a snapshot, then compares it to a reference snapshot file stored alongside the...
Read more >
Effective Snapshot Testing - Kent C. Dodds
Snapshot testing can be useless, or super useful. Your choice. Let's talk about how to make them useful.
Read more >
Jest Snapshots: The “Joker” Among Today's JavaScript ...
Throughout this article, I am going to share my personal experience with snapshot tests while taking a closer look at its up- and...
Read more >
How to unit test a component that depends on parameters ...
The simplest way to do this is to just use the useValue attribute and provide an Observable of the value you want to...
Read more >
NEWS
Once activated, snapshots will now use rlang to print error and warning ... to basic errors, which causes spurious snapshot changes when testing...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found