Giter VIP home page Giter VIP logo

shallow-render's People

Contributors

attrobit avatar dependabot[bot] avatar develobrix avatar duck-nukem avatar freddysilber avatar getsaf avatar ike18t avatar kekmeow avatar kylecannon avatar maartentibau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

shallow-render's Issues

ModuleWithProviders is not generic error

I have an Angular 5-based module (5.2 to be precise) and when I use the latest version (6.2.0) I get the following error message during the test run:

$ yarn test
yarn run v1.7.0
$ ng test
 10% building modules 1/1 modules 0 active16 10 2018 13:38:59.629:WARN [karma]: No captured browser, open http://localhost:9876/
16 10 2018 13:38:59.643:INFO [karma]: Karma v3.0.0 server started at http://0.0.0.0:9876/
16 10 2018 13:38:59.645:INFO [launcher]: Launching browser ChromeHeadless with unlimited concurrency
16 10 2018 13:38:59.651:INFO [launcher]: Starting browser ChromeHeadless
[./src/polyfills.ts] ./src/polyfills.ts 0 bytes {polyfills} [built]
   [0] multi ./src/polyfills.ts 28 bytes {polyfills} [built]
[./src/test.ts] ./src/test.ts 0 bytes {main} [built]


ERROR in node_modules/shallow-render/dist/lib/models/test-setup.d.ts(9,50): error TS2315: Type 'ModuleWithProviders' is not generic.
node_modules/shallow-render/dist/lib/models/test-setup.d.ts(9,88): error TS2315: Type 'ModuleWithProviders' is not generic.

If I edit the test-setup.d.ts file at line 9 and change it (removing the <any> following ModuleWithProviders):

readonly moduleReplacements: Map<Type<any> | ModuleWithProviders, Type<any> | ModuleWithProviders>;

compilation now completes. I tried stepping back to v6.1.3 but the error still occurred.

Is there a version I could use so that I didn't have to manually edit the file (worried about deploying this to my co-workers so they can start writing tests using the shallow-render package).

I'm just forging into the world of testing frontend code involving Angular. Happy to provide additional info if I haven't provide sufficient details. Trying to get testing to work first then consider migrations to Angular 6 and beyond if possible.

Warning with angular6

Thanks for the awesome library.

I get this error when using shallow-render with angular v6:

npm WARN @angular/[email protected] requires a peer of rxjs@^5.5.0 but none is installed. You must install peer dependencies yourself.
npm WARN @angular/[email protected] requires a peer of rxjs@^5.5.0 but none is installed. You must install peer dependencies yourself.
npm WARN @angular/[email protected] requires a peer of rxjs@^5.5.0 but none is installed. You must install peer dependencies yourself.

I am using shallow-render version 0.13.0

Incompatiblity with hammerjs components

I haven't gotten to the root of this one, but my normal Angular tests are passing fine, but those that leverage shallow-render are failing now that I have added some material components that support hammerjs.

See https://material.angular.io/guide/getting-started#step-5-gesture-support

When running in the browser, the console merely states that hammerjs is needed to support some gestures. I haven't added hammerjs to the project yet.

Instead of seeing the warning in my tests, I see

TypeError: Cannot read property 'indexOf' of undefined

      at HammerGesturesPlugin.isCustomEvent (../packages/platform-browser/src/dom/events/hammer_gestures.ts:236:74)
      at HammerGesturesPlugin.supports (../packages/platform-browser/src/dom/events/hammer_gestures.ts:163:71)
      at EventManager._findPluginFor (../packages/platform-browser/src/dom/events/event_manager.ts:83:18)
      at EventManager.addEventListener (../packages/platform-browser/src/dom/events/event_manager.ts:50:25)
      at DefaultDomRenderer2.listen (../packages/platform-browser/src/dom/dom_renderer.ts:218:42)
      at BaseAnimationRenderer.listen (../../packages/platform-browser/animations/src/animation_renderer.ts:194:26)

So it appears that some hammer placeholder module is being mocked when it shouldn't be.

Cannot Seem to .replaceModule() when using .forRoot() type modules

The "component with routing" example you have on Stackblitz isn't quite right.

In a real component/app, I would be using RouterModule.forRoot() and not simply RouterModule.

When I add that to the example, it breaks.

Here's my Stackblitz fork.

I immediately get the following error:

Error: Unexpected value '[object Object]' imported by the module 'DynamicTestModule'. Please add a @NgModule annotation.

I thought it might work similar to .dontMock() in that you need to save a reference to var = Module.forRoot() and put var in .dontMock(var). That didn't work either. I get the error:

TypeError: this.appInits[i] is not a function

I'm guessing that this means the .replaceModule() line is ignored altogether.

Do I also need to use .provide() or something?

Also, is there a way to send you a few dollars/btc for all the work you've done? It's been very helpful for me at work.

Great testbed!

Congrats with such an intuitive package.

Request: Could we have a shallow-cli to generate the boiler-plate. This would even reduce the amount of code we write.

Regards

How to use with animations?

First off, thank you so much for the library. I am having an issue when I have animations triggers though with using this library. Example:

