All Projects → getsaf → Shallow Render

getsaf / Shallow Render

Licence: mit
Angular testing made easy with shallow rendering and easy mocking. https://getsaf.github.io/shallow-render

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Shallow Render

Pegomock
Pegomock is a powerful, yet simple mocking framework for the Go programming language
Stars: ✭ 215 (-11.16%)
Mutual labels:  mock
Testing React Redux With Jest And Enzyme
React Redux Testing Template using Jest and Enzyme
Stars: ✭ 224 (-7.44%)
Mutual labels:  enzyme
Axios Mock Adapter
Axios adapter that allows to easily mock requests
Stars: ✭ 2,832 (+1070.25%)
Mutual labels:  mock
Nx Admin
👍 A magical 🐮 ⚔ vue admin,记得star
Stars: ✭ 2,497 (+931.82%)
Mutual labels:  mock
Redux Form Test
Shows how to do unit tests and integration tests with Redux-Form
Stars: ✭ 221 (-8.68%)
Mutual labels:  enzyme
Pester
Pester is the ubiquitous test and mock framework for PowerShell.
Stars: ✭ 2,620 (+982.64%)
Mutual labels:  mock
Python Mocket
a socket mock framework - for all kinds of socket animals, web-clients included
Stars: ✭ 209 (-13.64%)
Mutual labels:  mock
Faker
Provides fake data to your Android apps :)
Stars: ✭ 234 (-3.31%)
Mutual labels:  mock
Dgate
an API Gateway based on Vert.x
Stars: ✭ 222 (-8.26%)
Mutual labels:  mock
Mockiato
A strict, yet friendly mocking library for Rust 2018
Stars: ✭ 229 (-5.37%)
Mutual labels:  mock
Openapi Backend
Build, Validate, Route, Authenticate and Mock using OpenAPI
Stars: ✭ 216 (-10.74%)
Mutual labels:  mock
Mockery
A mock code autogenerator for Golang
Stars: ✭ 3,138 (+1196.69%)
Mutual labels:  mock
Node Mock Server
File based Node REST API mock server
Stars: ✭ 225 (-7.02%)
Mutual labels:  mock
Awesome Learning
Awesome Learning - Learn JavaScript and Front-End Fundamentals at your own pace
Stars: ✭ 216 (-10.74%)
Mutual labels:  enzyme
Mockito Scala
Mockito for Scala language
Stars: ✭ 231 (-4.55%)
Mutual labels:  mock
Protocol
Enzyme Protocol Implementation
Stars: ✭ 211 (-12.81%)
Mutual labels:  enzyme
Sinon Jest Cheatsheet
Some examples on how to achieve the same goal with either of both libraries: sinon and jest. Also some of those goals achievable only by one of these tools.
Stars: ✭ 226 (-6.61%)
Mutual labels:  mock
Mockoon
Mockoon is the easiest and quickest way to run mock APIs locally. No remote deployment, no account required, open source.
Stars: ✭ 3,448 (+1324.79%)
Mutual labels:  mock
Okhttp Json Mock
Mock your datas for Okhttp and Retrofit in json format in just a few moves
Stars: ✭ 231 (-4.55%)
Mutual labels:  mock
Jest Mock Extended
Type safe mocking extensions for Jest https://www.npmjs.com/package/jest-mock-extended
Stars: ✭ 224 (-7.44%)
Mutual labels:  mock

shallow-render

Build Status npm version

Angular testing made easy with shallow rendering and easy mocking.


Docs

Schematics

Articles

Angular Version Support

Angular shallow-render
11x 11x
10x 10x
9x 9x
6x-8x 8x
5x <= 7.2.0

Super Simple Tests

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

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

  it('renders a link with the name of the color', async () => {
    const { find } = await shallow.render({ bind: { color: 'Blue' } });
    // or shallow.render(`<color-link color="Blue"></color-link>`);

    expect(find('a').nativeElement.innerText).toBe('Blue');
  });

  it('emits color when clicked', async () => {
    const { element, outputs } = await shallow.render({ bind: { color: 'Red' } });
    element.click();

    expect(outputs.handleClick.emit).toHaveBeenCalledWith('Red');
  });
});

The problem

Testing in Angular is HARD. TestBed is powerful but its use in component specs ends with lots of duplication.

Here's a standard TestBed spec for a component that uses a few other components, a directive and a pipe and handles click events:

describe('MyComponent', () => {
  beforeEach(async => {
    return TestBed.configureTestModule({
      imports: [SomeModuleWithDependencies],
      declarations: [
        TestHostComponent,
        MyComponent, // <-- All I want to do is test this!!
        // We either must list all our dependencies here
        // -- OR --
        // Use NO_ERRORS_SCHEMA which allows any HTML to be used
        // even if it is invalid!
        ButtonComponent,
        LinkComponent,
        FooDirective,
        BarPipe,
      ],
      providers: [MyService],
    })
      .compileComponents()
      .then(() => {
        let myService = TestBed.get(MyService); // Not type safe
        spyOn(myService, 'foo').and.returnValue('mocked foo');
      });
  });

  it('renders a link with the provided label text', () => {
    const fixture = TestBed.createComponent(TestHostComponent);
    fixture.componentInstance.labelText = 'my text';
    fixture.detectChanges();
    const link = fixture.debugElement.query(By.css('a'));

    expect(a.nativeElement.innerText).toBe('my text');
  });

  it('sends "foo" to bound click events', () => {
    const fixture = TestBed.createComponent(TestHostComponent);
    spyOn(fixture.componentInstance, 'handleClick');
    fixture.detectChanges();
    const myComponentElement = fixture.debugElement.query(By.directive(MyComponent));
    myComponentElement.click();

    expect(fixture.componentInstance.handleClick).toHaveBeenCalledWith('foo');
  });
});

@Component({
  template: '<my-component [linkText]="linkText" (click)="handleClick($event)"></my-component>',
})
class TestHostComponent {
  linkLabel: string;
  handleClick() {}
}

Whew!!! That was a lot of boilerplate. Here's just some of the issues:

  • Our TestBed module looks very similar if not identical to the NgModule I've probably already added MyComponent too. Total module duplication.
  • Since I've duplicated my module in my spec, I'm not actually sure the real module was setup correctly.
  • I've used REAL components and services in my spec which means I have not isolated the component I'm interested in testing.
    • This also means I have to follow, and provide all the dependencies of those real components to the TestBed module.
  • I had to create a TestHostComponent so I could pass bindings into my actual component.
  • My TestBed boilerplate code-length exceeded my actual test code-length.

The Solution

We should mock everything we can except for the component in test and that should be EASY. Our modules already define the environment in which our components live. They should be reused, not rebuilt in our specs.

Here's the same specs using shallow-render:

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

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

  it('renders a link with the provided label text', async () => {
    const { find } = await shallow.render({ bind: { linkText: 'my text' } });
    // or shallow.render(`<my-component linkText="my text"></my-component>`);

    expect(find('a').nativeElement.innerText).toBe('my text');
  });

  it('sends "foo" to bound click events', async () => {
    const { element, outputs } = await shallow.render();
    element.click();

    expect(outputs.handleClick).toHaveBeenCalledWith('foo');
  });
});

Here's the difference:

  • Reuses (and verifies) MyModule contains your component and all its dependencies.
  • All components inside MyModule are mocked. This is what makes the rendering "shallow".
  • The tests have much less boilerplate which makes the specs easier to follow.
  • The HTML used to render the component is IN THE SPEC and easy to find.
    • This means specs now double examples of how to use your component.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].