Initial commit
This commit is contained in:
41
tests/unit/application/UserSelection.spec.ts
Normal file
41
tests/unit/application/UserSelection.spec.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { CategoryStub } from './../stubs/CategoryStub';
|
||||
import { ApplicationStub } from './../stubs/ApplicationStub';
|
||||
import { ScriptStub } from './../stubs/ScriptStub';
|
||||
import { UserSelection } from '@/application/State/Selection/UserSelection';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
|
||||
describe('UserSelection', () => {
|
||||
it('deselectAll removes all items', async () => {
|
||||
// arrange
|
||||
const app = new ApplicationStub()
|
||||
.withCategory(new CategoryStub(1)
|
||||
.withScripts('s1', 's2', 's3', 's4'));
|
||||
const selectedScripts = [new ScriptStub('s1'), new ScriptStub('s2'), new ScriptStub('s3')];
|
||||
const sut = new UserSelection(app, selectedScripts);
|
||||
|
||||
// act
|
||||
sut.deselectAll();
|
||||
const actual = sut.selectedScripts;
|
||||
|
||||
// assert
|
||||
expect(actual, JSON.stringify(sut.selectedScripts)).to.have.length(0);
|
||||
});
|
||||
it('selectOnly selects expected', async () => {
|
||||
// arrange
|
||||
const app = new ApplicationStub()
|
||||
.withCategory(new CategoryStub(1)
|
||||
.withScripts('s1', 's2', 's3', 's4'));
|
||||
const selectedScripts = [new ScriptStub('s1'), new ScriptStub('s2'), new ScriptStub('s3')];
|
||||
const sut = new UserSelection(app, selectedScripts);
|
||||
const expected = [new ScriptStub('s2'), new ScriptStub('s3'), new ScriptStub('s4')];
|
||||
|
||||
// act
|
||||
sut.selectOnly(expected);
|
||||
const actual = sut.selectedScripts;
|
||||
|
||||
// assert
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
55
tests/unit/infrastructure/AsyncLazy.spec.ts
Normal file
55
tests/unit/infrastructure/AsyncLazy.spec.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { AsyncLazy } from '@/infrastructure/Threading/AsyncLazy';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('AsyncLazy', () => {
|
||||
|
||||
it('returns value from lambda', async () => {
|
||||
// arrange
|
||||
const expected = 'test';
|
||||
const lambda = () => Promise.resolve(expected);
|
||||
const sut = new AsyncLazy(lambda);
|
||||
|
||||
// act
|
||||
const actual = await sut.getValueAsync();
|
||||
|
||||
// assert
|
||||
expect(actual).to.equal(expected);
|
||||
});
|
||||
|
||||
describe('when running multiple times', () => {
|
||||
let totalExecuted: number = 0;
|
||||
|
||||
beforeEach(() => totalExecuted = 0);
|
||||
|
||||
it('when running sync', async () => {
|
||||
const sut = new AsyncLazy(() => {
|
||||
totalExecuted++;
|
||||
return Promise.resolve(totalExecuted);
|
||||
});
|
||||
const results = new Array<number>();
|
||||
for (let i = 0; i < 5; i++) {
|
||||
results.push(await sut.getValueAsync());
|
||||
}
|
||||
expect(totalExecuted).to.equal(1);
|
||||
expect(results).to.deep.equal([1, 1, 1, 1, 1]);
|
||||
});
|
||||
|
||||
it('when running long-running task paralelly', async () => {
|
||||
const sleep = (time: number) => new Promise(((resolve) => setTimeout(resolve, time)));
|
||||
const sut = new AsyncLazy(async () => {
|
||||
await sleep(100);
|
||||
totalExecuted++;
|
||||
return Promise.resolve(totalExecuted);
|
||||
});
|
||||
const results = await Promise.all([
|
||||
sut.getValueAsync(),
|
||||
sut.getValueAsync(),
|
||||
sut.getValueAsync(),
|
||||
sut.getValueAsync(),
|
||||
sut.getValueAsync()]);
|
||||
expect(totalExecuted).to.equal(1);
|
||||
expect(results).to.deep.equal([1, 1, 1, 1, 1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
72
tests/unit/infrastructure/InMemoryRepository.spec.ts
Normal file
72
tests/unit/infrastructure/InMemoryRepository.spec.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { NumericEntityStub } from './../stubs/NumericEntityStub';
|
||||
import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryRepository';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('InMemoryRepository', () => {
|
||||
describe('exists', () => {
|
||||
const sut = new InMemoryRepository<number, NumericEntityStub>(
|
||||
[new NumericEntityStub(1), new NumericEntityStub(2), new NumericEntityStub(3)]);
|
||||
|
||||
describe('item exists', () => {
|
||||
const actual = sut.exists(new NumericEntityStub(1));
|
||||
it('returns true', () => expect(actual).to.be.true);
|
||||
});
|
||||
describe('item does not exist', () => {
|
||||
const actual = sut.exists(new NumericEntityStub(99));
|
||||
it('returns false', () => expect(actual).to.be.false);
|
||||
});
|
||||
});
|
||||
it('can get', () => {
|
||||
// arrange
|
||||
const expected = [
|
||||
new NumericEntityStub(1), new NumericEntityStub(2), new NumericEntityStub(3), new NumericEntityStub(4)];
|
||||
|
||||
// act
|
||||
const sut = new InMemoryRepository<number, NumericEntityStub>(expected);
|
||||
const actual = sut.getItems();
|
||||
|
||||
// assert
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
it('can add', () => {
|
||||
// arrange
|
||||
const sut = new InMemoryRepository<number, NumericEntityStub>();
|
||||
const expected = {
|
||||
length: 1,
|
||||
item: new NumericEntityStub(1),
|
||||
};
|
||||
|
||||
// act
|
||||
sut.addItem(expected.item);
|
||||
const actual = {
|
||||
length: sut.length,
|
||||
item: sut.getItems()[0],
|
||||
};
|
||||
|
||||
// assert
|
||||
expect(actual.length).to.equal(expected.length);
|
||||
expect(actual.item).to.deep.equal(expected.item);
|
||||
});
|
||||
it('can remove', () => {
|
||||
// arrange
|
||||
const initialItems = [
|
||||
new NumericEntityStub(1), new NumericEntityStub(2), new NumericEntityStub(3), new NumericEntityStub(4)];
|
||||
const idToDelete = 3;
|
||||
const expected = {
|
||||
length: 3,
|
||||
items: [new NumericEntityStub(1), new NumericEntityStub(2), new NumericEntityStub(4)],
|
||||
};
|
||||
const sut = new InMemoryRepository<number, NumericEntityStub>(initialItems);
|
||||
|
||||
// act
|
||||
sut.removeItem(idToDelete);
|
||||
const actual = {
|
||||
length: sut.length,
|
||||
items: sut.getItems(),
|
||||
};
|
||||
|
||||
// assert
|
||||
expect(actual.length).to.equal(expected.length);
|
||||
expect(actual.items).to.deep.equal(expected.items);
|
||||
});
|
||||
});
|
||||
77
tests/unit/infrastructure/Signal.spec.ts
Normal file
77
tests/unit/infrastructure/Signal.spec.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Signal } from '@/infrastructure/Events/Signal';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('Signal Tests', () => {
|
||||
class ReceiverMock {
|
||||
public onRecieveCalls = new Array<number>();
|
||||
public onReceive(arg: number): void { this.onRecieveCalls.push(arg); }
|
||||
}
|
||||
|
||||
let signal: Signal<number>;
|
||||
beforeEach(() => signal = new Signal());
|
||||
|
||||
describe('single reciever', () => {
|
||||
let receiver: ReceiverMock;
|
||||
|
||||
beforeEach(() => {
|
||||
receiver = new ReceiverMock();
|
||||
signal.on((arg) => receiver.onReceive(arg));
|
||||
});
|
||||
|
||||
it('notify() executes the callback', () => {
|
||||
signal.notify(5);
|
||||
expect(receiver.onRecieveCalls).to.have.length(1);
|
||||
});
|
||||
|
||||
it('notify() executes the callback with the payload', () => {
|
||||
const expected = 5;
|
||||
signal.notify(expected);
|
||||
expect(receiver.onRecieveCalls).to.deep.equal([expected]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple recievers', () => {
|
||||
let receivers: ReceiverMock[];
|
||||
|
||||
beforeEach(() => {
|
||||
receivers = [
|
||||
new ReceiverMock(), new ReceiverMock(),
|
||||
new ReceiverMock(), new ReceiverMock()];
|
||||
for (const receiver of receivers) {
|
||||
signal.on((arg) => receiver.onReceive(arg));
|
||||
}});
|
||||
|
||||
|
||||
it('notify() should execute all callbacks', () => {
|
||||
signal.notify(5);
|
||||
receivers.every((receiver) => {
|
||||
expect(receiver.onRecieveCalls).to.have.length(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('notify() should execute all callbacks with payload', () => {
|
||||
const expected = 5;
|
||||
signal.notify(expected);
|
||||
receivers.every((receiver) => {
|
||||
expect(receiver.onRecieveCalls).to.deep.equal([expected]);
|
||||
});
|
||||
});
|
||||
|
||||
it('notify() executes in FIFO order', () => {
|
||||
// arrange
|
||||
const expectedSequence = [0, 1, 2, 3];
|
||||
const actualSequence = new Array<number>();
|
||||
for (let i = 0; i < receivers.length; i++) {
|
||||
receivers[i].onReceive = ((arg) => {
|
||||
actualSequence.push(i);
|
||||
});
|
||||
}
|
||||
// act
|
||||
signal.notify(5);
|
||||
// assert
|
||||
expect(actualSequence).to.deep.equal(expectedSequence);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
21
tests/unit/stubs/ApplicationStub.ts
Normal file
21
tests/unit/stubs/ApplicationStub.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { IApplication, ICategory, IScript } from '@/domain/IApplication';
|
||||
|
||||
export class ApplicationStub implements IApplication {
|
||||
public readonly categories = new Array<ICategory>();
|
||||
|
||||
public withCategory(category: ICategory): IApplication {
|
||||
this.categories.push(category);
|
||||
return this;
|
||||
}
|
||||
public findCategory(categoryId: number): ICategory {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public findScript(scriptId: string): IScript {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public getAllScripts(): ReadonlyArray<IScript> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
20
tests/unit/stubs/CategoryStub.ts
Normal file
20
tests/unit/stubs/CategoryStub.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { ScriptStub } from './ScriptStub';
|
||||
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
|
||||
import { ICategory, IScript } from '@/domain/ICategory';
|
||||
|
||||
export class CategoryStub extends BaseEntity<number> implements ICategory {
|
||||
public readonly name = `category-with-id-${this.id}`;
|
||||
public readonly subCategories = new Array<ICategory>();
|
||||
public readonly scripts = new Array<IScript>();
|
||||
public readonly documentationUrls = new Array<string>();
|
||||
|
||||
constructor(id: number) {
|
||||
super(id);
|
||||
}
|
||||
public withScripts(...scriptIds: string[]): CategoryStub {
|
||||
for (const scriptId of scriptIds) {
|
||||
this.scripts.push(new ScriptStub(scriptId));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
7
tests/unit/stubs/NumericEntityStub.ts
Normal file
7
tests/unit/stubs/NumericEntityStub.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
|
||||
|
||||
export class NumericEntityStub extends BaseEntity<number> {
|
||||
constructor(id: number) {
|
||||
super(id);
|
||||
}
|
||||
}
|
||||
12
tests/unit/stubs/ScriptStub.ts
Normal file
12
tests/unit/stubs/ScriptStub.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
|
||||
import { IScript } from './../../../src/domain/IScript';
|
||||
|
||||
export class ScriptStub extends BaseEntity<string> implements IScript {
|
||||
public readonly name = `name${this.id}`;
|
||||
public readonly code = `name${this.id}`;
|
||||
public readonly documentationUrls = new Array<string>();
|
||||
|
||||
constructor(public readonly id: string) {
|
||||
super(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user