@Component({
    selector: 'app-applications-grid',
    templateUrl: './applications-grid.component.html',
    styleUrls: ['./applications-grid.component.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush,
    animations: [
        trigger('applicationAnimation', [
            transition('* => *', [
                query(
                    ':enter',
                    [
                        style({ opacity: 0, transform: 'translateY(-100px)' }),
                        stagger(50, [animate('400ms ease-out', style({ opacity: 1, transform: 'none' }))]),
                    ],
                    { optional: true }
                ),
            ]),
        ]),
    ],
})
export class ApplicationsGridComponent {
    @Input() applications: ApplicationDetail[];

    trackByFn(idx, { name }: ApplicationDetail) {
        return name;
    }
}

with a template of

<section class="application-grid" [@applicationAnimation]="applications?.length">
    <app-applications-grid-item *ngFor="let application of applications; trackBy: trackByFn" [item]="application"></app-applications-grid-item>
</section>

This error is thrown:

HeadlessChrome 0.0.0 (Linux 0.0.0) ApplicationsGridComponent should create FAILED
	Error: Found the synthetic property @applicationAnimation. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.
	    at checkNoSyntheticProp node_modules/@angular/platform-browser/fesm5/platform-browser.js:1296:1)
	    at EmulatedEncapsulationDomRenderer2.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.DefaultDomRenderer2.setProperty node_modules/@angular/platform-browser/fesm5/platform-browser.js:1280:1)
	    at DebugRenderer2.push../node_modules/@angular/core/fesm5/core.js.DebugRenderer2.setProperty node_modules/@angular/core/fesm5/core.js:11207:1)
	    at setElementProperty node_modules/@angular/core/fesm5/core.js:7966:1)
	    at checkAndUpdateElementValue node_modules/@angular/core/fesm5/core.js:7917:1)
	    at checkAndUpdateElementInline node_modules/@angular/core/fesm5/core.js:7864:1)
	    at checkAndUpdateNodeInline node_modules/@angular/core/fesm5/core.js:10205:1)
	    at checkAndUpdateNode node_modules/@angular/core/fesm5/core.js:10171:1)
	    at debugCheckAndUpdateNode node_modules/@angular/core/fesm5/core.js:10804:1)
	    at debugCheckRenderNodeFn node_modules/@angular/core/fesm5/core.js:10790:1)
HeadlessChrome 0.0.0 (Linux 0.0.0) ApplicationsGridComponent should create FAILED
	Error: Found the synthetic property @applicationAnimation. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.
	    at checkNoSyntheticProp node_modules/@angular/platform-browser/fesm5/platform-browser.js:1296:1)
	    at EmulatedEncapsulationDomRenderer2.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.DefaultDomRenderer2.setProperty node_modules/@angular/platform-browser/fesm5/platform-browser.js:1280:1)
	    at DebugRenderer2.push../node_modules/@angular/core/fesm5/core.js.DebugRenderer2.setProperty node_modules/@angular/core/fesm5/core.js:11207:1)
	    at setElementProperty node_modules/@angular/core/fesm5/core.js:7966:1)
	    at checkAndUpdateElementValue node_modules/@angular/core/fesm5/core.js:7917:1)
	    at checkAndUpdateElementInline node_modules/@angular/core/fesm5/core.js:7864:1)
	    at checkAndUpdateNodeInline node_modules/@angular/core/fesm5/core.js:10205:1)
	    at checkAndUpdateNode node_modules/@angular/core/fesm5/core.js:10171:1)
	    at debugCheckAndUpdateNode node_modules/@angular/core/fesm5/core.js:10804:1)

If I create a testing module that imports the NoopAnimationsModule,

@NgModule({
    imports: [NoopAnimationsModule, ApplicationsModule],
    exports: [ApplicationsModule],
})
export class ApplicationsTestModule {
}

describe('ApplicationsGridComponent', () => {
    let shallow: Shallow<ApplicationsGridComponent>;

    beforeEach(() => {
        shallow = new Shallow(ApplicationsGridComponent, ApplicationsTestModule);
    });

    const applications = mockApps;

    it('should create', async () => {
        const res = await shallow.render(
            `<app-applications-grid [applications]="applications"></app-applications-grid>`,
            { bind: { applications } },
        );
    });
});

the test fails with the following error:

HeadlessChrome 0.0.0 (Linux 0.0.0) ApplicationsGridComponent should create FAILED
	TypeError: this.delegate.createRenderer is not a function
	    at DebugRendererFactory2.push../node_modules/@angular/core/fesm5/core.js.DebugRendererFactory2.createRenderer node_modules/@angular/core/fesm5/core.js:11067:1)
	    at createRootData node_modules/@angular/core/fesm5/core.js:10538:1)
	    at Object.debugCreateRootView [as createRootView] node_modules/@angular/core/fesm5/core.js:10531:1)
	    at ComponentFactory_.push../node_modules/@angular/core/fesm5/core.js.ComponentFactory_.create node_modules/@angular/core/fesm5/core.js:8361:1)
	    at initComponent node_modules/@angular/core/fesm5/testing.js:1163:1)
	    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke node_modules/zone.js/dist/zone.js:388:1)
	    at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke node_modules/zone.js/dist/zone-testing.js:288:1)
	    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke node_modules/zone.js/dist/zone.js:387:1)
	    at Object.onInvoke node_modules/@angular/core/fesm5/core.js:3671:1)
	    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke node_modules/zone.js/dist/zone.js:38HeadlessChrome 0.0.0 (Linux 0.0.0): Executed 1 of 125 (1 FAILED) (skipped 124) ERROR (0.096 secs / 0.072 secs)

