dbmedialab/reader-critics

View on GitHub
src/test/database/persisting-services/EndUserServiceTests.ts

Summary

Maintainability
A
0 mins
Test Coverage
//
// LESERKRITIKK v2 (aka Reader Critics)
// Copyright (C) 2017 DB Medialab/Aller Media AS, Oslo, Norway
// https://github.com/dbmedialab/reader-critics/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
//

import * as Promise from 'bluebird';

import * as path from 'path';

import { assert } from 'chai';
import { ISuiteCallbackContext } from 'mocha';

import EndUser from 'base/EndUser';

import { enduserService } from 'app/services';
import { defaultLimit } from 'app/services/BasicPersistingService';
import { anonymousEndUser } from 'app/services/enduser/EndUserService';
import { EmptyError } from 'app/util/errors';

import * as app from 'app/util/applib';

const demoUsers = path.join('resources', 'user', 'demo-endusers.json5');

// Main test function

export default function(this: ISuiteCallbackContext) {
    this.slow(250);

    testParameterChecks();
    testClear();
    testSave();
    testCount();

    testGet();
    testGetRange();

    testAnonymousSave();
    testAnonymousGet();
}

// Test runtime data

let userCount : number;

// Check for thrown exceptions

const testParameterChecks = () => it('parameter checks', () => {
    // No checks for empty parameters to get() will be here, because this
    // function returns the "Anonymous" user if all parameters are empty.
    // This anonymous user is created in the get() function, should it not
    // exist in the current database.
    // But at least we can test for some parameter combinations here:
    assert.doesNotThrow(() => enduserService.get('Jake Peralta'), Error);
    assert.doesNotThrow(() => enduserService.get(null, 'det.peralta@99prec.nyc'), Error);

    assert.throws(() => enduserService.save(null), EmptyError);
});

// enduserService.clear()

const testClear = () => it('clear()', () => enduserService.clear());

// enduserService.save()

const testSave = () => it('save()', () => app.loadJSON(demoUsers).then(data => {
    assert.isArray(data);
    userCount = data.length;

    return Promise.mapSeries(data, enduserService.save);
})
.then((results : EndUser[]) => {
    assert.isArray(results);
    assert.lengthOf(results, userCount, 'Number of saved objects does not match');

    results.forEach(u => assertUserObject(u));
}));

// enduserService.count()

const testCount = () => it('count()', () => enduserService.count().then(count => {
    assert.strictEqual(count, userCount);
}));

// enduserService.get()

const testGet = () => it('get()', () => {
    return Promise.all([
        enduserService.get('Indiana Horst'),
        enduserService.get(null, 'prost.mahlzeit@lulu.org'),
    //    enduserService.get('Ernst Eisenbichler', 'ee@aller.com'),
    ]).then((results : EndUser[]) => {
        results.forEach(u => assertUserObject(u));
    });
});

// enduserService.getRange()

const testGetRange = () => it('getRange()', () => {
    const testLimit = 5;

    return Promise.all([
        // #1 should return the lesser of "defaultLimit" or "websiteCount" number of items:
        enduserService.getRange(),
        // #2 should return exactly "testLimit" items:
        enduserService.getRange(0, testLimit),
        // #3 skipping past the number of stored items should yield an empty result:
        enduserService.getRange(userCount),
    ])
    .spread((...ranges : EndUser[][]) => {
        ranges.forEach(result => {
            assert.isArray(result);
            result.forEach(item => assertUserObject(item));
        });

        const lengthCheck = [
            Math.min(userCount, defaultLimit),
            testLimit,
            0,
        ];

        ranges.forEach((result : EndUser[], index : number) => {
            assert.lengthOf(
                result,
                lengthCheck[index],
                `Incorrect number of objects in test range #${index + 1}`
            );
        });
    });
});

// Anonymous user

const testAnonymousSave = () => it('anonymous save()', () => enduserService
    .save({ name: null, email: null })
    .then(() => assert.fail())
    .catch(() => assert.ok(true))
);

const testAnonymousGet = () => it('anonymous get()', () => enduserService
.get(null, null)
.then((u : EndUser) => assertUserObject(u, anonymousEndUser))
);

// Generic structure check

const assertUserObject = (u : EndUser, name? : string) => {
    assert.isObject(u);

    [ 'ID', 'name', 'email' ].forEach(prop => {
        assert.property(u, prop);
    });

    if (u.name === null) {
        assert.isString(u.email);
    }
    if (u.email === null) {
        assert.isString(u.name);
    }
    if (u.name === null && u.email === null) {
        assert.fail('One of "name" or "email" has to be set');
    }

    if (name) {
        assert.strictEqual(u.name, name);
    }
};