added ability to revert (#21)
This commit is contained in:
65
tests/unit/application/State/Code/ApplicationCode.spec.ts
Normal file
65
tests/unit/application/State/Code/ApplicationCode.spec.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { CategoryStub } from './../../../stubs/CategoryStub';
|
||||
import { ScriptStub } from './../../../stubs/ScriptStub';
|
||||
import { ApplicationStub } from './../../../stubs/ApplicationStub';
|
||||
import { UserSelection } from '@/application/State/Selection/UserSelection';
|
||||
import { ApplicationCode } from '@/application/State/Code/ApplicationCode';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
||||
|
||||
describe('ApplicationCode', () => {
|
||||
describe('ctor', () => {
|
||||
it('empty when selection is empty', () => {
|
||||
// arrange
|
||||
const selection = new UserSelection(new ApplicationStub(), []);
|
||||
const sut = new ApplicationCode(selection, 'version');
|
||||
// act
|
||||
const actual = sut.current;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(0);
|
||||
});
|
||||
it('has code when selection is not empty', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const app = new ApplicationStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const selection = new UserSelection(app, scripts);
|
||||
const version = 'version-string';
|
||||
const sut = new ApplicationCode(selection, version);
|
||||
// act
|
||||
const actual = sut.current;
|
||||
// assert
|
||||
expect(actual).to.have.length.greaterThan(0).and.include(version);
|
||||
});
|
||||
});
|
||||
describe('user selection changes', () => {
|
||||
it('empty when selection is empty', () => {
|
||||
// arrange
|
||||
let signaled: string;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const app = new ApplicationStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const selection = new UserSelection(app, scripts);
|
||||
const sut = new ApplicationCode(selection, 'version');
|
||||
sut.changed.on((code) => signaled = code);
|
||||
// act
|
||||
selection.changed.notify([]);
|
||||
// assert
|
||||
expect(signaled).to.have.lengthOf(0);
|
||||
expect(signaled).to.equal(sut.current);
|
||||
});
|
||||
it('has code when selection is not empty', () => {
|
||||
// arrange
|
||||
let signaled: string;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const app = new ApplicationStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const selection = new UserSelection(app, scripts);
|
||||
const version = 'version-string';
|
||||
const sut = new ApplicationCode(selection, version);
|
||||
sut.changed.on((code) => signaled = code);
|
||||
// act
|
||||
selection.changed.notify(scripts.map((s) => new SelectedScript(s, false)));
|
||||
// assert
|
||||
expect(signaled).to.have.length.greaterThan(0).and.include(version);
|
||||
expect(signaled).to.equal(sut.current);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { ScriptStub } from './../../../stubs/ScriptStub';
|
||||
import { UserScriptGenerator, adminRightsScript } from '@/application/State/Code/UserScriptGenerator';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
||||
|
||||
describe('UserScriptGenerator', () => {
|
||||
it('adds version', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
// arrange
|
||||
const version = '1.5.0';
|
||||
const selectedScripts = [ new SelectedScript(new ScriptStub('id'), false)];
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, version);
|
||||
// assert
|
||||
expect(actual).to.include(version);
|
||||
});
|
||||
it('adds admin rights function', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
// arrange
|
||||
const selectedScripts = [ new SelectedScript(new ScriptStub('id'), false)];
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, 'non-important-version');
|
||||
// assert
|
||||
expect(actual).to.include(adminRightsScript.code);
|
||||
expect(actual).to.include(adminRightsScript.name);
|
||||
});
|
||||
it('appends revert script', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
// arrange
|
||||
const scriptName = 'test non-revert script';
|
||||
const scriptCode = 'REM nop';
|
||||
const script = new ScriptStub('id').withName(scriptName).withRevertCode(scriptCode);
|
||||
const selectedScripts = [ new SelectedScript(script, true)];
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, 'non-important-version');
|
||||
// assert
|
||||
expect(actual).to.include(`${scriptName} (revert)`);
|
||||
expect(actual).to.include(scriptCode);
|
||||
});
|
||||
it('appends non-revert script', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
// arrange
|
||||
const scriptName = 'test non-revert script';
|
||||
const scriptCode = 'REM nop';
|
||||
const script = new ScriptStub('id').withName(scriptName).withCode(scriptCode);
|
||||
const selectedScripts = [ new SelectedScript(script, false)];
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, 'non-important-version');
|
||||
// assert
|
||||
expect(actual).to.include(scriptName);
|
||||
expect(actual).to.include(scriptCode);
|
||||
});
|
||||
});
|
||||
46
tests/unit/application/State/Filter/FilterResult.spec.ts
Normal file
46
tests/unit/application/State/Filter/FilterResult.spec.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { CategoryStub } from './../../../stubs/CategoryStub';
|
||||
import { ScriptStub } from './../../../stubs/ScriptStub';
|
||||
import { FilterResult } from '@/application/State/Filter/FilterResult';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('FilterResult', () => {
|
||||
describe('hasAnyMatches', () => {
|
||||
it('false when no matches', () => {
|
||||
const sut = new FilterResult(
|
||||
/* scriptMatches */ [],
|
||||
/* categoryMatches */ [],
|
||||
'query',
|
||||
);
|
||||
const actual = sut.hasAnyMatches();
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('true when script matches', () => {
|
||||
const sut = new FilterResult(
|
||||
/* scriptMatches */ [ new ScriptStub('id') ],
|
||||
/* categoryMatches */ [],
|
||||
'query',
|
||||
);
|
||||
const actual = sut.hasAnyMatches();
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
it('true when category matches', () => {
|
||||
const sut = new FilterResult(
|
||||
/* scriptMatches */ [ ],
|
||||
/* categoryMatches */ [ new CategoryStub(5) ],
|
||||
'query',
|
||||
);
|
||||
const actual = sut.hasAnyMatches();
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
it('true when script + category matches', () => {
|
||||
const sut = new FilterResult(
|
||||
/* scriptMatches */ [ new ScriptStub('id') ],
|
||||
/* categoryMatches */ [ new CategoryStub(5) ],
|
||||
'query',
|
||||
);
|
||||
const actual = sut.hasAnyMatches();
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
135
tests/unit/application/State/Filter/UserFilter.spec.ts
Normal file
135
tests/unit/application/State/Filter/UserFilter.spec.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { CategoryStub } from './../../../stubs/CategoryStub';
|
||||
import { ScriptStub } from './../../../stubs/ScriptStub';
|
||||
import { IFilterResult } from '@/application/State/Filter/IFilterResult';
|
||||
import { ApplicationStub } from './../../../stubs/ApplicationStub';
|
||||
import { UserFilter } from '@/application/State/Filter/UserFilter';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('UserFilter', () => {
|
||||
it('signals when removing filter', () => {
|
||||
// arrange
|
||||
let isCalled = false;
|
||||
const sut = new UserFilter(new ApplicationStub());
|
||||
sut.filterRemoved.on(() => isCalled = true);
|
||||
// act
|
||||
sut.removeFilter();
|
||||
// assert
|
||||
expect(isCalled).to.be.equal(true);
|
||||
});
|
||||
it('signals when no matches', () => {
|
||||
// arrange
|
||||
let actual: IFilterResult;
|
||||
const nonMatchingFilter = 'non matching filter';
|
||||
const sut = new UserFilter(new ApplicationStub());
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(nonMatchingFilter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(false);
|
||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||
expect(actual.scriptMatches).to.have.lengthOf(0);
|
||||
expect(actual.query).to.equal(nonMatchingFilter);
|
||||
});
|
||||
describe('signals when script matches', () => {
|
||||
it('code matches', () => {
|
||||
// arrange
|
||||
const code = 'HELLO world';
|
||||
const filter = 'Hello WoRLD';
|
||||
let actual: IFilterResult;
|
||||
const script = new ScriptStub('id').withCode(code);
|
||||
const category = new CategoryStub(33).withScript(script);
|
||||
const sut = new UserFilter(new ApplicationStub()
|
||||
.withAction(category));
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(filter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(true);
|
||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||
expect(actual.query).to.equal(filter);
|
||||
});
|
||||
it('revertCode matches', () => {
|
||||
// arrange
|
||||
const revertCode = 'HELLO world';
|
||||
const filter = 'Hello WoRLD';
|
||||
let actual: IFilterResult;
|
||||
const script = new ScriptStub('id').withRevertCode(revertCode);
|
||||
const category = new CategoryStub(33).withScript(script);
|
||||
const sut = new UserFilter(new ApplicationStub()
|
||||
.withAction(category));
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(filter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(true);
|
||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||
expect(actual.query).to.equal(filter);
|
||||
});
|
||||
it('name matches', () => {
|
||||
// arrange
|
||||
const name = 'HELLO world';
|
||||
const filter = 'Hello WoRLD';
|
||||
let actual: IFilterResult;
|
||||
const script = new ScriptStub('id').withName(name);
|
||||
const category = new CategoryStub(33).withScript(script);
|
||||
const sut = new UserFilter(new ApplicationStub()
|
||||
.withAction(category));
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(filter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(true);
|
||||
expect(actual.categoryMatches).to.have.lengthOf(0);
|
||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||
expect(actual.query).to.equal(filter);
|
||||
});
|
||||
});
|
||||
it('signals when category matches', () => {
|
||||
// arrange
|
||||
const categoryName = 'HELLO world';
|
||||
const filter = 'Hello WoRLD';
|
||||
let actual: IFilterResult;
|
||||
const category = new CategoryStub(55).withName(categoryName);
|
||||
const sut = new UserFilter(new ApplicationStub()
|
||||
.withAction(category));
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(filter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(true);
|
||||
expect(actual.categoryMatches).to.have.lengthOf(1);
|
||||
expect(actual.categoryMatches[0]).to.deep.equal(category);
|
||||
expect(actual.scriptMatches).to.have.lengthOf(0);
|
||||
expect(actual.query).to.equal(filter);
|
||||
});
|
||||
it('signals when category and script matches', () => {
|
||||
// arrange
|
||||
const matchingText = 'HELLO world';
|
||||
const filter = 'Hello WoRLD';
|
||||
let actual: IFilterResult;
|
||||
const script = new ScriptStub('script')
|
||||
.withName(matchingText);
|
||||
const category = new CategoryStub(55)
|
||||
.withName(matchingText)
|
||||
.withScript(script);
|
||||
const app = new ApplicationStub()
|
||||
.withAction(category);
|
||||
const sut = new UserFilter(app);
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(filter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(true);
|
||||
expect(actual.categoryMatches).to.have.lengthOf(1);
|
||||
expect(actual.categoryMatches[0]).to.deep.equal(category);
|
||||
expect(actual.scriptMatches).to.have.lengthOf(1);
|
||||
expect(actual.scriptMatches[0]).to.deep.equal(script);
|
||||
expect(actual.query).to.equal(filter);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ScriptStub } from './../../../stubs/ScriptStub';
|
||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('SelectedScript', () => {
|
||||
it('id is same as script id', () => {
|
||||
// arrange
|
||||
const expectedId = 'scriptId';
|
||||
const script = new ScriptStub(expectedId);
|
||||
const sut = new SelectedScript(script, false);
|
||||
// act
|
||||
const actualId = sut.id;
|
||||
// assert
|
||||
expect(actualId).to.equal(expectedId);
|
||||
});
|
||||
it('throws when revert is true for irreversible script', () => {
|
||||
// arrange
|
||||
const expectedId = 'scriptId';
|
||||
const script = new ScriptStub(expectedId)
|
||||
.withRevertCode(undefined);
|
||||
// act
|
||||
function construct() { new SelectedScript(script, true); } // tslint:disable-line:no-unused-expression
|
||||
// assert
|
||||
expect(construct).to.throw('cannot revert an irreversible script');
|
||||
});
|
||||
|
||||
});
|
||||
96
tests/unit/application/State/Selection/UserSelection.spec.ts
Normal file
96
tests/unit/application/State/Selection/UserSelection.spec.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { ScriptStub } from './../../../stubs/ScriptStub';
|
||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
||||
import { CategoryStub } from '../../../stubs/CategoryStub';
|
||||
import { ApplicationStub } from '../../../stubs/ApplicationStub';
|
||||
import { UserSelection } from '@/application/State/Selection/UserSelection';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { IScript } from '@/domain/IScript';
|
||||
|
||||
describe('UserSelection', () => {
|
||||
it('deselectAll removes all items', () => {
|
||||
// arrange
|
||||
const events: Array<readonly SelectedScript[]> = [];
|
||||
const app = new ApplicationStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScriptIds('s1', 's2', 's3', 's4'));
|
||||
const selectedScripts = [new ScriptStub('s1'), new ScriptStub('s2'), new ScriptStub('s3')];
|
||||
const sut = new UserSelection(app, selectedScripts);
|
||||
sut.changed.on((newScripts) => events.push(newScripts));
|
||||
// act
|
||||
sut.deselectAll();
|
||||
// assert
|
||||
expect(sut.selectedScripts).to.have.length(0);
|
||||
expect(events).to.have.lengthOf(1);
|
||||
expect(events[0]).to.have.length(0);
|
||||
});
|
||||
it('selectOnly selects expected', () => {
|
||||
// arrange
|
||||
const events: Array<readonly SelectedScript[]> = [];
|
||||
const app = new ApplicationStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScriptIds('s1', 's2', 's3', 's4'));
|
||||
const selectedScripts = [new ScriptStub('s1'), new ScriptStub('s2'), new ScriptStub('s3')];
|
||||
const sut = new UserSelection(app, selectedScripts);
|
||||
sut.changed.on((newScripts) => events.push(newScripts));
|
||||
const scripts = [new ScriptStub('s2'), new ScriptStub('s3'), new ScriptStub('s4')];
|
||||
const expected = scripts.map((script) => new SelectedScript(script, false));
|
||||
// act
|
||||
sut.selectOnly(scripts);
|
||||
// assert
|
||||
expect(sut.selectedScripts).to.deep.equal(expected);
|
||||
expect(events).to.have.lengthOf(1);
|
||||
expect(events[0]).to.deep.equal(expected);
|
||||
});
|
||||
it('selectAll selects as expected', () => {
|
||||
// arrange
|
||||
const events: Array<readonly SelectedScript[]> = [];
|
||||
const scripts: IScript[] = [new ScriptStub('s1'), new ScriptStub('s2'), new ScriptStub('s3'), new ScriptStub('s4')];
|
||||
const app = new ApplicationStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(...scripts));
|
||||
const sut = new UserSelection(app, []);
|
||||
sut.changed.on((newScripts) => events.push(newScripts));
|
||||
const expected = scripts.map((script) => new SelectedScript(script, false));
|
||||
// act
|
||||
sut.selectAll();
|
||||
// assert
|
||||
expect(sut.selectedScripts).to.deep.equal(expected);
|
||||
expect(events).to.have.lengthOf(1);
|
||||
expect(events[0]).to.deep.equal(expected);
|
||||
});
|
||||
describe('addOrUpdateSelectedScript', () => {
|
||||
it('adds when item does not exist', () => {
|
||||
// arrange
|
||||
const events: Array<readonly SelectedScript[]> = [];
|
||||
const app = new ApplicationStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(new ScriptStub('s1'), new ScriptStub('s2')));
|
||||
const sut = new UserSelection(app, []);
|
||||
sut.changed.on((scripts) => events.push(scripts));
|
||||
const expected = [ new SelectedScript(new ScriptStub('s1'), false) ];
|
||||
// act
|
||||
sut.addOrUpdateSelectedScript('s1', false);
|
||||
// assert
|
||||
expect(sut.selectedScripts).to.deep.equal(expected);
|
||||
expect(events).to.have.lengthOf(1);
|
||||
expect(events[0]).to.deep.equal(expected);
|
||||
});
|
||||
it('updates when item exists', () => {
|
||||
// arrange
|
||||
const events: Array<readonly SelectedScript[]> = [];
|
||||
const app = new ApplicationStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(new ScriptStub('s1'), new ScriptStub('s2')));
|
||||
const sut = new UserSelection(app, []);
|
||||
sut.changed.on((scripts) => events.push(scripts));
|
||||
const expected = [ new SelectedScript(new ScriptStub('s1'), true) ];
|
||||
// act
|
||||
sut.addOrUpdateSelectedScript('s1', true);
|
||||
// assert
|
||||
expect(sut.selectedScripts).to.deep.equal(expected);
|
||||
expect(events).to.have.lengthOf(1);
|
||||
expect(events[0]).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user