Any ideas?

Unable to mock component methods

I apologize if I'm just misusing the library. Here is a test case demonstrating the failure: https://stackblitz.com/edit/shallow-render-jz9ubo?file=examples/multiple-components.spec.ts

If I have a child component and I need to mock out a method that is called (getThing() in the code below):

class AwesomeListComponent {
  @Input() topItem: string;
  @Input() boldTopItem = false;
  @ViewChild('listContainer') listContainer: ListContainerComponent;

  ngAfterViewInit(): void {
    console.log(this.listContainer.getThing())
  }

}

I would expect to be able to mock it out by: .mock(ListContainerComponent, {getThing : () => 'Test Thing'});

However I get TypeError: this.listContainer.getThing is not a function

"TypeError: this._moduleRef.injector.get(...).runInitializers is not a function" when using BrowserModule.withServerTransition

Test run fails with the following error when using Angular Universal with an import BrowserModule.withServerTransition({ appId: 'serverApp' }) :

TypeError: this._moduleRef.injector.get(...).runInitializers is not a function
            at TestBedViewEngine.push.../../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine._initIfNeeded (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/@angular/core/fesm5/testing.js?:1702:59)
            at TestBedViewEngine.push.../../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.createComponent (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/@angular/core/fesm5/testing.js?:1861:1)
            at Function.push.../../node_modules/@angular/core/fesm5/testing.js.TestBedViewEngine.createComponent (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/@angular/core/fesm5/testing.js?:1554:1)
            at Renderer.<anonymous> (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/shallow-render/dist/lib/models/renderer.js?:149:1)
            at step (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/shallow-render/dist/lib/models/renderer.js?:50:1)
            at Object.next (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/shallow-render/dist/lib/models/renderer.js?:31:45)
            at fulfilled (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/shallow-render/dist/lib/models/renderer.js?:22:42)
            at ZoneDelegate.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/zone.js/dist/zone.js?:388:1)
            at ProxyZoneSpec.push.../../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/C:/GIT/game-monorepo/game/node_modules/zone.js/dist/zone-testing.js?:288:1)

Stackblitz example https://stackblitz.com/edit/github-ccz1rn?file=examples%2Fmodule-with-server-transition.spec.ts

Please do let me know if you need any help with the investigation.

Should module mocks be fully recursive?

The theory here is that when mocking modules, we may not need to mock ALL dependencies all the way down. Maybe we can get away with mocking:

  • The full test-module
  • Only the exports[] of any other imported module

If this pans out, it could seriously cut down on how many modules/services/components are mocked for each test.

Property bindings don't work?

const r = shallow.dontMock(ReactiveFormsModule)
	.render(
		'<example [something]="data"></example>',
		{ bind: { data: { type: 'number' } } },
	);

const input = r.find('input').nativeElement;

// works fine
expect(input.getAttribute('ng-reflect-type'))
	.toBe('number'); // true

// doesn't work
expect(input.getAttribute('type'))
	.toBe('number'); // Expected null to be 'number


// elsewhere
@Component({
	selector: 'example',
	template: `<input [type]="data.type">`,
})
export class ExampleComponent {
	@Input() something: IData;
}

Am I forgetting some dependency? Why is <input type="number"> never happening?

find: Could not find the element you were looking for

Hi, thanks for a great lib, I really considering to use it for my projects. Now to the actual question:

when I try to query some element in my test:

expect(find('p')).toBeFalsy();

test throws an error:

context.js:243 Unhandled Promise rejection: Could not find the element you were looking for. Your test tried to access the 'prototype' property on a QueryResult but your query had no results. ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Could not find the element you were looking for. Your test tried to access the 'prototype' property on a QueryResult but your query had no results.
    at new NoMatchesError (VM40572 query-match.js:16)
    at throwErrorIfNotOneMatch (VM40572 query-match.js:31)
    at Object.getPrototypeOf (VM40572 query-match.js:71)
    at Function.[Symbol.hasInstance] (<anonymous>)
    at Proxy.Object.toString (VM267 zone.js:1466)
    at exports.instanceOf (VM23 context.js:90)
    at ContextKarma.stringify (VM23 context.js:39)
    at ContextKarma.log (VM23 context.js:138)

I'm kind of used to do this technique with fixture.debugElement.query to make sure that some elements are not rendered in some cases. Don't you think that throwing an error in #find is a little bit too much? Or I just should stick to using fixture.debugElement.query in this case?

Error when a component in project has no selector

Hi,

