Giter Club home page Giter Club logo

angular-tests's Introduction

Angular Testing Best Practices

Configure mocks globally for store, service, component etc.. [test.ts]

Shallow
.alwaysReplaceModule(BrowserAnimationsModule, NoopAnimationsModule);

Configure mocks per Module for store, service, component etc.. [home.shallow.ts]

import { HomeState } from './store/home.state';
import { Shallow } from 'shallow-render';
import { NgxsModule } from '@ngxs/store';

export const mockHomeModule = <T>(shallow: Shallow<T>) => {
  const ngxs = NgxsModule.forRoot([ HomeState ]);

  return shallow
    .import(ngxs)
    .dontMock(ngxs);
};

When you write shallow tests create TestComponent(page) class which will contains common logic with interaction with page elements [shallow-test-component.ts]

import { IShallowTestComponent } from './shallow-test-component.interface';

export abstract class ShallowTestComponent<TTestComponent>
  implements IShallowTestComponent {
  shallow: Shallow<TTestComponent>;
  find: (
    cssOrDirective: string | Type<any>,
    options?:
      | {
          query?: string | undefined;
        }
      | undefined
  ) => QueryMatch<DebugElement>;

  fixture: ComponentFixture<any>;
  get: <TValue>(
    queryClass: Type<TValue> | InjectionToken<TValue> | AbstractType<TValue>
  ) => TValue;
  instance: TTestComponent;

  constructor(
    testComponent: Type<TTestComponent>,
    testModule: Type<any> | ModuleWithProviders,
    mockModule: <T>(shallow: Shallow<T>) => Shallow<T> = null
  ) {
    this.shallow = mockModule
      ? mockModule(new Shallow(testComponent, testModule))
      : new Shallow(testComponent, testModule);
  }
}

Use .mock(UserService, { advancedSearch: () => of([]) }) in beforeEach to mock service for all tests

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

  beforeEach(async(() => {
    shallow = configureAdministrationModule(new Shallow(SearchAndInfoComponent, AdministrationModule))
      .mock(UserService, { advancedSearch: () => of([]) })
  }));
  ....
}); 

Use .mock(UserService, { advancedSearch: () => of([]) }) in test to mock service for specific test

it('should display empty search result message', async () => {
  const page = await createTestPage(shallow
    .mock(UserService, {
      advancedSearch: () => of(<SearchItem[]>[])
    }));

 await page.search(<SearchCriteria>{});

 expect(page.userList.el).toHaveFound(0);
 expect(page.emptySearch).toHaveFoundOne();
});

Don't create Test data object in each Test, create emptyObject and then extends it with spread operators ({...emptyTestData, name: 'john'})

const emptyProfile = <ProfileView>{
  tecComId: '',
  logoPath: '',
};


it('should display add partner button and profile title', async () => {
  const page = await shallow.render({
    bind: {
      showDefaultTitle: false,
      isAlreadyFriend: false,
      profileView: { ...emptyProfile, Id: '1234567890', general: { name: 'test' } }
    }
  });

  expect(page.find('[data-test-id="name"]').nativeElement.textContent.trim()).toBe('test');
});

Use Jasmine spyOn to validate if Service, Component etc.. methods are called

Use Jasmine spyOn(page.instance, 'search').and.callThrough(); to validate if real method implementation called

Preffer to use .toHaveBeenCalledWith when you test method called with arguments passed to it, combine it with spread operator to avoid comparing objects by reference .toHaveBeenCalledWith({ ...searchCriteria})

it('should display partners list table if search successfully', async () => {
  const page = await createTestPage(shallow
    .mock(PartnerService, {
      advancedSearch: () => of([<PartnerSearchItem>{}])
    }));
  spyOn(page.instance, 'search').and.callThrough();
  spyOn(page.get(Store), 'dispatch').and.callThrough();

  const searchCriteria = <PartnerSearchCriteria>{ name: 'test' };
  await page.searchForMembers(searchCriteria);

  expect(page.partnersList.el).toHaveFoundOne();
  expect(page.instance.search).toHaveBeenCalledWith(searchCriteria);
  expect(page.get(UserService).advancedSearch).toHaveBeenCalledWith(searchCriteria);
  expect(page.get(Store).dispatch).toHaveBeenCalledWith([new AdvancedSearch(searchCriteria)]);
});

Use instance.addPartner = jasmine.createSpyObj('EventEmitter', ['emit']); to mock and test EventEmitter has been called

it('should add user on button click', async () => {
  const { find, instance, get} = await shallow
    .mock(AppInsightsService, { trackEvent(name: string, properties?: any, measurements?: any): void {} })
    .render({
    bind: {
      isAlreadyFriend: false,
      profileView: { ...emptyProfile, tecComId: '1234567890' }
    }
  });
  instance.addUser = jasmine.createSpyObj('EventEmitter', ['emit']);

  find('[data-test-id="addUser"]').nativeElement.click();
  expect(instance.addUser.emit).toHaveBeenCalledWith('1234567890');
  expect(get(AppInsightsService).trackEvent).toHaveBeenCalledWith('mpv-add-user-btn-clicked');
});

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.