Testing HTTP interactions - Pragmatists/ng-test-runner GitHub Wiki

In contrast to stubbing HTTP requests, ng-test-runner allows to fake http request to server. To know difference between stubs, fakes and mocks visit Test Doubles – Fakes, Mocks and Stubs or Mocks Aren't Stubs.

By default HTTP communication is synchronous, as for most of the cases you don't need/want to include temporal dependencies in your tests. This saves you from writing obscure tick(). However, you can switch to asynchronous mode, if you feel you need to simulate network latency, for more complicated scenarios (ex. testing spinner).

Initialization

http([config])

Config:

respondImmediately: boolean - false enables async mode; default : true

autoRespond: boolean - true - respond immadietally, false - respond after; default : true

respondAfter: number - response will be returned after x miliseconds, it demands disabled autoRespond; default : 10

import { http, Server } from 'ng-test-runner';

let server: Server;

beforeEach(() => {
    server = http();
});

afterEach(() => {
    server.stop();
});

Creating fake

methodName(url, handler)

Creates fake server function for url. Possible method names : get, put, post, delete

Parameters

Argument Type Description
url string, RegExp url or regexp to match http requests
handler function(Request, ...args: any[]) function which will be call after matching http request

Example

import test, { http, Server, expectThat } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('responds with specific code', async(() => {
    // given:
    const server = http();
    const app = test(MyModule);
    server.get('/greeting', req => {
        req.sendJson({
            message: 'Hello from server!'
        });
    });

    // when:
    const comp = app.run(MyComponent);

    // then:
    comp.verify(
        expectThat.textOf('.greeting').isEqualTo('Hello from server!')
    );
}));

Example

import test, { http, Server, expectThat } from 'ng-test-runner';
import { async } from '@angular/core/testing';
    
it('should send request to correct path', async(() => {
    let receivedId;
    server.put(/api\/test\/(\d+)/, (req, id) => {
        receivedId = id;
        req.sendStatus(200);
    });
    const comp = app.run(MyComponent);

    comp.perform(
        click.in('.update')
    );
         
    comp.verify(
        () => expect(id).toEqual('321')
    );
}));

stop()

Reset all created fakes.

Async mode

server object allows to turn on async mode where waiting requests are resolving only in case of performing server.respond action.

Example:

import test, { expectThat, http } from 'ng-test-runner';

it('resolves request after respond()', () => {
    // given:
    const server = http({autoRespond: true, respondImmediately: false});
    const app = test(MyModule);
    server.get('/greeting', req => req.sendStatus(200));

    // when:
    const comp = app.run(MyComponent);

    comp.verify(
        expectThat.textOf('.greeting').isEqualTo('Waiting for server response!')
    );

    comp.perform(
        server.respond
    );

    comp.verify(
        expectThat.textOf('.greeting').isEqualTo('Hello from server!')
    );
});

Request

Req object allows to verify sent request and to customize responses. It's a generic type with two parameters Req<T = any, P = any>, where T is the type of request body and P is the type of query params object. By default both are set to any and there is no need to specify any of them if you don't need.

body()

Returns body of sent request.

Example

import test, { http, Server } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('body contains data from input', async(() => {
    let body;
    server.post('/create', req => {
        body = req.body();
        req.sendStatus(201);
    });

   const comp = app.run(MyComponent);
   comp.perform(
       type('John').in('.input-name'),
       click.in('.send-button')
   );

    comp.verify(
        () => expect(body.name).toEqual('John')
    );
}));

header(name: string)

Returns value of header with given name.

Example

import test, { http, Server } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('version in header is sent to backend', async(() => {
    let versionHeader;
    server.put('/update', req => {
        versionHeader = req.header('If-Match');
        req.sendStatus(200);
    });

   const comp = app.run(UpdatingComponent);
   comp.perform(
       type('Joe').in('.input-name'),
       click.in('.update-button')
   );

    comp.verify(
        () => expect(versionHeader).toEqual('1')
    );
}));

query()

Returns data from request query string.

Example

import test, { http, Server } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('query should contain user selection', async(() => {
    let query;
    // for query like messages?name=Joe&status=SENT,ERROR&limit=10&offset=10&sort=name
    server.get(/\/messages/, req => {
        query = req.query();
        req.sendJson([{
            name: 'Joe',
            status: 'SENT'
        }, {
            name: 'Joe',
            status: 'ERROR'
        }]);
    });

   const comp = app.run(FilteringComponent);
   comp.perform(
       type('Joe').in('.input-name'),
       select('SENT').in('.status-checkboxes'),
       select('ERROR').in('.status-checkboxes'),
       click.in('.filter-button')
   );

    comp.verify(
        () => expect(query.name).toEqual('Joe'),
        () => expect(query.status).toEqual('ERROR,SENT'),
    );
}));

sendJson(json: any, headers?: any)

Sends a json as a JSON object in response. Optional headers may be included.

Example

import test, { http, Server, expectThat } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('table should display players data in rows', async(() => {
    server.get('/players', req => req.sendJson([{
            name: 'Micheal',
            score: 30
        }, {
            name: 'Karl',
            score: 25
        }])
    );

    const comp = app.run(ComponentThatFetchDataInNgOnInit);

    comp.verify(
        expectThat.textOf('.player-row:nth-of-type(1) .name').isEqualTo('Michael'),
        expectThat.textOf('.player-row:nth-of-type(1) .score').isEqualTo('30'),
        expectThat.textOf('.player-row:nth-of-type(2) .name').isEqualTo('Karl'),
        expectThat.textOf('.player-row:nth-of-type(2) .score').isEqualTo('25')
    );
}));

sendResponse(status: number, body: string, headers: any)

Sends reponse with specific status, body and headers.

Example

import test, { http, Server, expectThat } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('id from location header should be displayed', async(() => {
    server.post('/configuration', req => req.sendResponse(200, '', {Location: 'config/10'}));
    const comp = app.run(MyComponent);

    comp.perform(
        click.in('.save-configuration')
    );

    comp.verify(
        expectThat.textOf('.config .id').isEqualTo('10')
    );
}));

sendStatus(status: number, json?: any, headers?: any)

Sends a specific status in response. Optional json body and headers may be included.

Example

import test, { http, Server, expectThat } from 'ng-test-runner';
import { async } from '@angular/core/testing';

it('body contains data from input', async(() => {
    let body;
    server.post('/create', req => req.sendStatus(201));
    
    const comp = app.run(MyComponent);
    comp.perform(
       type('John').in('.input-name'),
       click.in('.send-button')
   );

    comp.verify(
        expectThat.textOf('.status').isEqualTo('Success')
    );
}));