I started using shallow-render today, as it seems to perfectly align with how we want to test our Angular application. So far so good, if it weren't for the fact that I currently keep running into the same error that's blocking me from writing tests using shallow-render.

I'm currently testing a really easy component using the following setup:

let shallow: Shallow<OverviewCourseComponent>;

beforeEach(() => {
    shallow = new Shallow(OverviewCourseComponent, UIModule);
});

it('should create', async () => {
    const { instance } = await shallow.render('<overview-course></overview-course>');
    expect(instance).toBeTruthy();
});

I get thrown following error however:

Directive MockOfHeaderPickerComponent has no selector, please add it!

Analysing this error, it seems to originate from this HeaderPickerComponent that is part of ng-zorro-antd, a UI library I use.

As the error specifies: this specific component does not have a selector defined. This specific component is part of an external repository I have no control over, so adding one is not possible.

Is there a way around this issue, or is this a problem with the current implementation of shallow-render? I'm currently using version 6.1.2 in my Angular 6.1.4 project.

Thanks!
Nils

RouterTestingModule

Is there any way to add RouterTestingModule to TestingModule? I see that we can manipulate mocking of components, providers, but nothing about modules.

I'm used to test "href" attribute of anchor elements in my test, plus I would like to test the click event (to expect Router.navigate() to have been called for example).

Ngxs/store @select decorator compatibility

I couldn't test components using @select decorator of ngxs/store, I'm without new ideas how to test it!

if I try to provide store I've got this error:


    SelectFactory not connected to store!

      at LoginComponent.createSelect (node_modules/@ngxs/store/bundles/ng:/@ngxs/store/packages/store/src/select.ts:45:15)
      at LoginComponent.get [as conf] (node_modules/@ngxs/store/bundles/ng:/@ngxs/store/packages/store/src/select.ts:73:1)
      at Object.View_LoginComponent_0._co [as updateDirectives] (ng:/DynamicTestModule/LoginComponent.ngfactory.js:237:31)
      at Object.debugUpdateDirectives [as updateDirectives] (../../../../../execroot/angular/packages/core/src/view/services.ts:384:19)
      at checkAndUpdateView (../../../../../execroot/angular/packages/core/src/view/view.ts:359:12)

