Refactor code to comply with ESLint rules
Major refactoring using ESLint with rules from AirBnb and Vue. Enable most of the ESLint rules and do necessary linting in the code. Also add more information for rules that are disabled to describe what they are and why they are disabled. Allow logging (`console.log`) in test files, and in development mode (e.g. when working with `npm run serve`), but disable it when environment is production (as pre-configured by Vue). Also add flag (`--mode production`) in `lint:eslint` command so production linting is executed earlier in lifecycle. Disable rules that requires a separate work. Such as ESLint rules that are broken in TypeScript: no-useless-constructor (eslint/eslint#14118) and no-shadow (eslint/eslint#13014).
This commit is contained in:
@@ -10,92 +10,94 @@ import { CategoryStub } from '@tests/unit/stubs/CategoryStub';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
|
||||
describe('CategoryCollectionState', () => {
|
||||
describe('code', () => {
|
||||
it('initialized with empty code', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub();
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
const code = sut.code.current;
|
||||
// assert
|
||||
expect(!code);
|
||||
});
|
||||
it('reacts to selection changes as expected', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(0).withScriptIds('scriptId'));
|
||||
const selectionStub = new UserSelection(collection, []);
|
||||
const expectedCodeGenerator = new ApplicationCode(selectionStub, collection.scripting);
|
||||
selectionStub.selectAll();
|
||||
const expectedCode = expectedCodeGenerator.current;
|
||||
// act
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
sut.selection.selectAll();
|
||||
const actualCode = sut.code.current;
|
||||
// assert
|
||||
expect(actualCode).to.equal(expectedCode);
|
||||
});
|
||||
describe('code', () => {
|
||||
it('initialized with empty code', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub();
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
const code = sut.code.current;
|
||||
// assert
|
||||
expect(!code);
|
||||
});
|
||||
describe('os', () => {
|
||||
it('same as its collection', () => {
|
||||
// arrange
|
||||
const expected = OperatingSystem.macOS;
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withOs(expected);
|
||||
// act
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// assert
|
||||
const actual = sut.os;
|
||||
expect(expected).to.equal(actual);
|
||||
});
|
||||
it('reacts to selection changes as expected', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(0).withScriptIds('scriptId'));
|
||||
const selectionStub = new UserSelection(collection, []);
|
||||
const expectedCodeGenerator = new ApplicationCode(selectionStub, collection.scripting);
|
||||
selectionStub.selectAll();
|
||||
const expectedCode = expectedCodeGenerator.current;
|
||||
// act
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
sut.selection.selectAll();
|
||||
const actualCode = sut.code.current;
|
||||
// assert
|
||||
expect(actualCode).to.equal(expectedCode);
|
||||
});
|
||||
describe('selection', () => {
|
||||
it('initialized with no selection', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub();
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
const actual = sut.selection.selectedScripts.length;
|
||||
// assert
|
||||
expect(actual).to.equal(0);
|
||||
});
|
||||
it('can select a script from current collection', () => {
|
||||
// arrange
|
||||
const expectedScript = new ScriptStub('scriptId');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(0).withScript(expectedScript));
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
sut.selection.selectAll();
|
||||
// assert
|
||||
expect(sut.selection.selectedScripts.length).to.equal(1);
|
||||
expect(sut.selection.isSelected(expectedScript.id)).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('os', () => {
|
||||
it('same as its collection', () => {
|
||||
// arrange
|
||||
const expected = OperatingSystem.macOS;
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withOs(expected);
|
||||
// act
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// assert
|
||||
const actual = sut.os;
|
||||
expect(expected).to.equal(actual);
|
||||
});
|
||||
describe('filter', () => {
|
||||
it('initialized with an empty filter', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub();
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
const actual = sut.filter.currentFilter;
|
||||
// assert
|
||||
expect(actual).to.equal(undefined);
|
||||
});
|
||||
it('can match a script from current collection', () => {
|
||||
// arrange
|
||||
const scriptNameFilter = 'scriptName';
|
||||
const expectedScript = new ScriptStub('scriptId')
|
||||
.withName(scriptNameFilter);
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(0).withScript(expectedScript));
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
let actualScript: IScript;
|
||||
sut.filter.filtered.on((result) => actualScript = result.scriptMatches[0]);
|
||||
sut.filter.setFilter(scriptNameFilter);
|
||||
// assert
|
||||
expect(expectedScript).to.equal(actualScript);
|
||||
});
|
||||
});
|
||||
describe('selection', () => {
|
||||
it('initialized with no selection', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub();
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
const actual = sut.selection.selectedScripts.length;
|
||||
// assert
|
||||
expect(actual).to.equal(0);
|
||||
});
|
||||
it('can select a script from current collection', () => {
|
||||
// arrange
|
||||
const expectedScript = new ScriptStub('scriptId');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(0).withScript(expectedScript));
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
sut.selection.selectAll();
|
||||
// assert
|
||||
expect(sut.selection.selectedScripts.length).to.equal(1);
|
||||
expect(sut.selection.isSelected(expectedScript.id)).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('filter', () => {
|
||||
it('initialized with an empty filter', () => {
|
||||
// arrange
|
||||
const collection = new CategoryCollectionStub();
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
const actual = sut.filter.currentFilter;
|
||||
// assert
|
||||
expect(actual).to.equal(undefined);
|
||||
});
|
||||
it('can match a script from current collection', () => {
|
||||
// arrange
|
||||
const scriptNameFilter = 'scriptName';
|
||||
const expectedScript = new ScriptStub('scriptId')
|
||||
.withName(scriptNameFilter);
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(0).withScript(expectedScript));
|
||||
const sut = new CategoryCollectionState(collection);
|
||||
// act
|
||||
let actualScript: IScript;
|
||||
sut.filter.filtered.on((result) => {
|
||||
[actualScript] = result.scriptMatches;
|
||||
});
|
||||
sut.filter.setFilter(scriptNameFilter);
|
||||
// assert
|
||||
expect(expectedScript).to.equal(actualScript);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,177 +15,194 @@ import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
|
||||
describe('ApplicationCode', () => {
|
||||
describe('ctor', () => {
|
||||
it('empty when selection is empty', () => {
|
||||
// arrange
|
||||
const selection = new UserSelection(new CategoryCollectionStub(), []);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const sut = new ApplicationCode(selection, definition);
|
||||
// act
|
||||
const actual = sut.current;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(0);
|
||||
describe('ctor', () => {
|
||||
it('empty when selection is empty', () => {
|
||||
// arrange
|
||||
const selection = new UserSelection(new CategoryCollectionStub(), []);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const sut = new ApplicationCode(selection, definition);
|
||||
// act
|
||||
const actual = sut.current;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(0);
|
||||
});
|
||||
it('generates code from script generator when selection is not empty', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const selectedScripts = scripts.map((script) => script.toSelectedScript());
|
||||
const selection = new UserSelection(collection, selectedScripts);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const expected: IUserScript = {
|
||||
code: 'expected-code',
|
||||
scriptPositions: new Map(),
|
||||
};
|
||||
const generator = new UserScriptGeneratorMock()
|
||||
.plan({ scripts: selection.selectedScripts, definition }, expected);
|
||||
const sut = new ApplicationCode(selection, definition, generator);
|
||||
// act
|
||||
const actual = sut.current;
|
||||
// assert
|
||||
expect(actual).to.equal(expected.code);
|
||||
});
|
||||
});
|
||||
describe('changed event', () => {
|
||||
describe('code', () => {
|
||||
it('empty when nothing is selected', () => {
|
||||
// arrange
|
||||
let signaled: ICodeChangedEvent;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const sut = new ApplicationCode(selection, definition);
|
||||
sut.changed.on((code) => {
|
||||
signaled = code;
|
||||
});
|
||||
it('generates code from script generator when selection is not empty', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const selection = new UserSelection(collection, scripts.map((script) => script.toSelectedScript()));
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const expected: IUserScript = {
|
||||
code: 'expected-code',
|
||||
scriptPositions: new Map(),
|
||||
// act
|
||||
selection.changed.notify([]);
|
||||
// assert
|
||||
expect(signaled.code).to.have.lengthOf(0);
|
||||
expect(signaled.code).to.equal(sut.current);
|
||||
});
|
||||
it('has code when some are selected', () => {
|
||||
// arrange
|
||||
let signaled: ICodeChangedEvent;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const sut = new ApplicationCode(selection, definition);
|
||||
sut.changed.on((code) => {
|
||||
signaled = code;
|
||||
});
|
||||
// act
|
||||
selection.changed.notify(scripts.map((s) => new SelectedScript(s, false)));
|
||||
// assert
|
||||
expect(signaled.code).to.have.length.greaterThan(0);
|
||||
expect(signaled.code).to.equal(sut.current);
|
||||
});
|
||||
});
|
||||
describe('calls UserScriptGenerator', () => {
|
||||
it('sends scripting definition to generator', () => {
|
||||
// arrange
|
||||
const expectedDefinition = new ScriptingDefinitionStub();
|
||||
const collection = new CategoryCollectionStub();
|
||||
const selection = new UserSelection(collection, []);
|
||||
const generatorMock: IUserScriptGenerator = {
|
||||
buildCode: (selectedScripts, definition) => {
|
||||
if (definition !== expectedDefinition) {
|
||||
throw new Error('Unexpected scripting definition');
|
||||
}
|
||||
return {
|
||||
code: '',
|
||||
scriptPositions: new Map<SelectedScript, ICodePosition>(),
|
||||
};
|
||||
const generator = new UserScriptGeneratorMock()
|
||||
.plan({ scripts: selection.selectedScripts, definition }, expected);
|
||||
const sut = new ApplicationCode(selection, definition, generator);
|
||||
// act
|
||||
const actual = sut.current;
|
||||
// assert
|
||||
expect(actual).to.equal(expected.code);
|
||||
});
|
||||
});
|
||||
describe('changed event', () => {
|
||||
describe('code', () => {
|
||||
it('empty when nothing is selected', () => {
|
||||
// arrange
|
||||
let signaled: ICodeChangedEvent;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const sut = new ApplicationCode(selection, definition);
|
||||
sut.changed.on((code) => signaled = code);
|
||||
// act
|
||||
selection.changed.notify([]);
|
||||
// assert
|
||||
expect(signaled.code).to.have.lengthOf(0);
|
||||
expect(signaled.code).to.equal(sut.current);
|
||||
});
|
||||
it('has code when some are selected', () => {
|
||||
// arrange
|
||||
let signaled: ICodeChangedEvent;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const sut = new ApplicationCode(selection, definition);
|
||||
sut.changed.on((code) => signaled = code);
|
||||
// act
|
||||
selection.changed.notify(scripts.map((s) => new SelectedScript(s, false)));
|
||||
// assert
|
||||
expect(signaled.code).to.have.length.greaterThan(0);
|
||||
expect(signaled.code).to.equal(sut.current);
|
||||
});
|
||||
});
|
||||
describe('calls UserScriptGenerator', () => {
|
||||
it('sends scripting definition to generator', () => {
|
||||
// arrange
|
||||
const expectedDefinition = new ScriptingDefinitionStub();
|
||||
const collection = new CategoryCollectionStub();
|
||||
const selection = new UserSelection(collection, []);
|
||||
const generatorMock: IUserScriptGenerator = {
|
||||
buildCode: (selectedScripts, definition) => {
|
||||
if (definition !== expectedDefinition) {
|
||||
throw new Error('Unexpected scripting definition');
|
||||
}
|
||||
return {
|
||||
code: '',
|
||||
scriptPositions: new Map<SelectedScript, ICodePosition>(),
|
||||
};
|
||||
},
|
||||
};
|
||||
new ApplicationCode(selection, expectedDefinition, generatorMock);
|
||||
// act
|
||||
const act = () => selection.changed.notify([]);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
it('sends selected scripts to generator', () => {
|
||||
// arrange
|
||||
const expectedDefinition = new ScriptingDefinitionStub();
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub().withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const generatorMock: IUserScriptGenerator = {
|
||||
buildCode: (selectedScripts) => {
|
||||
if (JSON.stringify(selectedScripts) !== JSON.stringify(scriptsToSelect)) {
|
||||
throw new Error('Unexpected scripts');
|
||||
}
|
||||
return {
|
||||
code: '',
|
||||
scriptPositions: new Map<SelectedScript, ICodePosition>(),
|
||||
};
|
||||
},
|
||||
};
|
||||
new ApplicationCode(selection, expectedDefinition, generatorMock);
|
||||
// act
|
||||
const act = () => selection.changed.notify(scriptsToSelect);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
it('sets positions from the generator', () => {
|
||||
// arrange
|
||||
let signaled: ICodeChangedEvent;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const scriptingDefinition = new ScriptingDefinitionStub();
|
||||
const totalLines = 20;
|
||||
const expected = new Map<SelectedScript, ICodePosition>(
|
||||
[
|
||||
[scriptsToSelect[0], new CodePosition(0, totalLines / 2)],
|
||||
[scriptsToSelect[1], new CodePosition(totalLines / 2, totalLines)],
|
||||
],
|
||||
);
|
||||
const generatorMock: IUserScriptGenerator = {
|
||||
buildCode: () => {
|
||||
return {
|
||||
code: '\nREM LINE'.repeat(totalLines),
|
||||
scriptPositions: expected,
|
||||
};
|
||||
},
|
||||
};
|
||||
const sut = new ApplicationCode(selection, scriptingDefinition, generatorMock);
|
||||
sut.changed.on((code) => signaled = code);
|
||||
// act
|
||||
selection.changed.notify(scriptsToSelect);
|
||||
// assert
|
||||
expect(signaled.getScriptPositionInCode(scripts[0]))
|
||||
.to.deep.equal(expected.get(scriptsToSelect[0]));
|
||||
expect(signaled.getScriptPositionInCode(scripts[1]))
|
||||
.to.deep.equal(expected.get(scriptsToSelect[1]));
|
||||
});
|
||||
},
|
||||
};
|
||||
// eslint-disable-next-line no-new
|
||||
new ApplicationCode(selection, expectedDefinition, generatorMock);
|
||||
// act
|
||||
const act = () => selection.changed.notify([]);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
it('sends selected scripts to generator', () => {
|
||||
// arrange
|
||||
const expectedDefinition = new ScriptingDefinitionStub();
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const generatorMock: IUserScriptGenerator = {
|
||||
buildCode: (selectedScripts) => {
|
||||
if (JSON.stringify(selectedScripts) !== JSON.stringify(scriptsToSelect)) {
|
||||
throw new Error('Unexpected scripts');
|
||||
}
|
||||
return {
|
||||
code: '',
|
||||
scriptPositions: new Map<SelectedScript, ICodePosition>(),
|
||||
};
|
||||
},
|
||||
};
|
||||
// eslint-disable-next-line no-new
|
||||
new ApplicationCode(selection, expectedDefinition, generatorMock);
|
||||
// act
|
||||
const act = () => selection.changed.notify(scriptsToSelect);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
it('sets positions from the generator', () => {
|
||||
// arrange
|
||||
let signaled: ICodeChangedEvent;
|
||||
const scripts = [new ScriptStub('first'), new ScriptStub('second')];
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1).withScripts(...scripts));
|
||||
const scriptsToSelect = scripts.map((script) => new SelectedScript(script, false));
|
||||
const selection = new UserSelection(collection, scriptsToSelect);
|
||||
const scriptingDefinition = new ScriptingDefinitionStub();
|
||||
const totalLines = 20;
|
||||
const expected = new Map<SelectedScript, ICodePosition>(
|
||||
[
|
||||
[scriptsToSelect[0], new CodePosition(0, totalLines / 2)],
|
||||
[scriptsToSelect[1], new CodePosition(totalLines / 2, totalLines)],
|
||||
],
|
||||
);
|
||||
const generatorMock: IUserScriptGenerator = {
|
||||
buildCode: () => {
|
||||
return {
|
||||
code: '\nREM LINE'.repeat(totalLines),
|
||||
scriptPositions: expected,
|
||||
};
|
||||
},
|
||||
};
|
||||
const sut = new ApplicationCode(selection, scriptingDefinition, generatorMock);
|
||||
sut.changed.on((code) => {
|
||||
signaled = code;
|
||||
});
|
||||
// act
|
||||
selection.changed.notify(scriptsToSelect);
|
||||
// assert
|
||||
expect(signaled.getScriptPositionInCode(scripts[0]))
|
||||
.to.deep.equal(expected.get(scriptsToSelect[0]));
|
||||
expect(signaled.getScriptPositionInCode(scripts[1]))
|
||||
.to.deep.equal(expected.get(scriptsToSelect[1]));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
interface IScriptGenerationParameters {
|
||||
scripts: readonly SelectedScript[];
|
||||
definition: IScriptingDefinition;
|
||||
scripts: readonly SelectedScript[];
|
||||
definition: IScriptingDefinition;
|
||||
}
|
||||
class UserScriptGeneratorMock implements IUserScriptGenerator {
|
||||
private prePlanned = new Map<IScriptGenerationParameters, IUserScript>();
|
||||
public plan(
|
||||
parameters: IScriptGenerationParameters,
|
||||
result: IUserScript): UserScriptGeneratorMock {
|
||||
this.prePlanned.set(parameters, result);
|
||||
return this;
|
||||
}
|
||||
public buildCode(
|
||||
selectedScripts: readonly SelectedScript[],
|
||||
scriptingDefinition: IScriptingDefinition): IUserScript {
|
||||
for (const [parameters, result] of Array.from(this.prePlanned)) {
|
||||
if (selectedScripts === parameters.scripts
|
||||
&& scriptingDefinition === parameters.definition) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new Error('Unexpected parameters');
|
||||
private prePlanned = new Map<IScriptGenerationParameters, IUserScript>();
|
||||
|
||||
public plan(
|
||||
parameters: IScriptGenerationParameters,
|
||||
result: IUserScript,
|
||||
): UserScriptGeneratorMock {
|
||||
this.prePlanned.set(parameters, result);
|
||||
return this;
|
||||
}
|
||||
|
||||
public buildCode(
|
||||
selectedScripts: readonly SelectedScript[],
|
||||
scriptingDefinition: IScriptingDefinition,
|
||||
): IUserScript {
|
||||
for (const [parameters, result] of Array.from(this.prePlanned)) {
|
||||
if (selectedScripts === parameters.scripts
|
||||
&& scriptingDefinition === parameters.definition) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new Error('Unexpected parameters');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,140 +8,204 @@ import { SelectedScriptStub } from '@tests/unit/stubs/SelectedScriptStub';
|
||||
import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
|
||||
describe('CodeChangedEvent', () => {
|
||||
describe('ctor', () => {
|
||||
describe('position validation', () => {
|
||||
it('throws when code position is out of range', () => {
|
||||
const act = () => new CodeChangedEvent(
|
||||
'singleline code', [], new Map<SelectedScript, ICodePosition>([
|
||||
[ new SelectedScriptStub('1'), new CodePosition(0, 2) ],
|
||||
]),
|
||||
);
|
||||
expect(act).to.throw();
|
||||
});
|
||||
it('does not throw with valid code position', () => {
|
||||
const act = () => new CodeChangedEvent(
|
||||
'singleline code', [], new Map<SelectedScript, ICodePosition>([
|
||||
[ new SelectedScriptStub('1'), new CodePosition(0, 1) ],
|
||||
]),
|
||||
);
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
});
|
||||
});
|
||||
it('code returns expected', () => {
|
||||
describe('ctor', () => {
|
||||
describe('position validation', () => {
|
||||
it('throws when code position is out of range', () => {
|
||||
// arrange
|
||||
const expected = 'code';
|
||||
const code = 'singleline code';
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[new SelectedScriptStub('1'), new CodePosition(0, 2 /* nonexisting line */)],
|
||||
]);
|
||||
// act
|
||||
const sut = new CodeChangedEvent(
|
||||
expected, [], new Map<SelectedScript, ICodePosition>(),
|
||||
);
|
||||
const actual = sut.code;
|
||||
const act = () => new CodeChangedEventBuilder()
|
||||
.withCode(code)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// assert
|
||||
expect(actual).to.equal(expected);
|
||||
});
|
||||
describe('addedScripts', () => {
|
||||
it('returns new scripts when scripts are added', () => {
|
||||
// arrange
|
||||
const expected = [ new ScriptStub('3'), new ScriptStub('4') ];
|
||||
const initialScripts = [ new SelectedScriptStub('1'), new SelectedScriptStub('2') ];
|
||||
expect(act).to.throw();
|
||||
});
|
||||
describe('does not throw with valid code position', () => {
|
||||
// arrange
|
||||
const testCases = [
|
||||
{
|
||||
name: 'singleline',
|
||||
code: 'singleline code',
|
||||
position: new CodePosition(0, 1),
|
||||
},
|
||||
{
|
||||
name: 'multiline',
|
||||
code: 'multiline code\nsecond line',
|
||||
position: new CodePosition(0, 2),
|
||||
},
|
||||
];
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[initialScripts[0], new CodePosition(0, 1) ],
|
||||
[initialScripts[1], new CodePosition(0, 1) ],
|
||||
[new SelectedScript(expected[0], false), new CodePosition(0, 1) ],
|
||||
[new SelectedScript(expected[1], false), new CodePosition(0, 1) ],
|
||||
[new SelectedScriptStub('1'), testCase.position],
|
||||
]);
|
||||
// act
|
||||
const sut = new CodeChangedEvent(
|
||||
'code', initialScripts, newScripts,
|
||||
);
|
||||
const actual = sut.addedScripts;
|
||||
const act = () => new CodeChangedEventBuilder()
|
||||
.withCode(testCase.code)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(2);
|
||||
expect(actual[0]).to.deep.equal(expected[0]);
|
||||
expect(actual[1]).to.deep.equal(expected[1]);
|
||||
});
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
describe('removedScripts', () => {
|
||||
it('returns removed scripts when script are removed', () => {
|
||||
// arrange
|
||||
const existingScripts = [ new SelectedScriptStub('0'), new SelectedScriptStub('1') ];
|
||||
const removedScripts = [ new SelectedScriptStub('2') ];
|
||||
const initialScripts = [ ...existingScripts, ...removedScripts ];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[initialScripts[0], new CodePosition(0, 1) ],
|
||||
[initialScripts[1], new CodePosition(0, 1) ],
|
||||
]);
|
||||
// act
|
||||
const sut = new CodeChangedEvent(
|
||||
'code', initialScripts, newScripts,
|
||||
);
|
||||
const actual = sut.removedScripts;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(removedScripts.length);
|
||||
expect(actual[0]).to.deep.equal(removedScripts[0].script);
|
||||
});
|
||||
});
|
||||
it('code returns expected', () => {
|
||||
// arrange
|
||||
const expected = 'code';
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withCode(expected)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.code;
|
||||
// assert
|
||||
expect(actual).to.equal(expected);
|
||||
});
|
||||
describe('addedScripts', () => {
|
||||
it('returns new scripts when scripts are added', () => {
|
||||
// arrange
|
||||
const expected = [new ScriptStub('3'), new ScriptStub('4')];
|
||||
const initialScripts = [new SelectedScriptStub('1'), new SelectedScriptStub('2')];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[initialScripts[0], new CodePosition(0, 1)],
|
||||
[initialScripts[1], new CodePosition(0, 1)],
|
||||
[new SelectedScript(expected[0], false), new CodePosition(0, 1)],
|
||||
[new SelectedScript(expected[1], false), new CodePosition(0, 1)],
|
||||
]);
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withOldScripts(initialScripts)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.addedScripts;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(2);
|
||||
expect(actual[0]).to.deep.equal(expected[0]);
|
||||
expect(actual[1]).to.deep.equal(expected[1]);
|
||||
});
|
||||
describe('changedScripts', () => {
|
||||
it('returns changed scripts when scripts are changed', () => {
|
||||
// arrange
|
||||
const initialScripts = [ new SelectedScriptStub('1', false), new SelectedScriptStub('2', false) ];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[new SelectedScriptStub('1', true), new CodePosition(0, 1) ],
|
||||
[new SelectedScriptStub('2', false), new CodePosition(0, 1) ],
|
||||
]);
|
||||
// act
|
||||
const sut = new CodeChangedEvent(
|
||||
'code', initialScripts, newScripts,
|
||||
);
|
||||
const actual = sut.changedScripts;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(1);
|
||||
expect(actual[0]).to.deep.equal(initialScripts[0].script);
|
||||
});
|
||||
});
|
||||
describe('removedScripts', () => {
|
||||
it('returns removed scripts when script are removed', () => {
|
||||
// arrange
|
||||
const existingScripts = [new SelectedScriptStub('0'), new SelectedScriptStub('1')];
|
||||
const removedScripts = [new SelectedScriptStub('2')];
|
||||
const initialScripts = [...existingScripts, ...removedScripts];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[initialScripts[0], new CodePosition(0, 1)],
|
||||
[initialScripts[1], new CodePosition(0, 1)],
|
||||
]);
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withOldScripts(initialScripts)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.removedScripts;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(removedScripts.length);
|
||||
expect(actual[0]).to.deep.equal(removedScripts[0].script);
|
||||
});
|
||||
describe('isEmpty', () => {
|
||||
it('returns true when empty', () => {
|
||||
// arrange
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>();
|
||||
const oldScripts = [ new SelectedScriptStub('1', false) ];
|
||||
const sut = new CodeChangedEvent(
|
||||
'code', oldScripts, newScripts,
|
||||
);
|
||||
// act
|
||||
const actual = sut.isEmpty();
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
it('returns false when not empty', () => {
|
||||
// arrange
|
||||
const oldScripts = [ new SelectedScriptStub('1') ];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>( [
|
||||
[oldScripts[0], new CodePosition(0, 1) ],
|
||||
]);
|
||||
const sut = new CodeChangedEvent(
|
||||
'code', oldScripts, newScripts,
|
||||
);
|
||||
// act
|
||||
const actual = sut.isEmpty();
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('changedScripts', () => {
|
||||
it('returns changed scripts when scripts are changed', () => {
|
||||
// arrange
|
||||
const initialScripts = [new SelectedScriptStub('1', false), new SelectedScriptStub('2', false)];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[new SelectedScriptStub('1', true), new CodePosition(0, 1)],
|
||||
[new SelectedScriptStub('2', false), new CodePosition(0, 1)],
|
||||
]);
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withOldScripts(initialScripts)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.changedScripts;
|
||||
// assert
|
||||
expect(actual).to.have.lengthOf(1);
|
||||
expect(actual[0]).to.deep.equal(initialScripts[0].script);
|
||||
});
|
||||
describe('getScriptPositionInCode', () => {
|
||||
it('returns expected position for existing script', () => {
|
||||
// arrange
|
||||
const script = new ScriptStub('1');
|
||||
const expected = new CodePosition(0, 1);
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>( [
|
||||
[new SelectedScript(script, false), expected ],
|
||||
]);
|
||||
const sut = new CodeChangedEvent(
|
||||
'code', [], newScripts,
|
||||
);
|
||||
// act
|
||||
const actual = sut.getScriptPositionInCode(script);
|
||||
// assert
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
describe('isEmpty', () => {
|
||||
it('returns true when empty', () => {
|
||||
// arrange
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>();
|
||||
const oldScripts = [new SelectedScriptStub('1', false)];
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withOldScripts(oldScripts)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.isEmpty();
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
it('returns false when not empty', () => {
|
||||
// arrange
|
||||
const oldScripts = [new SelectedScriptStub('1')];
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[oldScripts[0], new CodePosition(0, 1)],
|
||||
]);
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withOldScripts(oldScripts)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.isEmpty();
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('getScriptPositionInCode', () => {
|
||||
it('returns expected position for existing script', () => {
|
||||
// arrange
|
||||
const script = new ScriptStub('1');
|
||||
const expected = new CodePosition(0, 1);
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[new SelectedScript(script, false), expected],
|
||||
]);
|
||||
const sut = new CodeChangedEventBuilder()
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
// act
|
||||
const actual = sut.getScriptPositionInCode(script);
|
||||
// assert
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Prefer over original ctor in tests for easier future ctor refactorings
|
||||
class CodeChangedEventBuilder {
|
||||
private code = '[CodeChangedEventBuilder] default code';
|
||||
|
||||
private oldScripts: ReadonlyArray<SelectedScript> = [];
|
||||
|
||||
private newScripts = new Map<SelectedScript, ICodePosition>();
|
||||
|
||||
public withCode(code: string) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public withOldScripts(oldScripts: ReadonlyArray<SelectedScript>) {
|
||||
this.oldScripts = oldScripts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public withNewScripts(newScripts: Map<SelectedScript, ICodePosition>) {
|
||||
this.newScripts = newScripts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public build(): CodeChangedEvent {
|
||||
return new CodeChangedEvent(
|
||||
this.code,
|
||||
this.oldScripts,
|
||||
this.newScripts,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,134 +3,137 @@ import { expect } from 'chai';
|
||||
import { CodeBuilder } from '@/application/Context/State/Code/Generation/CodeBuilder';
|
||||
|
||||
describe('CodeBuilder', () => {
|
||||
class CodeBuilderConcrete extends CodeBuilder {
|
||||
private commentDelimiter = '//';
|
||||
public withCommentDelimiter(delimiter: string): CodeBuilderConcrete {
|
||||
this.commentDelimiter = delimiter;
|
||||
return this;
|
||||
}
|
||||
protected getCommentDelimiter(): string {
|
||||
return this.commentDelimiter;
|
||||
}
|
||||
protected writeStandardOut(text: string): string {
|
||||
return text;
|
||||
}
|
||||
class CodeBuilderConcrete extends CodeBuilder {
|
||||
private commentDelimiter = '//';
|
||||
|
||||
public withCommentDelimiter(delimiter: string): CodeBuilderConcrete {
|
||||
this.commentDelimiter = delimiter;
|
||||
return this;
|
||||
}
|
||||
describe('appendLine', () => {
|
||||
it('when empty appends empty line', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine().appendLine().appendLine();
|
||||
// assert
|
||||
expect(sut.toString()).to.equal('\n\n');
|
||||
});
|
||||
it('when not empty append string in new line', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
const expected = 'str';
|
||||
// act
|
||||
sut.appendLine()
|
||||
.appendLine(expected);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
expect(lines[1]).to.equal('str');
|
||||
});
|
||||
|
||||
protected getCommentDelimiter(): string {
|
||||
return this.commentDelimiter;
|
||||
}
|
||||
|
||||
protected writeStandardOut(text: string): string {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
describe('appendLine', () => {
|
||||
it('when empty appends empty line', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine().appendLine().appendLine();
|
||||
// assert
|
||||
expect(sut.toString()).to.equal('\n\n');
|
||||
});
|
||||
it('appendFunction', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
const functionName = 'function';
|
||||
const code = 'code';
|
||||
// act
|
||||
sut.appendFunction(functionName, code);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
expect(result).to.include(functionName);
|
||||
expect(result).to.include(code);
|
||||
it('when not empty append string in new line', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
const expected = 'str';
|
||||
// act
|
||||
sut.appendLine()
|
||||
.appendLine(expected);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
expect(lines[1]).to.equal('str');
|
||||
});
|
||||
it('appendTrailingHyphensCommentLine', () => {
|
||||
// arrange
|
||||
const commentDelimiter = '//';
|
||||
const sut = new CodeBuilderConcrete()
|
||||
.withCommentDelimiter(commentDelimiter);
|
||||
const totalHyphens = 5;
|
||||
const expected = `${commentDelimiter} ${'-'.repeat(totalHyphens)}`;
|
||||
// act
|
||||
sut.appendTrailingHyphensCommentLine(totalHyphens);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
expect(lines[0]).to.equal(expected);
|
||||
});
|
||||
it('appendFunction', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
const functionName = 'function';
|
||||
const code = 'code';
|
||||
// act
|
||||
sut.appendFunction(functionName, code);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
expect(result).to.include(functionName);
|
||||
expect(result).to.include(code);
|
||||
});
|
||||
it('appendTrailingHyphensCommentLine', () => {
|
||||
// arrange
|
||||
const commentDelimiter = '//';
|
||||
const sut = new CodeBuilderConcrete()
|
||||
.withCommentDelimiter(commentDelimiter);
|
||||
const totalHyphens = 5;
|
||||
const expected = `${commentDelimiter} ${'-'.repeat(totalHyphens)}`;
|
||||
// act
|
||||
sut.appendTrailingHyphensCommentLine(totalHyphens);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
expect(lines[0]).to.equal(expected);
|
||||
});
|
||||
it('appendCommentLine', () => {
|
||||
// arrange
|
||||
const commentDelimiter = '//';
|
||||
const sut = new CodeBuilderConcrete()
|
||||
.withCommentDelimiter(commentDelimiter);
|
||||
const comment = 'comment';
|
||||
const expected = `${commentDelimiter} comment`;
|
||||
// act
|
||||
const result = sut
|
||||
.appendCommentLine(comment)
|
||||
.toString();
|
||||
// assert
|
||||
const lines = getLines(result);
|
||||
expect(lines[0]).to.equal(expected);
|
||||
});
|
||||
it('appendCommentLineWithHyphensAround', () => {
|
||||
// arrange
|
||||
const commentDelimiter = '//';
|
||||
const sut = new CodeBuilderConcrete()
|
||||
.withCommentDelimiter(commentDelimiter);
|
||||
const sectionName = 'section';
|
||||
const totalHyphens = sectionName.length + 3 * 2;
|
||||
const expected = `${commentDelimiter} ---section---`;
|
||||
// act
|
||||
const result = sut
|
||||
.appendCommentLineWithHyphensAround(sectionName, totalHyphens)
|
||||
.toString();
|
||||
// assert
|
||||
const lines = getLines(result);
|
||||
expect(lines[1]).to.equal(expected);
|
||||
});
|
||||
describe('currentLine', () => {
|
||||
it('no lines returns zero', () => {
|
||||
// arrange & act
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(0);
|
||||
});
|
||||
it('appendCommentLine', () => {
|
||||
// arrange
|
||||
const commentDelimiter = '//';
|
||||
const sut = new CodeBuilderConcrete()
|
||||
.withCommentDelimiter(commentDelimiter);
|
||||
const comment = 'comment';
|
||||
const expected = `${commentDelimiter} comment`;
|
||||
// act
|
||||
const result = sut
|
||||
.appendCommentLine(comment)
|
||||
.toString();
|
||||
// assert
|
||||
const lines = getLines(result);
|
||||
expect(lines[0]).to.equal(expected);
|
||||
it('single line returns one', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine();
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(1);
|
||||
});
|
||||
it('appendCommentLineWithHyphensAround', () => {
|
||||
// arrange
|
||||
const commentDelimiter = '//';
|
||||
const sut = new CodeBuilderConcrete()
|
||||
.withCommentDelimiter(commentDelimiter);
|
||||
const sectionName = 'section';
|
||||
const totalHyphens = sectionName.length + 3 * 2;
|
||||
const expected = `${commentDelimiter} ---section---`;
|
||||
// act
|
||||
const result = sut
|
||||
.appendCommentLineWithHyphensAround(sectionName, totalHyphens)
|
||||
.toString();
|
||||
// assert
|
||||
const lines = getLines(result);
|
||||
expect(lines[1]).to.equal(expected);
|
||||
it('multiple lines returns as expected', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine('1')
|
||||
.appendCommentLine('2')
|
||||
.appendLine();
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(3);
|
||||
});
|
||||
describe('currentLine', () => {
|
||||
it('no lines returns zero', () => {
|
||||
// arrange & act
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(0);
|
||||
});
|
||||
it('single line returns one', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine();
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(1);
|
||||
});
|
||||
it('multiple lines returns as expected', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine('1')
|
||||
.appendCommentLine('2')
|
||||
.appendLine();
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(3);
|
||||
});
|
||||
it('multiple lines in code', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine('hello\ncode-here\nwith-3-lines');
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(3);
|
||||
});
|
||||
it('multiple lines in code', () => {
|
||||
// arrange
|
||||
const sut = new CodeBuilderConcrete();
|
||||
// act
|
||||
sut.appendLine('hello\ncode-here\nwith-3-lines');
|
||||
// assert
|
||||
expect(sut.currentLine).to.equal(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getLines(text: string): string[] {
|
||||
return text.split(/\r\n|\r|\n/);
|
||||
return text.split(/\r\n|\r|\n/);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import { CodeBuilderFactory } from '@/application/Context/State/Code/Generation/
|
||||
import { ScriptingLanguageFactoryTestRunner } from '@tests/unit/application/Common/ScriptingLanguage/ScriptingLanguageFactoryTestRunner';
|
||||
|
||||
describe('CodeBuilderFactory', () => {
|
||||
const sut = new CodeBuilderFactory();
|
||||
const runner = new ScriptingLanguageFactoryTestRunner()
|
||||
.expect(ScriptingLanguage.shellscript, ShellBuilder)
|
||||
.expect(ScriptingLanguage.batchfile, BatchBuilder);
|
||||
runner.testCreateMethod(sut);
|
||||
const sut = new CodeBuilderFactory();
|
||||
const runner = new ScriptingLanguageFactoryTestRunner()
|
||||
.expect(ScriptingLanguage.shellscript, ShellBuilder)
|
||||
.expect(ScriptingLanguage.batchfile, BatchBuilder);
|
||||
runner.testCreateMethod(sut);
|
||||
});
|
||||
|
||||
@@ -3,57 +3,58 @@ import { expect } from 'chai';
|
||||
import { BatchBuilder } from '@/application/Context/State/Code/Generation/Languages/BatchBuilder';
|
||||
|
||||
describe('BatchBuilder', () => {
|
||||
class BatchBuilderRevealer extends BatchBuilder {
|
||||
public getCommentDelimiter(): string {
|
||||
return super.getCommentDelimiter();
|
||||
}
|
||||
public writeStandardOut(text: string): string {
|
||||
return super.writeStandardOut(text);
|
||||
}
|
||||
class BatchBuilderRevealer extends BatchBuilder {
|
||||
public getCommentDelimiter(): string {
|
||||
return super.getCommentDelimiter();
|
||||
}
|
||||
describe('getCommentDelimiter', () => {
|
||||
it('returns expected', () => {
|
||||
// arrange
|
||||
const expected = '::';
|
||||
const sut = new BatchBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.getCommentDelimiter();
|
||||
// assert
|
||||
expect(expected).to.equal(actual);
|
||||
});
|
||||
});
|
||||
describe('writeStandardOut', () => {
|
||||
const testData = [
|
||||
{
|
||||
name: 'plain text',
|
||||
text: 'test',
|
||||
expected: 'echo test',
|
||||
},
|
||||
{
|
||||
name: 'text with ampersand',
|
||||
text: 'a & b',
|
||||
expected: 'echo a ^& b',
|
||||
},
|
||||
{
|
||||
name: 'text with percent sign',
|
||||
text: '90%',
|
||||
expected: 'echo 90%%',
|
||||
},
|
||||
{
|
||||
name: 'text with multiple ampersands and percent signs',
|
||||
text: 'Me&you in % ? You & me = 0%',
|
||||
expected: 'echo Me^&you in %% ? You ^& me = 0%%',
|
||||
},
|
||||
];
|
||||
for (const test of testData) {
|
||||
it(test.name, () => {
|
||||
// arrange
|
||||
const sut = new BatchBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.writeStandardOut(test.text);
|
||||
// assert
|
||||
expect(test.expected).to.equal(actual);
|
||||
});
|
||||
}
|
||||
|
||||
public writeStandardOut(text: string): string {
|
||||
return super.writeStandardOut(text);
|
||||
}
|
||||
}
|
||||
describe('getCommentDelimiter', () => {
|
||||
it('returns expected', () => {
|
||||
// arrange
|
||||
const expected = '::';
|
||||
const sut = new BatchBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.getCommentDelimiter();
|
||||
// assert
|
||||
expect(expected).to.equal(actual);
|
||||
});
|
||||
});
|
||||
describe('writeStandardOut', () => {
|
||||
const testData = [
|
||||
{
|
||||
name: 'plain text',
|
||||
text: 'test',
|
||||
expected: 'echo test',
|
||||
},
|
||||
{
|
||||
name: 'text with ampersand',
|
||||
text: 'a & b',
|
||||
expected: 'echo a ^& b',
|
||||
},
|
||||
{
|
||||
name: 'text with percent sign',
|
||||
text: '90%',
|
||||
expected: 'echo 90%%',
|
||||
},
|
||||
{
|
||||
name: 'text with multiple ampersands and percent signs',
|
||||
text: 'Me&you in % ? You & me = 0%',
|
||||
expected: 'echo Me^&you in %% ? You ^& me = 0%%',
|
||||
},
|
||||
];
|
||||
for (const test of testData) {
|
||||
it(test.name, () => {
|
||||
// arrange
|
||||
const sut = new BatchBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.writeStandardOut(test.text);
|
||||
// assert
|
||||
expect(test.expected).to.equal(actual);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,52 +3,53 @@ import { expect } from 'chai';
|
||||
import { ShellBuilder } from '@/application/Context/State/Code/Generation/Languages/ShellBuilder';
|
||||
|
||||
describe('ShellBuilder', () => {
|
||||
class ShellBuilderRevealer extends ShellBuilder {
|
||||
public getCommentDelimiter(): string {
|
||||
return super.getCommentDelimiter();
|
||||
}
|
||||
public writeStandardOut(text: string): string {
|
||||
return super.writeStandardOut(text);
|
||||
}
|
||||
class ShellBuilderRevealer extends ShellBuilder {
|
||||
public getCommentDelimiter(): string {
|
||||
return super.getCommentDelimiter();
|
||||
}
|
||||
describe('getCommentDelimiter', () => {
|
||||
it('returns expected', () => {
|
||||
// arrange
|
||||
const expected = '#';
|
||||
const sut = new ShellBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.getCommentDelimiter();
|
||||
// assert
|
||||
expect(expected).to.equal(actual);
|
||||
});
|
||||
});
|
||||
describe('writeStandardOut', () => {
|
||||
const testData = [
|
||||
{
|
||||
name: 'plain text',
|
||||
text: 'test',
|
||||
expected: 'echo \'test\'',
|
||||
},
|
||||
{
|
||||
name: 'text with single quote',
|
||||
text: 'I\'m not who you think I am',
|
||||
expected: 'echo \'I\'\\\'\'m not who you think I am\'',
|
||||
},
|
||||
{
|
||||
name: 'text with multiple single quotes',
|
||||
text: 'I\'m what you\'re',
|
||||
expected: 'echo \'I\'\\\'\'m what you\'\\\'\'re\'',
|
||||
},
|
||||
];
|
||||
for (const test of testData) {
|
||||
it(test.name, () => {
|
||||
// arrange
|
||||
const sut = new ShellBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.writeStandardOut(test.text);
|
||||
// assert
|
||||
expect(test.expected).to.equal(actual);
|
||||
});
|
||||
}
|
||||
|
||||
public writeStandardOut(text: string): string {
|
||||
return super.writeStandardOut(text);
|
||||
}
|
||||
}
|
||||
describe('getCommentDelimiter', () => {
|
||||
it('returns expected', () => {
|
||||
// arrange
|
||||
const expected = '#';
|
||||
const sut = new ShellBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.getCommentDelimiter();
|
||||
// assert
|
||||
expect(expected).to.equal(actual);
|
||||
});
|
||||
});
|
||||
describe('writeStandardOut', () => {
|
||||
const testData = [
|
||||
{
|
||||
name: 'plain text',
|
||||
text: 'test',
|
||||
expected: 'echo \'test\'',
|
||||
},
|
||||
{
|
||||
name: 'text with single quote',
|
||||
text: 'I\'m not who you think I am',
|
||||
expected: 'echo \'I\'\\\'\'m not who you think I am\'',
|
||||
},
|
||||
{
|
||||
name: 'text with multiple single quotes',
|
||||
text: 'I\'m what you\'re',
|
||||
expected: 'echo \'I\'\\\'\'m what you\'\\\'\'re\'',
|
||||
},
|
||||
];
|
||||
for (const test of testData) {
|
||||
it(test.name, () => {
|
||||
// arrange
|
||||
const sut = new ShellBuilderRevealer();
|
||||
// act
|
||||
const actual = sut.writeStandardOut(test.text);
|
||||
// assert
|
||||
expect(test.expected).to.equal(actual);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,230 +8,239 @@ import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { ScriptingDefinitionStub } from '@tests/unit/stubs/ScriptingDefinitionStub';
|
||||
|
||||
describe('UserScriptGenerator', () => {
|
||||
describe('scriptingDefinition', () => {
|
||||
describe('startCode', () => {
|
||||
it('is prepended if not empty', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const startCode = 'Start\nCode';
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(startCode)
|
||||
.withEndCode(undefined);
|
||||
const expectedStart = `${startCode}\n`;
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
});
|
||||
it('is not prepended if empty', () => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(undefined)
|
||||
.withEndCode(undefined);
|
||||
const expectedStart = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
});
|
||||
});
|
||||
describe('endCode', () => {
|
||||
it('is appended if not empty', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const endCode = 'End\nCode';
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withEndCode(endCode);
|
||||
const expectedEnd = `${endCode}\n`;
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
});
|
||||
it('is not appended if empty', () => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const expectedEnd = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withEndCode(undefined);
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
});
|
||||
});
|
||||
});
|
||||
it('appends revert script', () => {
|
||||
describe('scriptingDefinition', () => {
|
||||
describe('startCode', () => {
|
||||
it('is prepended if not empty', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const scriptName = 'test non-revert script';
|
||||
const scriptCode = 'REM nop';
|
||||
const startCode = 'Start\nCode';
|
||||
const script = new ScriptStub('id')
|
||||
.withName(scriptName)
|
||||
.withRevertCode(scriptCode)
|
||||
.toSelectedScript(true);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(startCode)
|
||||
.withEndCode(undefined);
|
||||
const expectedStart = `${startCode}\n`;
|
||||
// act
|
||||
const actual = sut.buildCode([ script ], definition);
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
expect(actual.code).to.include(`${scriptName} (revert)`);
|
||||
expect(actual.code).to.include(scriptCode);
|
||||
});
|
||||
it('appends non-revert script', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
});
|
||||
it('is not prepended if empty', () => {
|
||||
// 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)];
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(undefined)
|
||||
.withEndCode(undefined);
|
||||
const expectedStart = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
});
|
||||
});
|
||||
describe('endCode', () => {
|
||||
it('is appended if not empty', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const endCode = 'End\nCode';
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withEndCode(endCode);
|
||||
const expectedEnd = `${endCode}\n`;
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
});
|
||||
it('is not appended if empty', () => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const expectedEnd = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withEndCode(undefined);
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
});
|
||||
});
|
||||
});
|
||||
it('appends revert script', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const scriptName = 'test non-revert script';
|
||||
const scriptCode = 'REM nop';
|
||||
const script = new ScriptStub('id')
|
||||
.withName(scriptName)
|
||||
.withRevertCode(scriptCode)
|
||||
.toSelectedScript(true);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
// act
|
||||
const actual = sut.buildCode([script], definition);
|
||||
// assert
|
||||
expect(actual.code).to.include(`${scriptName} (revert)`);
|
||||
expect(actual.code).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)];
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, definition);
|
||||
// assert
|
||||
expect(actual.code).to.include(scriptName);
|
||||
expect(actual.code).to.not.include(`${scriptName} (revert)`);
|
||||
expect(actual.code).to.include(scriptCode);
|
||||
});
|
||||
describe('scriptPositions', () => {
|
||||
it('without script; returns empty', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const selectedScripts = [];
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, definition);
|
||||
// assert
|
||||
expect(actual.scriptPositions.size).to.equal(0);
|
||||
});
|
||||
describe('with scripts', () => {
|
||||
// arrange
|
||||
const totalStartCodeLines = 2;
|
||||
const totalFunctionNameLines = 4;
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode('First line\nSecond line');
|
||||
describe('single script', () => {
|
||||
const testCases = [
|
||||
{
|
||||
name: 'single-lined',
|
||||
scriptCode: 'only line',
|
||||
codeLines: 1,
|
||||
},
|
||||
{
|
||||
name: 'multi-lined',
|
||||
scriptCode: 'first line\nsecond line',
|
||||
codeLines: 2,
|
||||
},
|
||||
];
|
||||
const sut = new UserScriptGenerator();
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const expectedStartLine = totalStartCodeLines
|
||||
+ 1 // empty line code begin
|
||||
+ 1; // code begin
|
||||
const expectedEndLine = expectedStartLine
|
||||
+ totalFunctionNameLines
|
||||
+ testCase.codeLines;
|
||||
const selectedScript = new ScriptStub('script-id')
|
||||
.withName('script')
|
||||
.withCode(testCase.scriptCode)
|
||||
.toSelectedScript(false);
|
||||
// act
|
||||
const actual = sut.buildCode([selectedScript], definition);
|
||||
// expect
|
||||
expect(1).to.equal(actual.scriptPositions.size);
|
||||
const position = actual.scriptPositions.get(selectedScript);
|
||||
expect(expectedStartLine).to.equal(position.startLine, 'Unexpected start line position');
|
||||
expect(expectedEndLine).to.equal(position.endLine, 'Unexpected end line position');
|
||||
});
|
||||
}
|
||||
});
|
||||
it('multiple scripts', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
const selectedScripts = [
|
||||
new ScriptStub('1').withCode('only line'),
|
||||
new ScriptStub('2').withCode('first line\nsecond line'),
|
||||
].map((s) => s.toSelectedScript());
|
||||
const expectedFirstScriptStart = totalStartCodeLines
|
||||
+ 1 // empty line code begin
|
||||
+ 1; // code begin
|
||||
const expectedFirstScriptEnd = expectedFirstScriptStart
|
||||
+ totalFunctionNameLines
|
||||
+ 1; // total code lines
|
||||
const expectedSecondScriptStart = expectedFirstScriptEnd
|
||||
+ 1 // code end hyphens
|
||||
+ 1 // new line
|
||||
+ 1; // code begin
|
||||
const expectedSecondScriptEnd = expectedSecondScriptStart
|
||||
+ totalFunctionNameLines
|
||||
+ 2; // total lines of second script
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, definition);
|
||||
// assert
|
||||
expect(actual.code).to.include(scriptName);
|
||||
expect(actual.code).to.not.include(`${scriptName} (revert)`);
|
||||
expect(actual.code).to.include(scriptCode);
|
||||
});
|
||||
describe('scriptPositions', () => {
|
||||
it('without script; returns empty', () => {
|
||||
// arrange
|
||||
const sut = new UserScriptGenerator();
|
||||
const selectedScripts = [ ];
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, definition);
|
||||
// assert
|
||||
expect(actual.scriptPositions.size).to.equal(0);
|
||||
});
|
||||
describe('with scripts', () => {
|
||||
// arrange
|
||||
const totalStartCodeLines = 2;
|
||||
const totalFunctionNameLines = 4;
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode('First line\nSecond line');
|
||||
describe('single script', () => {
|
||||
const testCases = [
|
||||
{
|
||||
name: 'single-lined',
|
||||
scriptCode: 'only line',
|
||||
codeLines: 1,
|
||||
},
|
||||
{
|
||||
name: 'multi-lined',
|
||||
scriptCode: 'first line\nsecond line',
|
||||
codeLines: 2,
|
||||
},
|
||||
];
|
||||
const sut = new UserScriptGenerator();
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const expectedStartLine = totalStartCodeLines
|
||||
+ 1 // empty line code begin
|
||||
+ 1; // code begin
|
||||
const expectedEndLine = expectedStartLine
|
||||
+ totalFunctionNameLines
|
||||
+ testCase.codeLines;
|
||||
const selectedScript = new ScriptStub(`script-id`)
|
||||
.withName(`script`)
|
||||
.withCode(testCase.scriptCode)
|
||||
.toSelectedScript(false);
|
||||
// act
|
||||
const actual = sut.buildCode([ selectedScript ], definition);
|
||||
// expect
|
||||
expect(1).to.equal(actual.scriptPositions.size);
|
||||
const position = actual.scriptPositions.get(selectedScript);
|
||||
expect(expectedStartLine).to.equal(position.startLine, 'Unexpected start line position');
|
||||
expect(expectedEndLine).to.equal(position.endLine, 'Unexpected end line position');
|
||||
});
|
||||
}
|
||||
});
|
||||
it('multiple scripts', () => {
|
||||
const sut = new UserScriptGenerator();
|
||||
const selectedScripts = [
|
||||
new ScriptStub('1').withCode('only line'),
|
||||
new ScriptStub('2').withCode('first line\nsecond line'),
|
||||
].map((s) => s.toSelectedScript());
|
||||
const expectedFirstScriptStart = totalStartCodeLines
|
||||
+ 1 // empty line code begin
|
||||
+ 1; // code begin
|
||||
const expectedFirstScriptEnd = expectedFirstScriptStart
|
||||
+ totalFunctionNameLines
|
||||
+ 1; // total code lines
|
||||
const expectedSecondScriptStart = expectedFirstScriptEnd
|
||||
+ 1 // code end hyphens
|
||||
+ 1 // new line
|
||||
+ 1; // code begin
|
||||
const expectedSecondScriptEnd =
|
||||
expectedSecondScriptStart
|
||||
+ totalFunctionNameLines
|
||||
+ 2; // total lines of second script
|
||||
// act
|
||||
const actual = sut.buildCode(selectedScripts, definition);
|
||||
// assert
|
||||
const firstPosition = actual.scriptPositions.get(selectedScripts[0]);
|
||||
const secondPosition = actual.scriptPositions.get(selectedScripts[1]);
|
||||
expect(actual.scriptPositions.size).to.equal(2);
|
||||
expect(expectedFirstScriptStart).to.equal(firstPosition.startLine, 'Unexpected start line position (first script)');
|
||||
expect(expectedFirstScriptEnd).to.equal(firstPosition.endLine, 'Unexpected end line position (first script)');
|
||||
expect(expectedSecondScriptStart).to.equal(secondPosition.startLine, 'Unexpected start line position (second script)');
|
||||
expect(expectedSecondScriptEnd).to.equal(secondPosition.endLine, 'Unexpected end line position (second script)');
|
||||
});
|
||||
});
|
||||
const firstPosition = actual.scriptPositions.get(selectedScripts[0]);
|
||||
const secondPosition = actual.scriptPositions.get(selectedScripts[1]);
|
||||
expect(actual.scriptPositions.size).to.equal(2);
|
||||
expect(expectedFirstScriptStart).to.equal(firstPosition.startLine, 'Unexpected start line position (first script)');
|
||||
expect(expectedFirstScriptEnd).to.equal(firstPosition.endLine, 'Unexpected end line position (first script)');
|
||||
expect(expectedSecondScriptStart).to.equal(secondPosition.startLine, 'Unexpected start line position (second script)');
|
||||
expect(expectedSecondScriptEnd).to.equal(secondPosition.endLine, 'Unexpected end line position (second script)');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function mockCodeBuilderFactory(mock: ICodeBuilder): ICodeBuilderFactory {
|
||||
return {
|
||||
create: () => mock,
|
||||
};
|
||||
return {
|
||||
create: () => mock,
|
||||
};
|
||||
}
|
||||
|
||||
class CodeBuilderStub implements ICodeBuilder {
|
||||
public currentLine = 0;
|
||||
private text = '';
|
||||
public appendLine(code?: string): ICodeBuilder {
|
||||
this.text += this.text ? `${code}\n` : code;
|
||||
this.currentLine++;
|
||||
return this;
|
||||
}
|
||||
public appendTrailingHyphensCommentLine(totalRepeatHyphens: number): ICodeBuilder {
|
||||
return this.appendLine(`trailing-hyphens-${totalRepeatHyphens}`);
|
||||
}
|
||||
public appendCommentLine(commentLine?: string): ICodeBuilder {
|
||||
return this.appendLine(`Comment | ${commentLine}`);
|
||||
}
|
||||
public appendCommentLineWithHyphensAround(sectionName: string, totalRepeatHyphens: number): ICodeBuilder {
|
||||
return this.appendLine(`hyphens-around-${totalRepeatHyphens} | Section name: ${sectionName} | hyphens-around-${totalRepeatHyphens}`);
|
||||
}
|
||||
public appendFunction(name: string, code: string): ICodeBuilder {
|
||||
return this
|
||||
.appendLine(`Function | Name: ${name}`)
|
||||
.appendLine(`Function | Code: ${code}`);
|
||||
}
|
||||
public toString(): string {
|
||||
return this.text;
|
||||
}
|
||||
public currentLine = 0;
|
||||
|
||||
private text = '';
|
||||
|
||||
public appendLine(code?: string): ICodeBuilder {
|
||||
this.text += this.text ? `${code}\n` : code;
|
||||
this.currentLine++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public appendTrailingHyphensCommentLine(totalRepeatHyphens: number): ICodeBuilder {
|
||||
return this.appendLine(`trailing-hyphens-${totalRepeatHyphens}`);
|
||||
}
|
||||
|
||||
public appendCommentLine(commentLine?: string): ICodeBuilder {
|
||||
return this.appendLine(`Comment | ${commentLine}`);
|
||||
}
|
||||
|
||||
public appendCommentLineWithHyphensAround(
|
||||
sectionName: string,
|
||||
totalRepeatHyphens: number,
|
||||
): ICodeBuilder {
|
||||
return this.appendLine(`hyphens-around-${totalRepeatHyphens} | Section name: ${sectionName} | hyphens-around-${totalRepeatHyphens}`);
|
||||
}
|
||||
|
||||
public appendFunction(name: string, code: string): ICodeBuilder {
|
||||
return this
|
||||
.appendLine(`Function | Name: ${name}`)
|
||||
.appendLine(`Function | Code: ${code}`);
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
return this.text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,52 +3,52 @@ import { expect } from 'chai';
|
||||
import { CodePosition } from '@/application/Context/State/Code/Position/CodePosition';
|
||||
|
||||
describe('CodePosition', () => {
|
||||
describe('ctor', () => {
|
||||
it('creates with valid parameters', () => {
|
||||
// arrange
|
||||
const startPosition = 0;
|
||||
const endPosition = 5;
|
||||
// act
|
||||
const sut = new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(sut.startLine).to.equal(startPosition);
|
||||
expect(sut.endLine).to.equal(endPosition);
|
||||
});
|
||||
it('throws with negative start position', () => {
|
||||
// arrange
|
||||
const startPosition = -1;
|
||||
const endPosition = 5;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('Code cannot start in a negative line');
|
||||
});
|
||||
it('throws with negative end position', () => {
|
||||
// arrange
|
||||
const startPosition = 1;
|
||||
const endPosition = -5;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('Code cannot end in a negative line');
|
||||
});
|
||||
it('throws when start and end position is same', () => {
|
||||
// arrange
|
||||
const startPosition = 0;
|
||||
const endPosition = 0;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('Empty code');
|
||||
});
|
||||
it('throws when ends before start', () => {
|
||||
// arrange
|
||||
const startPosition = 3;
|
||||
const endPosition = 2;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('End line cannot be less than start line');
|
||||
});
|
||||
describe('ctor', () => {
|
||||
it('creates with valid parameters', () => {
|
||||
// arrange
|
||||
const startPosition = 0;
|
||||
const endPosition = 5;
|
||||
// act
|
||||
const sut = new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(sut.startLine).to.equal(startPosition);
|
||||
expect(sut.endLine).to.equal(endPosition);
|
||||
});
|
||||
it('throws with negative start position', () => {
|
||||
// arrange
|
||||
const startPosition = -1;
|
||||
const endPosition = 5;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('Code cannot start in a negative line');
|
||||
});
|
||||
it('throws with negative end position', () => {
|
||||
// arrange
|
||||
const startPosition = 1;
|
||||
const endPosition = -5;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('Code cannot end in a negative line');
|
||||
});
|
||||
it('throws when start and end position is same', () => {
|
||||
// arrange
|
||||
const startPosition = 0;
|
||||
const endPosition = 0;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('Empty code');
|
||||
});
|
||||
it('throws when ends before start', () => {
|
||||
// arrange
|
||||
const startPosition = 3;
|
||||
const endPosition = 2;
|
||||
// act
|
||||
const getSut = () => new CodePosition(startPosition, endPosition);
|
||||
// assert
|
||||
expect(getSut).to.throw('End line cannot be less than start line');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,42 +5,42 @@ import { CategoryStub } from '@tests/unit/stubs/CategoryStub';
|
||||
import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
|
||||
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);
|
||||
});
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,158 +7,172 @@ import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
|
||||
describe('UserFilter', () => {
|
||||
describe('removeFilter', () => {
|
||||
it('signals when removing filter', () => {
|
||||
// arrange
|
||||
let isCalled = false;
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
sut.filterRemoved.on(() => isCalled = true);
|
||||
// act
|
||||
sut.removeFilter();
|
||||
// assert
|
||||
expect(isCalled).to.be.equal(true);
|
||||
});
|
||||
it('sets currentFilter to undefined', () => {
|
||||
// arrange
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
// act
|
||||
sut.setFilter('non-important');
|
||||
sut.removeFilter();
|
||||
// assert
|
||||
expect(sut.currentFilter).to.be.equal(undefined);
|
||||
});
|
||||
describe('removeFilter', () => {
|
||||
it('signals when removing filter', () => {
|
||||
// arrange
|
||||
let isCalled = false;
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
sut.filterRemoved.on(() => {
|
||||
isCalled = true;
|
||||
});
|
||||
// act
|
||||
sut.removeFilter();
|
||||
// assert
|
||||
expect(isCalled).to.be.equal(true);
|
||||
});
|
||||
describe('setFilter', () => {
|
||||
it('signals when no matches', () => {
|
||||
// arrange
|
||||
let actual: IFilterResult;
|
||||
const nonMatchingFilter = 'non matching filter';
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
sut.filtered.on((filterResult) => actual = filterResult);
|
||||
// act
|
||||
sut.setFilter(nonMatchingFilter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(false);
|
||||
expect(actual.query).to.equal(nonMatchingFilter);
|
||||
});
|
||||
it('sets currentFilter as expected when no matches', () => {
|
||||
// arrange
|
||||
const nonMatchingFilter = 'non matching filter';
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
// act
|
||||
sut.setFilter(nonMatchingFilter);
|
||||
// assert
|
||||
const actual = sut.currentFilter;
|
||||
expect(actual.hasAnyMatches()).be.equal(false);
|
||||
expect(actual.query).to.equal(nonMatchingFilter);
|
||||
});
|
||||
describe('signals when matches', () => {
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
});
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
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 collection = new CategoryCollectionStub()
|
||||
.withAction(category);
|
||||
const sut = new UserFilter(collection);
|
||||
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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
});
|
||||
it('sets currentFilter to undefined', () => {
|
||||
// arrange
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
// act
|
||||
sut.setFilter('non-important');
|
||||
sut.removeFilter();
|
||||
// assert
|
||||
expect(sut.currentFilter).to.be.equal(undefined);
|
||||
});
|
||||
});
|
||||
describe('setFilter', () => {
|
||||
it('signals when no matches', () => {
|
||||
// arrange
|
||||
let actual: IFilterResult;
|
||||
const nonMatchingFilter = 'non matching filter';
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
sut.filtered.on((filterResult) => {
|
||||
actual = filterResult;
|
||||
});
|
||||
// act
|
||||
sut.setFilter(nonMatchingFilter);
|
||||
// assert
|
||||
expect(actual.hasAnyMatches()).be.equal(false);
|
||||
expect(actual.query).to.equal(nonMatchingFilter);
|
||||
});
|
||||
it('sets currentFilter as expected when no matches', () => {
|
||||
// arrange
|
||||
const nonMatchingFilter = 'non matching filter';
|
||||
const sut = new UserFilter(new CategoryCollectionStub());
|
||||
// act
|
||||
sut.setFilter(nonMatchingFilter);
|
||||
// assert
|
||||
const actual = sut.currentFilter;
|
||||
expect(actual.hasAnyMatches()).be.equal(false);
|
||||
expect(actual.query).to.equal(nonMatchingFilter);
|
||||
});
|
||||
describe('signals when matches', () => {
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
});
|
||||
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 CategoryCollectionStub()
|
||||
.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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
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 collection = new CategoryCollectionStub()
|
||||
.withAction(category);
|
||||
const sut = new UserFilter(collection);
|
||||
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);
|
||||
expect(sut.currentFilter).to.deep.equal(actual);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,25 +4,25 @@ import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
|
||||
|
||||
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); }
|
||||
// assert
|
||||
expect(construct).to.throw('cannot revert an irreversible script');
|
||||
});
|
||||
|
||||
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
|
||||
// eslint-disable-next-line no-new
|
||||
function construct() { new SelectedScript(script, true); }
|
||||
// assert
|
||||
expect(construct).to.throw('cannot revert an irreversible script');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,390 +9,394 @@ import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { UserSelectionTestRunner } from './UserSelectionTestRunner';
|
||||
|
||||
describe('UserSelection', () => {
|
||||
describe('ctor', () => {
|
||||
describe('has nothing with no initial selection', () => {
|
||||
// arrange
|
||||
const allScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(1, allScripts.map((s) => s.script))
|
||||
// act
|
||||
.run()
|
||||
// assert
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
describe('has initial selection', () => {
|
||||
// arrange
|
||||
const scripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(scripts)
|
||||
.withCategory(1, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run()
|
||||
// assert
|
||||
.expectFinalScripts(scripts);
|
||||
});
|
||||
describe('ctor', () => {
|
||||
describe('has nothing with no initial selection', () => {
|
||||
// arrange
|
||||
const allScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(1, allScripts.map((s) => s.script))
|
||||
// act
|
||||
.run()
|
||||
// assert
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
describe('deselectAll removes all items', () => {
|
||||
describe('has initial selection', () => {
|
||||
// arrange
|
||||
const scripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(scripts)
|
||||
.withCategory(1, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run()
|
||||
// assert
|
||||
.expectFinalScripts(scripts);
|
||||
});
|
||||
});
|
||||
describe('deselectAll removes all items', () => {
|
||||
// arrange
|
||||
const allScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
new SelectedScriptStub('s3', false),
|
||||
new SelectedScriptStub('s4', false),
|
||||
];
|
||||
const selectedScripts = allScripts.filter(
|
||||
(s) => ['s1', 's2', 's3'].includes(s.id),
|
||||
);
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(selectedScripts)
|
||||
.withCategory(1, allScripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.deselectAll();
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([])
|
||||
.expectFinalScriptsInEvent(0, []);
|
||||
});
|
||||
describe('selectOnly selects expected', () => {
|
||||
// arrange
|
||||
const allScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
new SelectedScriptStub('s3', false),
|
||||
new SelectedScriptStub('s4', false),
|
||||
];
|
||||
const selectedScripts = allScripts.filter(
|
||||
(s) => ['s1', 's2', 's3'].includes(s.id),
|
||||
);
|
||||
const scriptsToSelect = allScripts.filter(
|
||||
(s) => ['s2', 's3', 's4'].includes(s.id),
|
||||
);
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(selectedScripts)
|
||||
.withCategory(1, allScripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.selectOnly(scriptsToSelect.map((s) => s.script));
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(scriptsToSelect)
|
||||
.expectFinalScriptsInEvent(0, scriptsToSelect);
|
||||
});
|
||||
describe('selectAll selects as expected', () => {
|
||||
// arrange
|
||||
const expected = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(1, expected.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.selectAll();
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expected)
|
||||
.expectFinalScriptsInEvent(0, expected);
|
||||
});
|
||||
describe('addOrUpdateSelectedScript', () => {
|
||||
describe('adds when item does not exist', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
const expected = [new SelectedScript(scripts[0], false)];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(1, scripts)
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateSelectedScript(scripts[0].id, false);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expected)
|
||||
.expectFinalScriptsInEvent(0, expected);
|
||||
});
|
||||
describe('updates when item exists', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
const existing = new SelectedScript(scripts[0], false);
|
||||
const expected = new SelectedScript(scripts[0], true);
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([existing])
|
||||
.withCategory(1, scripts)
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateSelectedScript(expected.id, expected.revert);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([expected])
|
||||
.expectFinalScriptsInEvent(0, [expected]);
|
||||
});
|
||||
});
|
||||
describe('removeAllInCategory', () => {
|
||||
describe('does nothing when nothing exists', () => {
|
||||
// arrange
|
||||
const categoryId = 99;
|
||||
const scripts = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(categoryId, scripts)
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.removeAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(0)
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
describe('removes all when all exists', () => {
|
||||
// arrange
|
||||
const categoryId = 34;
|
||||
const scripts = [new SelectedScriptStub('s1'), new SelectedScriptStub('s2')];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(scripts)
|
||||
.withCategory(categoryId, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.removeAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
describe('removes existing when some exists', () => {
|
||||
// arrange
|
||||
const categoryId = 55;
|
||||
const existing = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
const notExisting = [new ScriptStub('s3'), new ScriptStub('s4')];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(existing.map((script) => new SelectedScript(script, false)))
|
||||
.withCategory(categoryId, [...existing, ...notExisting])
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.removeAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
});
|
||||
describe('addOrUpdateAllInCategory', () => {
|
||||
describe('when all already exists', () => {
|
||||
describe('does nothing if nothing is changed', () => {
|
||||
// arrange
|
||||
const allScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
new SelectedScriptStub('s3', false),
|
||||
new SelectedScriptStub('s4', false),
|
||||
const categoryId = 55;
|
||||
const existingScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
];
|
||||
const selectedScripts = allScripts.filter(
|
||||
(s) => ['s1', 's2', 's3'].includes(s.id));
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(selectedScripts)
|
||||
.withCategory(1, allScripts.map((s) => s.script))
|
||||
.withSelectedScripts(existingScripts)
|
||||
.withCategory(categoryId, existingScripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.deselectAll();
|
||||
})
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([])
|
||||
.expectFinalScriptsInEvent(0, []);
|
||||
});
|
||||
describe('selectOnly selects expected', () => {
|
||||
.expectTotalFiredEvents(0)
|
||||
.expectFinalScripts(existingScripts);
|
||||
});
|
||||
describe('changes revert status of all', () => {
|
||||
// arrange
|
||||
const allScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
new SelectedScriptStub('s3', false),
|
||||
new SelectedScriptStub('s4', false),
|
||||
const newStatus = false;
|
||||
const scripts = [
|
||||
new SelectedScriptStub('e1', !newStatus),
|
||||
new SelectedScriptStub('e2', !newStatus),
|
||||
new SelectedScriptStub('e3', newStatus),
|
||||
];
|
||||
const selectedScripts = allScripts.filter(
|
||||
(s) => ['s1', 's2', 's3'].includes(s.id));
|
||||
const scriptsToSelect = allScripts.filter(
|
||||
(s) => ['s2', 's3', 's4'].includes(s.id));
|
||||
const expectedScripts = scripts.map((s) => new SelectedScript(s.script, newStatus));
|
||||
const categoryId = 31;
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(selectedScripts)
|
||||
.withCategory(1, allScripts.map((s) => s.script))
|
||||
.withSelectedScripts(scripts)
|
||||
.withCategory(categoryId, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.selectOnly(scriptsToSelect.map((s) => s.script));
|
||||
})
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId, newStatus);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(scriptsToSelect)
|
||||
.expectFinalScriptsInEvent(0, scriptsToSelect);
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expectedScripts)
|
||||
.expectFinalScriptsInEvent(0, expectedScripts);
|
||||
});
|
||||
});
|
||||
describe('selectAll selects as expected', () => {
|
||||
// arrange
|
||||
const expected = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
describe('when nothing exists; adds all with given revert status', () => {
|
||||
const revertStatuses = [true, false];
|
||||
for (const revertStatus of revertStatuses) {
|
||||
describe(`when revert status is ${revertStatus}`, () => {
|
||||
// arrange
|
||||
const categoryId = 1;
|
||||
const scripts = [
|
||||
new SelectedScriptStub('s1', !revertStatus),
|
||||
new SelectedScriptStub('s2', !revertStatus),
|
||||
];
|
||||
const expected = scripts.map((s) => new SelectedScript(s.script, revertStatus));
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(1, expected.map((s) => s.script))
|
||||
// act
|
||||
.withCategory(categoryId, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.selectAll();
|
||||
sut.addOrUpdateAllInCategory(categoryId, revertStatus);
|
||||
})
|
||||
// assert
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expected)
|
||||
.expectFinalScriptsInEvent(0, expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
describe('addOrUpdateSelectedScript', () => {
|
||||
describe('adds when item does not exist', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
const expected = [ new SelectedScript(scripts[0], false) ];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(1, scripts)
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateSelectedScript(scripts[0].id, false);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expected)
|
||||
.expectFinalScriptsInEvent(0, expected);
|
||||
});
|
||||
describe('updates when item exists', () => {
|
||||
// arrange
|
||||
const scripts = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
const existing = new SelectedScript(scripts[0], false);
|
||||
const expected = new SelectedScript(scripts[0], true);
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([existing])
|
||||
.withCategory(1, scripts)
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateSelectedScript(expected.id, expected.revert);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([ expected ])
|
||||
.expectFinalScriptsInEvent(0, [ expected ]);
|
||||
});
|
||||
describe('when some exists; changes revert status of all', () => {
|
||||
// arrange
|
||||
const newStatus = true;
|
||||
const existing = [
|
||||
new SelectedScriptStub('e1', true),
|
||||
new SelectedScriptStub('e2', false),
|
||||
];
|
||||
const notExisting = [
|
||||
new SelectedScriptStub('n3', true),
|
||||
new SelectedScriptStub('n4', false),
|
||||
];
|
||||
const allScripts = [...existing, ...notExisting];
|
||||
const expectedScripts = allScripts.map((s) => new SelectedScript(s.script, newStatus));
|
||||
const categoryId = 77;
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(existing)
|
||||
.withCategory(categoryId, allScripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId, newStatus);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expectedScripts)
|
||||
.expectFinalScriptsInEvent(0, expectedScripts);
|
||||
});
|
||||
describe('removeAllInCategory', () => {
|
||||
describe('does nothing when nothing exists', () => {
|
||||
// arrange
|
||||
const categoryId = 99;
|
||||
const scripts = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(categoryId, scripts)
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.removeAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(0)
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
describe('removes all when all exists', () => {
|
||||
// arrange
|
||||
const categoryId = 34;
|
||||
const scripts = [new SelectedScriptStub('s1'), new SelectedScriptStub('s2')];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(scripts)
|
||||
.withCategory(categoryId, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.removeAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
describe('removes existing when some exists', () => {
|
||||
// arrange
|
||||
const categoryId = 55;
|
||||
const existing = [new ScriptStub('s1'), new ScriptStub('s2')];
|
||||
const notExisting = [new ScriptStub('s3'), new ScriptStub('s4')];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(existing.map((script) => new SelectedScript(script, false)))
|
||||
.withCategory(categoryId, [ ...existing, ...notExisting ])
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.removeAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts([]);
|
||||
});
|
||||
});
|
||||
describe('isSelected', () => {
|
||||
it('returns false when not selected', () => {
|
||||
// arrange
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const notSelectedScript = new ScriptStub('not selected');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(selectedScript, notSelectedScript));
|
||||
const sut = new UserSelection(collection, [new SelectedScript(selectedScript, false)]);
|
||||
// act
|
||||
const actual = sut.isSelected(notSelectedScript.id);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
describe('addOrUpdateAllInCategory', () => {
|
||||
describe('when all already exists', () => {
|
||||
describe('does nothing if nothing is changed', () => {
|
||||
// arrange
|
||||
const categoryId = 55;
|
||||
const existingScripts = [
|
||||
new SelectedScriptStub('s1', false),
|
||||
new SelectedScriptStub('s2', false),
|
||||
];
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(existingScripts)
|
||||
.withCategory(categoryId, existingScripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(0)
|
||||
.expectFinalScripts(existingScripts);
|
||||
});
|
||||
describe('changes revert status of all', () => {
|
||||
// arrange
|
||||
const newStatus = false;
|
||||
const scripts = [
|
||||
new SelectedScriptStub('e1', !newStatus),
|
||||
new SelectedScriptStub('e2', !newStatus),
|
||||
new SelectedScriptStub('e3', newStatus),
|
||||
];
|
||||
const expectedScripts = scripts.map((s) => new SelectedScript(s.script, newStatus));
|
||||
const categoryId = 31;
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(scripts)
|
||||
.withCategory(categoryId, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId, newStatus);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expectedScripts)
|
||||
.expectFinalScriptsInEvent(0, expectedScripts);
|
||||
});
|
||||
});
|
||||
describe('when nothing exists; adds all with given revert status', () => {
|
||||
const revertStatuses = [ true, false ];
|
||||
for (const revertStatus of revertStatuses) {
|
||||
describe(`when revert status is ${revertStatus}`, () => {
|
||||
// arrange
|
||||
const categoryId = 1;
|
||||
const scripts = [
|
||||
new SelectedScriptStub('s1', !revertStatus),
|
||||
new SelectedScriptStub('s2', !revertStatus),
|
||||
];
|
||||
const expected = scripts.map((s) => new SelectedScript(s.script, revertStatus));
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts([])
|
||||
.withCategory(categoryId, scripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId, revertStatus);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expected)
|
||||
.expectFinalScriptsInEvent(0, expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
describe('when some exists; changes revert status of all', () => {
|
||||
// arrange
|
||||
const newStatus = true;
|
||||
const existing = [
|
||||
new SelectedScriptStub('e1', true),
|
||||
new SelectedScriptStub('e2', false),
|
||||
];
|
||||
const notExisting = [
|
||||
new SelectedScriptStub('n3', true),
|
||||
new SelectedScriptStub('n4', false),
|
||||
];
|
||||
const allScripts = [ ...existing, ...notExisting ];
|
||||
const expectedScripts = allScripts.map((s) => new SelectedScript(s.script, newStatus));
|
||||
const categoryId = 77;
|
||||
new UserSelectionTestRunner()
|
||||
.withSelectedScripts(existing)
|
||||
.withCategory(categoryId, allScripts.map((s) => s.script))
|
||||
// act
|
||||
.run((sut) => {
|
||||
sut.addOrUpdateAllInCategory(categoryId, newStatus);
|
||||
})
|
||||
// assert
|
||||
.expectTotalFiredEvents(1)
|
||||
.expectFinalScripts(expectedScripts)
|
||||
.expectFinalScriptsInEvent(0, expectedScripts);
|
||||
});
|
||||
it('returns true when selected', () => {
|
||||
// arrange
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const notSelectedScript = new ScriptStub('not selected');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(selectedScript, notSelectedScript));
|
||||
const sut = new UserSelection(collection, [new SelectedScript(selectedScript, false)]);
|
||||
// act
|
||||
const actual = sut.isSelected(selectedScript.id);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
describe('isSelected', () => {
|
||||
it('returns false when not selected', () => {
|
||||
// arrange
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const notSelectedScript = new ScriptStub('not selected');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(selectedScript, notSelectedScript));
|
||||
const sut = new UserSelection(collection, [ new SelectedScript(selectedScript, false) ]);
|
||||
// act
|
||||
const actual = sut.isSelected(notSelectedScript.id);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('returns true when selected', () => {
|
||||
// arrange
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const notSelectedScript = new ScriptStub('not selected');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(new CategoryStub(1)
|
||||
.withScripts(selectedScript, notSelectedScript));
|
||||
const sut = new UserSelection(collection, [ new SelectedScript(selectedScript, false) ]);
|
||||
// act
|
||||
const actual = sut.isSelected(selectedScript.id);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('category state', () => {
|
||||
describe('when no scripts are selected', () => {
|
||||
// arrange
|
||||
const category = new CategoryStub(1)
|
||||
.withScriptIds('non-selected-script-1', 'non-selected-script-2');
|
||||
const collection = new CategoryCollectionStub().withAction(category);
|
||||
const sut = new UserSelection(collection, []);
|
||||
it('areAllSelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('isAnySelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('category state', () => {
|
||||
describe('when no scripts are selected', () => {
|
||||
// arrange
|
||||
const category = new CategoryStub(1)
|
||||
.withScriptIds('non-selected-script-1', 'non-selected-script-2');
|
||||
const collection = new CategoryCollectionStub().withAction(category);
|
||||
const sut = new UserSelection(collection, [ ]);
|
||||
it('areAllSelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('isAnySelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('when no subscript exists in selected scripts', () => {
|
||||
// arrange
|
||||
const category = new CategoryStub(1)
|
||||
.withScriptIds('non-selected-script-1', 'non-selected-script-2');
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(category)
|
||||
.withAction(new CategoryStub(22).withScript(selectedScript));
|
||||
const sut = new UserSelection(collection, [ new SelectedScript(selectedScript, false) ]);
|
||||
it('areAllSelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('isAnySelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('when one of the scripts are selected', () => {
|
||||
// arrange
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const category = new CategoryStub(1)
|
||||
.withScriptIds('non-selected-script-1', 'non-selected-script-2')
|
||||
.withCategory(new CategoryStub(12).withScript(selectedScript));
|
||||
const collection = new CategoryCollectionStub().withAction(category);
|
||||
const sut = new UserSelection(collection, [ new SelectedScript(selectedScript, false) ]);
|
||||
it('areAllSelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('isAnySelected returns true', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when all scripts are selected', () => {
|
||||
// arrange
|
||||
const firstSelectedScript = new ScriptStub('selected1');
|
||||
const secondSelectedScript = new ScriptStub('selected2');
|
||||
const category = new CategoryStub(1)
|
||||
.withScript(firstSelectedScript)
|
||||
.withCategory(new CategoryStub(12).withScript(secondSelectedScript));
|
||||
const collection = new CategoryCollectionStub().withAction(category);
|
||||
const sut = new UserSelection(collection,
|
||||
[ firstSelectedScript, secondSelectedScript ].map((s) => new SelectedScript(s, false)));
|
||||
it('areAllSelected returns true', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
it('isAnySelected returns true', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when no subscript exists in selected scripts', () => {
|
||||
// arrange
|
||||
const category = new CategoryStub(1)
|
||||
.withScriptIds('non-selected-script-1', 'non-selected-script-2');
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const collection = new CategoryCollectionStub()
|
||||
.withAction(category)
|
||||
.withAction(new CategoryStub(22).withScript(selectedScript));
|
||||
const sut = new UserSelection(collection, [new SelectedScript(selectedScript, false)]);
|
||||
it('areAllSelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('isAnySelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('when one of the scripts are selected', () => {
|
||||
// arrange
|
||||
const selectedScript = new ScriptStub('selected');
|
||||
const category = new CategoryStub(1)
|
||||
.withScriptIds('non-selected-script-1', 'non-selected-script-2')
|
||||
.withCategory(new CategoryStub(12).withScript(selectedScript));
|
||||
const collection = new CategoryCollectionStub().withAction(category);
|
||||
const sut = new UserSelection(collection, [new SelectedScript(selectedScript, false)]);
|
||||
it('areAllSelected returns false', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('isAnySelected returns true', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('when all scripts are selected', () => {
|
||||
// arrange
|
||||
const firstSelectedScript = new ScriptStub('selected1');
|
||||
const secondSelectedScript = new ScriptStub('selected2');
|
||||
const category = new CategoryStub(1)
|
||||
.withScript(firstSelectedScript)
|
||||
.withCategory(new CategoryStub(12).withScript(secondSelectedScript));
|
||||
const collection = new CategoryCollectionStub().withAction(category);
|
||||
const selectedScripts = [firstSelectedScript, secondSelectedScript]
|
||||
.map((s) => new SelectedScript(s, false));
|
||||
const sut = new UserSelection(collection, selectedScripts);
|
||||
it('areAllSelected returns true', () => {
|
||||
// act
|
||||
const actual = sut.areAllSelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
it('isAnySelected returns true', () => {
|
||||
// act
|
||||
const actual = sut.isAnySelected(category);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,72 +7,83 @@ import { UserSelection } from '@/application/Context/State/Selection/UserSelecti
|
||||
import { IScript } from '@/domain/IScript';
|
||||
|
||||
export class UserSelectionTestRunner {
|
||||
private readonly collection = new CategoryCollectionStub();
|
||||
private existingScripts: readonly SelectedScript[] = [];
|
||||
private events: Array<readonly SelectedScript[]> = [];
|
||||
private sut: UserSelection;
|
||||
private readonly collection = new CategoryCollectionStub();
|
||||
|
||||
public withCategory(categoryId: number, scripts: readonly IScript[]) {
|
||||
const category = new CategoryStub(categoryId)
|
||||
.withScripts(...scripts);
|
||||
this.collection
|
||||
.withAction(category);
|
||||
return this;
|
||||
}
|
||||
public withSelectedScripts(existingScripts: readonly SelectedScript[]) {
|
||||
this.existingScripts = existingScripts;
|
||||
return this;
|
||||
}
|
||||
public run(runner?: (sut: UserSelection) => void) {
|
||||
this.sut = this.createSut();
|
||||
if (runner) {
|
||||
runner(this.sut);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public expectTotalFiredEvents(amount: number) {
|
||||
const testName = amount === 0 ? 'does not fire changed event' : `fires changed event ${amount} times`;
|
||||
it(testName, () => {
|
||||
expect(this.events).to.have.lengthOf(amount);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
public expectFinalScripts(finalScripts: readonly SelectedScript[]) {
|
||||
expectSameScripts(finalScripts, this.sut.selectedScripts);
|
||||
return this;
|
||||
}
|
||||
public expectFinalScriptsInEvent(eventIndex: number, finalScripts: readonly SelectedScript[]) {
|
||||
expectSameScripts(this.events[eventIndex], finalScripts);
|
||||
return this;
|
||||
}
|
||||
private createSut(): UserSelection {
|
||||
const sut = new UserSelection(this.collection, this.existingScripts);
|
||||
sut.changed.on((s) => this.events.push(s));
|
||||
return sut;
|
||||
private existingScripts: readonly SelectedScript[] = [];
|
||||
|
||||
private events: Array<readonly SelectedScript[]> = [];
|
||||
|
||||
private sut: UserSelection;
|
||||
|
||||
public withCategory(categoryId: number, scripts: readonly IScript[]) {
|
||||
const category = new CategoryStub(categoryId)
|
||||
.withScripts(...scripts);
|
||||
this.collection
|
||||
.withAction(category);
|
||||
return this;
|
||||
}
|
||||
|
||||
public withSelectedScripts(existingScripts: readonly SelectedScript[]) {
|
||||
this.existingScripts = existingScripts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public run(runner?: (sut: UserSelection) => void) {
|
||||
this.sut = this.createSut();
|
||||
if (runner) {
|
||||
runner(this.sut);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public expectTotalFiredEvents(amount: number) {
|
||||
const testName = amount === 0 ? 'does not fire changed event' : `fires changed event ${amount} times`;
|
||||
it(testName, () => {
|
||||
expect(this.events).to.have.lengthOf(amount);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public expectFinalScripts(finalScripts: readonly SelectedScript[]) {
|
||||
expectSameScripts(finalScripts, this.sut.selectedScripts);
|
||||
return this;
|
||||
}
|
||||
|
||||
public expectFinalScriptsInEvent(eventIndex: number, finalScripts: readonly SelectedScript[]) {
|
||||
expectSameScripts(this.events[eventIndex], finalScripts);
|
||||
return this;
|
||||
}
|
||||
|
||||
private createSut(): UserSelection {
|
||||
const sut = new UserSelection(this.collection, this.existingScripts);
|
||||
sut.changed.on((s) => this.events.push(s));
|
||||
return sut;
|
||||
}
|
||||
}
|
||||
|
||||
function expectSameScripts(actual: readonly SelectedScript[], expected: readonly SelectedScript[]) {
|
||||
it('has same expected scripts', () => {
|
||||
const existingScriptIds = expected.map((script) => script.id).sort();
|
||||
const expectedScriptIds = actual.map((script) => script.id).sort();
|
||||
expect(existingScriptIds).to.deep.equal(expectedScriptIds);
|
||||
});
|
||||
it('has expected revert state', () => {
|
||||
const scriptsWithDifferentStatus = actual
|
||||
.filter((script) => {
|
||||
const other = expected.find((existing) => existing.id === script.id);
|
||||
if (!other) {
|
||||
throw new Error(`Script "${script.id}" does not exist in expected scripts: ${JSON.stringify(expected, null, '\t')}`);
|
||||
}
|
||||
return script.revert !== other.revert;
|
||||
});
|
||||
expect(scriptsWithDifferentStatus).to.have
|
||||
.lengthOf(0, 'Scripts with different statuses:\n' + scriptsWithDifferentStatus
|
||||
.map((s) =>
|
||||
`[id: ${s.id}, actual status: ${s.revert}, ` +
|
||||
`expected status: ${expected.find((existing) => existing.id === s.id).revert}]`)
|
||||
.join(' , '),
|
||||
);
|
||||
});
|
||||
it('has same expected scripts', () => {
|
||||
const existingScriptIds = expected.map((script) => script.id).sort();
|
||||
const expectedScriptIds = actual.map((script) => script.id).sort();
|
||||
expect(existingScriptIds).to.deep.equal(expectedScriptIds);
|
||||
});
|
||||
it('has expected revert state', () => {
|
||||
const scriptsWithDifferentStatus = actual
|
||||
.filter((script) => {
|
||||
const other = expected.find((existing) => existing.id === script.id);
|
||||
if (!other) {
|
||||
throw new Error(`Script "${script.id}" does not exist in expected scripts: ${JSON.stringify(expected, null, '\t')}`);
|
||||
}
|
||||
return script.revert !== other.revert;
|
||||
});
|
||||
expect(scriptsWithDifferentStatus).to.have.lengthOf(
|
||||
0,
|
||||
`Scripts with different statuses:\n${
|
||||
scriptsWithDifferentStatus
|
||||
.map((s) => `[id: ${s.id}, actual status: ${s.revert}, `
|
||||
+ `expected status: ${expected.find((existing) => existing.id === s.id).revert}]`)
|
||||
.join(' , ')
|
||||
}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user