If I try to provide store and don't mock it, I've got this one:

  ● LoginComponent Shallow Render β€Ί should log in

    StaticInjectorError(DynamicTestModule)[Store -> StateStream]:
      StaticInjectorError(Platform: core)[Store -> StateStream]:
        NullInjectorError: No provider for StateStream!```

entryComponents missing?

Possibly just doing this wrong, but exactly what is not obvious to me. Maybe it's a bug?

Here's what I have:

////// Module Setup //////
@Directive({
	selector: '[exampleHost]'
})
export class ExampleHostDirective {
	constructor(public viewContainerRef: ViewContainerRef) {}
}

@Component({
	selector: 'example',
	template: '<ng-template exampleHost></ng-template>',
})
export class ExampleContainerComponent implements OnInit {
	constructor(private cfr: ComponentFactoryResolver) {}

	@ViewChild(ExampleHostDirective) cellHost: ExampleHostDirective;
	@Input() data: { component: new () => { data } };
	template: string;

	ngOnInit() {
		const componentFactory = this.cfr.resolveComponentFactory(this.data.component);
		const viewContainerRef = this.cellHost.viewContainerRef;
		viewContainerRef.clear();

		viewContainerRef.createComponent(componentFactory);
	}
}

@Component({
	selector: 'example-two',
	template: '<span>{{biz}}</span>',
})
export class ExampleContainerComponentTwo {
	biz = 'baz';
}

@NgModule({
	imports: [ReactiveFormsModule, MatFormFieldModule],
	declarations: [ExampleContainerComponent, ExampleHostDirective, ExampleContainerComponentTwo],
	entryComponents: [ExampleContainerComponentTwo]
})
class ExampleModule {}
//////////////////////////

describe('component with bindings', () => {
	let shallow: Shallow<ExampleContainerComponent>;

	beforeEach(() => {
		shallow = new Shallow(ExampleContainerComponent, ExampleModule)
			.dontMock(ExampleHostDirective);
	});

	const data = {
		foo: 'bar'
	};

	fit('sets type on an input', async () => {
		const {find} = await shallow.render(
			'<example [data]="data"></example>',
			{ bind: { data: { component: ExampleContainerComponentTwo } } }
		);

		console.log(find('input').nativeElement);
		expect(find('input').nativeElement.getAttribute('type'))
			.toBe('number');
	});
});

My test fails with the error:

Failed: No component factory found for ExampleContainerComponentTwo. Did you add it to @NgModule.entryComponents?

It is in entryComponents though.

nativeElement.disabled always returning false

I created a stackblitz in an attempt to recreate my issue I'm having in a real app. I'm my real app the [disabled] property is always false but I see the ng-reflect-disabled attribute updating to true | false

This is what I have to do in my real app test

function expectSignButtonDisabled(find: any, disabled: boolean) {
    const signButton = find('#sign-button');
    // signButton.nativeElement.disabled always returns false ???
    expect(signButton.attributes['ng-reflect-disabled'] === `${disabled}`).toBe(disabled);
  }

In my stackblitz app it doesn't appear to be responding to my click() which seems odd but I even tried hardcoding [disabled] to be true | false.

Why does .nativeElement.disabled always returning false? I assume I'm missing something...

https://stackblitz.com/edit/shallow-render-r8qh8d?file=examples%2Fcomponent-with-template-var.spec.ts

import { Component, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'
import { Shallow } from 'shallow-render';

////// Module Setup //////
interface Person {
  firstName: string;
  lastName: string;
  birthDate: Date;
}

@Component({
  selector: 'my-comp',
  template: `
    <input type="checkbox" id="cbox" name="cbox" #cbox [(ngModel)]="cbox.selected">
    <button id="btn" [disabled]="!cbox.selected" [innerText]="cbox.selected? 'Submit': 'Disabled'">Submit</button>
  `,
})
class MyComponent {
}

@NgModule({
  imports: [FormsModule],
  declarations: [MyComponent]
})
class MyModule {}
//////////////////////////

describe('component with bindings', () => {
  let shallow: Shallow<MyComponent>;

  beforeEach(() => {
    shallow = new Shallow(MyComponent, MyModule);
  });


  it('button should be disabled, text should say Disabled', async () => {
    const {find, fixture} = await shallow.render(
      '<my-comp></my-comp>'
    );

    let btn = find('#btn');
    let checkbox = find ('#cbox');

    expect(btn.nativeElement.disabled).toBe(true);
    expect(btn.nativeElement.innerText).toBe('Disabled');
  });

  it('button should be enabled, text should say Submit', async () => {
    const {find, fixture} = await shallow.render(
      '<my-comp></my-comp>'
    );

    let checkbox = find('#cbox');
    let btn = find('#btn');

    checkbox.nativeElement.click();
    
    expect(btn.nativeElement.innerText).toBe('Submit');
    expect(btn.nativeElement.disabled).toBeFalsy();
  });
});

[Question] Testing of functions, possible?

First of all, great library. Thanks for the hard work.

Secondly, is it possible to test functions defined in the component class? All the examples/documentation tests against the template. If it is possible, could you please provide a small example?

Create angular schematics for shallow-render

I'd like to propose to add Angular schematics, so when you create a component with Angular CLI, instead of a default spec file, a shallow-render spec file is generated.

Let's say you execute: ng g c app/shallow-component
It would generate the following spec file:

import { ShallowComponentComponent } from './shallow-component.component';
import { AppModule } from './app.module';
import { Shallow } from 'shallow-render/dist';

describe('ShallowComponentComponent', () => {
  let shallow: Shallow<ShallowComponentComponent>;

  beforeEach(() => {
    shallow = new Shallow(ShallowComponentComponent, AppModule);
  });

  it('should create', async () => {
    const { instance } = await shallow.render();
    expect(instance).toBeTruthy();
  });
});

@getsaf If you are interested, I can help with a PR as I have got a working solution already.

Example of using a Mat Dialog?

I looked in the stackblitz example and didn't see any nice example of dealing with dialogs. Think we could get a good example in the stackblitz when you get some time?

How to mock property of dependency?

Can't wrap my head around this. So I have this code:

constructor(private store: FooStore) {
    this.foo= this.store.foo
}

Is it possible to mock what this.store.foo returns?

Button disabled property not updating

Hi,
I've got a simple component, where a button is disabled or enabled on the validation of an input field.
I'm finding that the tests are running in reverse order, and more importantly, nativeElement.disabled is always false, whereas componentInstance.disabled is always true.
This is even after either fixture.detectChanges(); and await fixture.detectChange

Throw an error when a mocked service is not found in the test-module.

It's possible that a user would specify a mock for an injectable that is not contained in the test-module or any of the subsequent module mocks. If this happens, it would be an oversight on the developer's part that they provided a mock for a thing that is not possible to be provided in their module. Shallow should throw an error in this case as a helpful note to the user.

Does shallow-render support ViewChild queries?

Hello,

I have the next component tree:

            AppComponent
                 |
                 |
           ParentComponent
                 |
                 |
            ChildComponent

The ParentComponent has a ViewChild reference to ChildComponent. When i mock ChildComponent by hand in the ParentComponent spec, it renders but never gets the reference to the ViewChild. Is any way to solve this using shallow-render?

If it helps, this repo has an example of the case i explained above: https://github.com/Ivykp/test-viewchild-mock

Thanks!

Using `find` method

Let's say I have a condition rendering in my template. I want to test that conditional rendering. find method throws an error about element not existing Could not find the element you were looking for. Your test tried to access the 'prototype' property on a QueryResult but your query had no results. I either need to wrap that into a try/catch block or in some different way.

Ideally I would like to determine if element exists only by using find method.

Mocking function as dependencies

So I have situation when I use @ngx-translate/i18n-polyfill. It is injected in constructor constructor(private i18n: I18n) {} and then used a function this.i18n({ ... }). Mocking is not working for me since this.i18n returns MockOfI18n object and is not a function.

I've bypassed this by spying upon instance.i18n after the render.

Tests for structural directive fail with "was not found in test template"

First of all, I'd like to thank you for creating such a great library! It already saved us loads of time!

Issue details:

  • When testing structural directives with shallow-render it tests fail with "Error: <DirectiveType> was not found in test template"

Steps to reproduce:

Findings:
I cloned the source code. Exception is thrown in rendering.ts on line 22. It seems that the code on line 19 this.fixture.debugElement.query(By.directive(this._setup.testComponent)); returns a null object.

I'd be happy to help to resolve the issue if you can point to the right direction.

Error: Template parse errors

I get the following error when trying to apply the demo @ https://github.com/getsaf/shallow-render/wiki into my app.

Error: Template parse errors:​​
​​Unexpected closing tag "__MockOfEmptyOutletComponent-selector". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags ("<__MockOfEmptyOutletComponent-selector>[ERROR ->]</__MockOfEmptyOutletComponent-selector>"): @0:39​​

Angular Material Failed: Cannot read property 'indexOf' of undefined

I just want to share the fix to the problem that I've recently encountered when using Angular Material:

Failed: Cannot read property 'indexOf' of undefined

TypeError: Cannot read property 'indexOf' of undefined
at HammerGesturesPlugin.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.HammerGesturesPlugin.isCustomEvent (http://localhost:9876/node_modules/@angular/platform-browser/fesm5/platform-browser.js?:1585:74)

// Remaining of the stack trace....

The error appears when adding one of the modules: MatSliderModule, MatSlideToggleModule or MatTooltipModule

To fix the problem add Shallow.neverMock(HAMMER_GESTURE_CONFIG); to your tests or better to append it to the end of the test.ts file.

Explanation:
Aforementioned modules have the following provider declared as part of the module declaration
{provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig}
As shallow-render mock the implementation, test execution fails. Adding Shallow.neverMock prevents the error.

TwoWay Databinding does not update bindings

Hey there!
First of all, awesome piece of work!

It really does simplify the process of testing angular applications :)

But I have one issue that makes me pulling my hair out of my head:

I've got a component that has a two way binding implemented on in:

@Component({
  selector: 'bc-checkbox',
  templateUrl: './checkbox.component.html',
  styleUrls: ['./checkbox.component.scss'],
})
export class CheckboxComponent {
  private static idCounter: number = 0;

  @Input() public id: string = `bc-checkbox-${++CheckboxComponent.idCounter}`;
  @Input() public disabled: boolean = false;
  @Input() public checked: boolean = false;
  @Output() public checkedChange: EventEmitter<boolean> = new EventEmitter();

  public get checkedValue(): boolean {
    return this.checked;
  }

  public set checkedValue(value: boolean) {
    this.checked = value;
    this.checkedChange.emit(this.checked);
  }

  public change(): void {
    if (this.disabled) {
      return;
    }
    this.checkedValue = !this.checkedValue;
  }
}
<div (click)="change()" class="bc-checkbox">
  <input id="{{id}}" type="checkbox" [disabled]="disabled" [checked]="checkedValue" (change)="change()">
  <label for="{{id}}">
    <ng-content></ng-content>
  </label>
</div>

Now I want to unit test this binding (checked):

it('should emit the checked value on click on input', fakeAsync(async () => {
    const { find, bindings } = await shallow.render(
      `<bc-checkbox [(checked)]="checked"></bc-checkbox>`,
      { bind: { checked: false } },
    );
    find('input').triggerEventHandler('change', null);

    expect(bindings.checked).toBe(true);
  }));

But checked is not set to True.
Event when I use fixture.detectChanges.

Can you help me? :)

Cheers and a nice day

Entry Component can't be found, but is in module definition

I created a Stackblitz example showing the issue: https://stackblitz.com/edit/shallow-render-angular?file=examples%2Findex.ts

I'm using the dynamic component loading pattern described in the angular guide here: https://angular.io/guide/dynamic-component-loader

The error that displays:

Error: No component factory found for TestEntryComponent. Did you add it to @NgModule.entryComponents?

I added the entry component to the module definition, but it didn't help:

@NgModule({
  declarations: [OuterComponent, TestHostDirective],
  entryComponents: [TestEntryComponent]
})
class TestModule {}

I also tried to use .dontMock(TestEntryComponent) but that didn't help either :/

TypeError: this.appInits[i] is not a function

I don't know if this is something with shallow-render or something just due to our module design. But figured I'd ask and see what help you can provide.

My test file:

import { Shallow } from 'shallow-render'

import { DialogSortComponent } from '@agilitypr/app/briefing/composition/sortTool/sort-tool.component';
import { BriefingModule} from "@agilitypr/app/briefing/briefing.module";

describe (
    'DialogSortComponent',
    () => {
        let shallow: Shallow<DialogSortComponent>;

        beforeEach(() => {
            shallow = new Shallow(DialogSortComponent, BriefingModule)
            }
        );

        it(
            'Sort Component created',
            async () => {
                const {find} = await shallow.render('<sorttool-dialog></sorttool-dialog>');
            }
        );
    }
);

When I try to run the test, I an error:

$ yarn test --environment dev_web1mars1 --watch=false
yarn run v1.7.0
$ ng test --environment dev_web1mars1 --watch=false
 10% building modules 1/1 modules 0 active18 10 2018 10:41:36.599:INFO [karma]: Karma v3.0.0 server started at http://0.0.0.0:9876/
18 10 2018 10:41:36.602:INFO [launcher]: Launching browser ChromeHeadless with unlimited concurrency
18 10 2018 10:41:36.615:INFO [launcher]: Starting browser ChromeHeadless
18 10 2018 10:41:51.868:INFO [HeadlessChrome 0.0.0 (Ubuntu 0.0.0)]: Connected on socket JNNa6hVTyM3iXaiPAAAA with id 67817959

  DialogSortComponent
    βœ— Sort Component created
        TypeError: this.appInits[i] is not a function
            at <Jasmine>
            at ApplicationInitStatus.webpackJsonp../node_modules/@angular/core/esm5/core.js.ApplicationInitStatus.runInitializers node_modules/@angular/core/esm5/core.js:3574:34)
            at TestBed.webpackJsonp../node_modules/@angular/core/esm5/testing.js.TestBed._initIfNeeded node_modules/@angular/core/esm5/testing.js:1011:59)
            at TestBed.webpackJsonp../node_modules/@angular/core/esm5/testing.js.TestBed.createComponent node_modules/@angular/core/esm5/testing.js:1138:1)
            at Function.webpackJsonp../node_modules/@angular/core/esm5/testing.js.TestBed.createComponent node_modules/@angular/core/esm5/testing.js:837:1)
            at Renderer.<anonymous> node_modules/shallow-render/dist/lib/models/renderer.js:149:1)
            at step node_modules/shallow-render/dist/lib/models/renderer.js:50:1)
            at Object.next node_modules/shallow-render/dist/lib/models/renderer.js:31:45)
            at fulfilled node_modules/shallow-render/dist/lib/models/renderer.js:22:42)
            at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke node_modules/zone.js/dist/zone.js:388:1)
            at ProxyZoneSpec.webpackJsonp../node_modules/zone.js/dist/proxy.js.ProxyZoneSpec.onInvoke node_modules/zone.js/dist/proxy.js:128:1)

HeadlessChrome 0.0.0 (Ubuntu 0.0.0) DialogSortComponent Sort Component created FAILED
        TypeError: this.appInits[i] is not a function
            at <Jasmine>
            at ApplicationInitStatus.webpackJsonp../node_modules/@angular/core/esm5/core.js.ApplicationInitStatus.runInitializers node_modules/@angular/core/esm5/core.js:3574:34)
            at TestBed.webpackJsonp../node_modules/@angular/core/esm5/testing.js.TestBed._initIfNeeded node_modules/@angular/core/esm5/testing.js:1011:59)
            at TestBed.webpackJsonp../node_modules/@angular/core/esm5/testing.js.TestBed.createComponent node_modules/@angular/core/esm5/testing.js:1138:1)
            at Function.webpackJsonp../node_modules/@angular/core/esm5/testing.js.TestBed.createComponent node_modules/@angular/core/esm5/testing.js:837:1)
            at Renderer.<anonymous> node_modules/shallow-render/dist/lib/models/renderer.js:149:1)
            at step node_modules/shallow-render/dist/lib/models/renderer.js:50:1)
            at Object.next node_modules/shallow-render/dist/lib/models/renderer.js:31:45)
            at fulfilled node_modules/shallow-render/dist/lib/models/renderer.js:22:42)
            at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke node_modules/zone.js/dist/zone.js:388:1)
            at ProxyZoneSpec.webpackJsonp../node_modules/zone.js/dist/proxy.js.ProxyZoneSpec.onInvoke node_modules/zone.js/dist/proxy.js:128:1)

HeadlessChrome 0.0.0 (Ubuntu 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.889 secs / 0.807 secs)

I know the test doesn't do much but the line 19 causes the error (remove it and the error goes away, with it and things go bang).

A snippet for the component, to show the selector:

@Component({
    selector: 'sorttool-dialog',
    templateUrl: './sort-tool.component.html',
    styleUrls: [
        '../../shared/css/briefings.css',
        './sort-tool.component.css',
    ],
    providers: [
        ConfirmationService,
        StringTokenService
    ],

Any guidance - is this error coming from shallow-render and something that can be dealt with? Is this something due to the complexity of our module? This module is based on Angular 5.2.

Value provider does not provide value

I provide a value like this:

        shallow = new Shallow(FooComponent, FooModule)
            .provide(
                {provide: 'myValue', useValue: 'world'},
            );

And use it like this:

constructor(@Inject('myValue') myValue: string) {
        this.message = "Hello " + myValue;
        console.log(myValue);
    }

Expected value of message:
Hello world
Actual value of message:
Hello [object Object]

The log statement outputs:
LOG: MockProvider{mockOf: Object{provide: 'myValue', useValue: 'world'}}

Complete test case:
foo.component.spec.ts.txt

Tests fail if ng-bootstrap module is imported

If NgbModule from ng-bootstrap is imported, the test fails with the following Error.

I realize that you cannot support all combinations of third-party frameworks but I'm curious if this is only a problem with ng-bootstrap or something that could be fixed in shallow-render.

Example: https://stackblitz.com/edit/shallow-render-mock-method-provider-dy21dd

error properties: Object({ ngSyntaxError: true })
Error: MockOfNgbModalBackdrop cannot be used as an entry component.
    at syntaxError (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:1093:21)
    at CompileMetadataResolver._getEntryComponentMetadata (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:11087:23)
    at eval (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:10727:57)
    at <Jasmine>
    at CompileMetadataResolver.getNgModuleMetadata (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:10727:22)
    at CompileMetadataResolver.getNgModuleSummary (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:10553:39)
    at eval (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:10640:59)
    at <Jasmine>
    at CompileMetadataResolver.getNgModuleMetadata (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:10618:53)
    at CompileMetadataResolver.getNgModuleSummary (https://shallow-render-mock-method-provider-dy21dd.stackblitz.io/turbo_modules/@angular/[email protected]/bundles/compiler.umd.js:10553:39)

6.1.3 Regression with selectors

After upgrading to the latest shallow render, my tests started failing. Before, I was at 6.0.6.

Here is the error:

	Unexpected closing tag "__MockOfEmptyOutletComponent-selector". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags ("<__MockOfEmptyOutletComponent-selector>[ERROR ->]</__MockOfEmptyOutletComponent-selector>"): @0:39
	    at syntaxError (./node_modules/@angular/compiler/fesm5/compiler.js?:1275:17)
	    at TemplateParser.parse (./node_modules/@angular/compiler/fesm5/compiler.js?:15084:19)
	    at JitCompiler._parseTemplate (./node_modules/@angular/compiler/fesm5/compiler.js?:24272:37)
	    at JitCompiler._compileTemplate (./node_modules/@angular/compiler/fesm5/compiler.js?:24259:23)
	    at eval (./node_modules/@angular/compiler/fesm5/compiler.js?:24202:62)
	    at Set.forEach (<anonymous>)
	    at JitCompiler._compileComponents (./node_modules/@angular/compiler/fesm5/compiler.js?:24202:19)
	    at eval (./node_modules/@angular/compiler/fesm5/compiler.js?:24120:19)
	    at Object.then (./node_modules/@angular/compiler/fesm5/compiler.js?:1266:77)

Downgrading to 6.1.2 solves the issue.

Commit that seemed to cause it: 07ac3a3

Is there a way to add imports?

When you:

  • use the NGRX Store module
  • use it inside of a feature module
  • use it in a component within that module
  • and you want to test it,
    then they require you to add an additional import.

It looks like this:

imports: [ 
    StoreModule.forRoot({}), // This is the extra import
    StoreModule.forFeature('yourFeature', fromFeature.reducers)
]

Without the extra import, you can't use the Store service within your component. It complains about missing providers.

But you can't just add StoreModule.forRoot({}) to your feature module since it would defeat the whole purpose of having StoreModule.forFeature('yourFeature', fromFeature.reducers). The extra import is only for the test.

Is there a way to add new imports?

I recall there used to be an .imports() method on the shallow class instance, but it's no longer there.

TypeError: Cannot read property 'injector' of null

Hi there

i'm struggling to setup shallow-render in my meteor angular project. Hopefully you can help me.

I'm getting following error:

 TypeError: Cannot read property 'injector' of null
 at TestBedViewEngine._createCompilerAndModule (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:42029:49)
 at TestBedViewEngine.compileComponents (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:41942:35)
 at Function.TestBedViewEngine.compileComponents (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:41802:81)
 at Renderer.\u003Canonymous> (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:2680:16)
 at step (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:2538:19)
 at Object.next (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:2468:14)
 at packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:2440:67
 at new Promise (\u003Canonymous>)
 at __awaiter (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:2417:10)
 at Renderer.render (packages/modules.js?hash=9bf6a4a74870f7e24c465ccdd26da1c74b199b4c:2644:12)`

i have following packages installed:

 "devDependencies": {
      "chai": "^4.2.0",
      "chromedriver": "^2.41.0",
      "faker": "^4.1.0",
      "shallow-render": "^7.1.2",
      "selenium-webdriver": "^3.6.0",
      "sinon": "^7.2.3"
 },

and in packages:

  • jquery
  • sanjo:jasmine

And following Code:

 import { AppModule } from '../../app.module';`

 import { ServersFormComponent } from "../servers-form.component";`

 import { Shallow } from 'shallow-render';`

 describe("ServersFormComponent", () => { 
      let shallow: Shallow<ServersFormComponent>;
      beforeEach(()=>{
           shallow = new Shallow(ServersFormComponent, AppModule);
      });

      it('should render this', async () => {
           const {find} = await shallow.render('<servers-form></servers-form>');
           console.log(find("h5"));
      });
 });

I run the tests with:

TEST_BROWSER_DRIVER=chrome meteor test --once --driver-package meteortesting:mocha

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.