test(serializer): Add KeystrokeAction tests (#430)

* test: add basis of the unit testing of the uhk-common package

* test(serializer): Add KeystrokeAction tests

* fix(serializer): Fix KeystrokeAction scancode mapping

* test(serializer): Add NoneAction test cases

* test(serializer): Add MouseAction test cases

* test(serializer): Add PlayMacroAction test cases

* test(serializer): Add SwitchKeymapAction test cases

* test(serializer): Add UserConfiguration test cases

fix KeyAction mapping

* test(serializer): Add SwitchLayerAction test cases
This commit is contained in:
Róbert Kiss
2017-10-06 22:24:33 +02:00
committed by László Monda
parent 85bc5b94e1
commit 35c0d98cd2
19 changed files with 4148 additions and 17 deletions

View File

@@ -30,4 +30,11 @@ describe('Test Serializer', () => {
expect(buffersContentsAreEqual).toBe(true);
});
it('check json serializer', () => {
const config1Ts: UserConfiguration = new UserConfiguration().fromJsonObject(userConfig);
const jsonObject = config1Ts.toJsonObject();
expect(jsonObject).toEqual(userConfig);
});
});

2
packages/uhk-common/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.nyc_output/
coverage/

View File

@@ -1,4 +1 @@
export * from './src/util';
export * from './src/models';
export * from './src/services';
export * from './src/config-serializer';
export * from './src';

View File

@@ -0,0 +1,8 @@
{
"spec_dir": "src",
"spec_files": [
"**/*.ts"
],
"stopSpecOnExpectationFailure": true,
"random": false
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,16 +4,42 @@
"version": "1.0.0",
"description": "Common Library contains the common code for uhk-agent (electron-main) and web (electron-renderer) modules",
"main": "dist/index.js",
"author": "Ultimate Gadget Laboratories",
"repository": {
"type": "git",
"url": "git@github.com:UltimateHackingKeyboard/agent.git"
},
"scripts": {
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "jasmine-ts --config=jasmine.json",
"coverage": "nyc jasmine-ts --config=jasmine.json"
},
"author": "",
"license": "ISC",
"license": "GPL-3.0",
"devDependencies": {
"@angular/core": "4.3.3",
"@ngrx/core": "1.2.0",
"@types/jasmine": "2.6.0",
"@ngrx/store": "2.2.3",
"@types/node": "8.0.28"
"@types/node": "8.0.30",
"jasmine": "2.8.0",
"jasmine-core": "2.8.0",
"jasmine-node": "2.0.0",
"jasmine-ts": "0.2.1",
"nyc": "11.2.1",
"ts-node": "3.3.0"
},
"nyc": {
"extension": [
".ts"
],
"include": [
"src/**/*.ts"
],
"exclude": [
"src/**/*.spec.ts"
],
"reporter": [
"lcov"
]
}
}

View File

@@ -63,7 +63,7 @@ export class Helper {
private static fromJSONObject(keyAction: any, macros: Macro[]): KeyAction {
if (!keyAction) {
return;
return null;
}
switch (keyAction.keyActionType) {

View File

@@ -0,0 +1,303 @@
import { KeystrokeAction } from './keystroke-action';
import { KeystrokeType } from './keystroke-type';
import { LongPressAction } from '../long-press-action';
describe('keystroke-action', () => {
it('should be instantiate', () => {
const action = new KeystrokeAction();
expect(action).toBeTruthy();
});
it('Should be inherit from other KeyStroke', () => {
const other = new KeystrokeAction();
other.type = KeystrokeType.basic;
other.scancode = 125;
other.modifierMask = 1;
other.longPressAction = LongPressAction.leftAlt;
const action = new KeystrokeAction(other);
expect(action).toEqual(other);
});
describe('set scancode', () => {
it('should store the value without modification', () => {
const value = 125;
const action = new KeystrokeAction();
action.scancode = value;
expect(action.scancode).toEqual(value);
});
it('should not change the "type" when is "basic"', () => {
const type = KeystrokeType.basic;
const action = new KeystrokeAction();
action.type = type;
action.scancode = 125;
expect(action.type).toEqual(type);
});
it('should not change the "type" when is "system"', () => {
const type = KeystrokeType.system;
const action = new KeystrokeAction();
action.type = type;
action.scancode = 125;
expect(action.type).toEqual(type);
});
it('should not change the "type" when is "shortMedia" if scancode < 256', () => {
const type = KeystrokeType.shortMedia;
const action = new KeystrokeAction();
action.type = type;
action.scancode = 125;
expect(action.type).toEqual(type);
});
it('should not change the "type" to "shortMedia" when is "longMedia" if scancode < 256', () => {
const action = new KeystrokeAction();
action.type = KeystrokeType.longMedia;
action.scancode = 125;
expect(action.type).toEqual(KeystrokeType.shortMedia);
});
it('should not change the "type" when is "longMedia" if scancode >= 256', () => {
const type = KeystrokeType.longMedia;
const action = new KeystrokeAction();
action.type = type;
action.scancode = 256;
expect(action.type).toEqual(type);
});
it('should not change the "type" to "longMedia" when is "shortMedia" if scancode >= 256', () => {
const action = new KeystrokeAction();
action.type = KeystrokeType.shortMedia;
action.scancode = 256;
expect(action.type).toEqual(KeystrokeType.longMedia);
});
});
describe('modifierMask', () => {
it('should store the value without modification', () => {
const value = 100;
const action = new KeystrokeAction();
action.modifierMask = value;
expect(action.modifierMask).toEqual(value);
});
it('should throw an error when value < 0', () => {
const value = -1;
function test() {
const action = new KeystrokeAction();
action.modifierMask = value;
}
expect(test).toThrow(`KeystrokeAction.modifierMask: Integer ${value} is outside the valid [0, 255] interval`);
});
it('should throw an error when value > 255', () => {
const value = 256;
function test() {
const action = new KeystrokeAction();
action.modifierMask = value;
}
expect(test).toThrow(`KeystrokeAction.modifierMask: Integer ${value} is outside the valid [0, 255] interval`);
});
});
describe('longPressAction', () => {
it('should store the value without modification', () => {
const value = LongPressAction.leftAlt;
const action = new KeystrokeAction();
action.longPressAction = value;
expect(action.longPressAction).toEqual(value);
});
});
describe('type', () => {
it('should not change the value if value "basic"', () => {
const value = KeystrokeType.basic;
const scancode = 200;
const action = new KeystrokeAction();
action.scancode = scancode;
action.type = value;
expect(action.type).toEqual(value);
expect(action.scancode).toEqual(scancode);
});
it('should not change the value if value "system"', () => {
const value = KeystrokeType.system;
const scancode = 200;
const action = new KeystrokeAction();
action.scancode = scancode;
action.type = value;
expect(action.type).toEqual(value);
expect(action.scancode).toEqual(scancode);
});
it('should not change the value if scancode >= 256 and value "longMedia"', () => {
const value = KeystrokeType.longMedia;
const scancode = 256;
const action = new KeystrokeAction();
action.scancode = scancode;
action.type = value;
expect(action.type).toEqual(value);
expect(action.scancode).toEqual(scancode);
});
it('should change the value to "longMedia" if scancode >= 256 and value "shortMedia"', () => {
const value = KeystrokeType.shortMedia;
const scancode = 256;
const action = new KeystrokeAction();
action.scancode = scancode;
action.type = value;
expect(action.type).toEqual(KeystrokeType.longMedia);
expect(action.scancode).toEqual(scancode);
});
it('should not change the value if scancode < 256 and value "shortMedia"', () => {
const value = KeystrokeType.shortMedia;
const scancode = 100;
const action = new KeystrokeAction();
action.scancode = scancode;
action.type = value;
expect(action.type).toEqual(value);
expect(action.scancode).toEqual(scancode);
});
it('should change the value to "shortMedia" if scancode < 256 and value "longMedia"', () => {
const value = KeystrokeType.longMedia;
const scancode = 100;
const action = new KeystrokeAction();
action.scancode = scancode;
action.type = value;
expect(action.type).toEqual(KeystrokeType.shortMedia);
expect(action.scancode).toEqual(scancode);
});
});
describe('fromJsonObject', () => {
it('should map "basic" type', () => {
const jsObject = {
keyActionType: 'keystroke',
type: 'basic',
scancode: 100,
modifierMask: 10,
longPressAction: 'leftAlt'
};
const action = new KeystrokeAction();
action.fromJsonObject(jsObject);
const expected = new KeystrokeAction();
expected.type = KeystrokeType.basic;
expected.scancode = 100;
expected.modifierMask = 10;
expected.longPressAction = LongPressAction.leftAlt;
expect(action).toEqual(expected);
});
it('should map "system" type', () => {
const jsObject = {
keyActionType: 'keystroke',
type: 'system',
scancode: 100,
modifierMask: 10,
longPressAction: 'leftAlt'
};
const action = new KeystrokeAction();
action.fromJsonObject(jsObject);
const expected = new KeystrokeAction();
expected.type = KeystrokeType.system;
expected.scancode = 100;
expected.modifierMask = 10;
expected.longPressAction = LongPressAction.leftAlt;
expect(action).toEqual(expected);
});
it('should map "media" type to "shortMedia" if scancode < 256', () => {
const jsObject = {
keyActionType: 'keystroke',
type: 'media',
scancode: 100,
modifierMask: 10,
longPressAction: 'leftAlt'
};
const action = new KeystrokeAction();
action.fromJsonObject(jsObject);
const expected = new KeystrokeAction();
expected.type = KeystrokeType.shortMedia;
expected.scancode = 100;
expected.modifierMask = 10;
expected.longPressAction = LongPressAction.leftAlt;
expect(action).toEqual(expected);
});
it('should map "media" type to "longMedia" if scancode <= 256', () => {
const jsObject = {
keyActionType: 'keystroke',
type: 'media',
scancode: 256,
modifierMask: 10,
longPressAction: 'leftAlt'
};
const action = new KeystrokeAction();
action.fromJsonObject(jsObject);
const expected = new KeystrokeAction();
expected.type = KeystrokeType.longMedia;
expected.scancode = 256;
expected.modifierMask = 10;
expected.longPressAction = LongPressAction.leftAlt;
expect(action).toEqual(expected);
});
});
describe('fromBinary', () => {
});
describe('toJsonObject', () => {
});
describe('toBinary', () => {
});
describe('toString', () => {
});
describe('isActive', () => {
});
describe('hasActiveModifier', () => {
});
describe('hasLongPressAction', () => {
});
describe('hasScancode', () => {
});
describe('hasOnlyOneActiveModifier', () => {
});
describe('getModifierList', () => {
});
describe('getName', () => {
});
});

View File

@@ -65,7 +65,7 @@ export class KeystrokeAction extends KeyAction {
return;
}
this.type = other.type;
this._scancode = other._scancode;
this.scancode = other.scancode;
this.modifierMask = other.modifierMask;
this.longPressAction = other.longPressAction;
}
@@ -77,7 +77,8 @@ export class KeystrokeAction extends KeyAction {
} else {
this.type = KeystrokeType[jsonObject.type];
}
this._scancode = jsonObject.scancode;
this.scancode = jsonObject.scancode;
this.modifierMask = jsonObject.modifierMask;
this.longPressAction = LongPressAction[jsonObject.longPressAction];
return this;
@@ -134,17 +135,17 @@ export class KeystrokeAction extends KeyAction {
if (this.hasScancode()) {
flags |= KeystrokeActionFlag.scancode;
toWrite.push({ data: this._scancode, long: this.type === KeystrokeType.longMedia });
toWrite.push({data: this._scancode, long: this.type === KeystrokeType.longMedia});
}
if (this.hasActiveModifier()) {
flags |= KeystrokeActionFlag.modifierMask;
toWrite.push({ data: this.modifierMask, long: false });
toWrite.push({data: this.modifierMask, long: false});
}
if (this.hasLongPressAction()) {
flags |= KeystrokeActionFlag.longPressAction;
toWrite.push({ data: this.longPressAction, long: false });
toWrite.push({data: this.longPressAction, long: false});
}
const TYPE_OFFSET = flags + (this.type << KEYSTROKE_ACTION_FLAG_LENGTH);

View File

@@ -0,0 +1,39 @@
import { binaryDefaultHelper, jsonDefaultHelper } from '../../../../test/serializer-test-helper';
import { MouseAction, MouseActionParam } from './mouse-action';
// TODO: Add null, undefined, empty object, empty buffer test cases
describe('mouse-action', () => {
it('should be instantiate', () => {
const action = new MouseAction();
expect(action).toBeTruthy();
});
describe('toString', () => {
it(`should return with <MouseAction mouseAction="${MouseActionParam.leftClick}">`, () => {
const action = new MouseAction();
action.mouseAction = MouseActionParam.leftClick;
expect(action.toString()).toEqual(`<MouseAction mouseAction="${MouseActionParam.leftClick}">`);
});
});
describe('getName', () => {
it('should return with "MouseAction"', () => {
const action = new MouseAction();
expect(action.getName()).toEqual('MouseAction');
});
});
describe('full serialization', () => {
it('should json match', () => {
const action = new MouseAction();
action.mouseAction = MouseActionParam.leftClick;
jsonDefaultHelper(action);
});
it('should binary match', () => {
const action = new MouseAction();
action.mouseAction = MouseActionParam.leftClick;
binaryDefaultHelper(action);
});
});
});

View File

@@ -0,0 +1,73 @@
import { NoneAction } from './none-action';
import { keyActionType } from './key-action';
import { UhkBuffer } from '../../uhk-buffer';
import { binaryDefaultHelper, jsonDefaultHelper } from '../../../../test/serializer-test-helper';
// TODO: Add null, undefined, empty object, empty buffer test cases
describe('node-action', () => {
it('should be instantiate', () => {
const action = new NoneAction();
expect(action).toBeTruthy();
});
describe('fromJsonObject', () => {
it('should map null', () => {
const action = new NoneAction();
expect(action.fromJsonObject({keyActionType: keyActionType.NoneAction})).toEqual(new NoneAction());
});
});
describe('toJsonObject', () => {
it('should work', () => {
const action = new NoneAction();
expect(action.toJsonObject()).toEqual({
keyActionType: keyActionType.NoneAction
});
});
});
describe('fromBinary', () => {
it('should work', () => {
const buffer = new UhkBuffer();
const action = new NoneAction();
action.toBinary(buffer);
expect(action).toEqual(new NoneAction());
});
});
describe('toBinary', () => {
it('should work', () => {
const buffer = new UhkBuffer();
const action = new NoneAction();
action.toBinary(buffer);
const expected = new UhkBuffer();
expected.offset = 1;
expect(buffer).toEqual(expected);
});
});
describe('toString', () => {
it('should return with "<NoneAction>"', () => {
const action = new NoneAction();
expect(action.toString()).toEqual('<NoneAction>');
});
});
describe('getName', () => {
it('should return with "NoneAction"', () => {
const action = new NoneAction();
expect(action.getName()).toEqual('NoneAction');
});
});
describe('full serialization', () => {
it('should json match with default constructor', () => {
jsonDefaultHelper(new NoneAction());
});
it('should binary match with default constructor', () => {
binaryDefaultHelper(new NoneAction());
});
});
});

View File

@@ -0,0 +1,42 @@
import { binaryDefaultHelper, jsonDefaultHelper } from '../../../../test/serializer-test-helper';
import { PlayMacroAction } from './play-macro-action';
// TODO: Add null, undefined, empty object, empty buffer test cases
describe('play-action', () => {
const macros = [{id: 1}, {id: 2}];
const userConfiguration = {macros};
it('should be instantiate', () => {
const action = new PlayMacroAction();
expect(action).toBeTruthy();
});
describe('toString', () => {
it('should return <PlayMacroAction macroId="1">', () => {
const action = new PlayMacroAction();
action.macroId = 1;
expect(action.toString()).toEqual('<PlayMacroAction macroId="1">');
});
});
describe('getName', () => {
it('should return with "PlayMacroAction"', () => {
const action = new PlayMacroAction();
expect(action.getName()).toEqual('PlayMacroAction');
});
});
describe('full serialization', () => {
it('should json match', () => {
const action = new PlayMacroAction();
action.macroId = 1;
jsonDefaultHelper(action, macros, macros);
});
it('should binary match', () => {
const action = new PlayMacroAction();
action.macroId = 1;
binaryDefaultHelper(action, userConfiguration, macros);
});
});
});

View File

@@ -0,0 +1,43 @@
import { binaryDefaultHelper, jsonDefaultHelper } from '../../../../test/serializer-test-helper';
import { SwitchKeymapAction } from './switch-keymap-action';
// TODO: Add null, undefined, empty object, empty buffer test cases
describe('switch-keymap-action', () => {
const userConfiguration = {
keymaps: [
{abbreviation: 'AB1'},
{abbreviation: 'AB2'}
]
};
it('should be instantiate', () => {
const action = new SwitchKeymapAction();
expect(action).toBeTruthy();
});
describe('toString', () => {
it('should return <SwitchKeymapAction keymapAbbreviation="ABB">', () => {
const action = new SwitchKeymapAction('ABB');
expect(action.toString()).toEqual('<SwitchKeymapAction keymapAbbreviation="ABB">');
});
});
describe('getName', () => {
it('should return with "SwitchKeymapAction"', () => {
const action = new SwitchKeymapAction();
expect(action.getName()).toEqual('SwitchKeymapAction');
});
});
describe('full serialization', () => {
it('should json match', () => {
const action = new SwitchKeymapAction('AB1');
jsonDefaultHelper(action, null, userConfiguration);
});
it('should binary match', () => {
const action = new SwitchKeymapAction('AB1');
binaryDefaultHelper(action, userConfiguration, userConfiguration);
});
});
});

View File

@@ -35,6 +35,14 @@ export class SwitchKeymapAction extends KeyAction {
};
}
// TODO: New method pls check UnresolvedSwitchKeymapAction TODO
fromBinary(buffer: UhkBuffer, userConfiguration: UserConfiguration): SwitchKeymapAction {
buffer.readUInt8(); // Skip key action id
const keymapIndex = buffer.readUInt8();
this.keymapAbbreviation = userConfiguration.keymaps[keymapIndex].abbreviation;
return this;
}
toBinary(buffer: UhkBuffer, userConfiguration: UserConfiguration): void {
const keymapIndex = userConfiguration.keymaps.findIndex(keymap => keymap.abbreviation === this.keymapAbbreviation);
buffer.writeUInt8(KeyActionId.SwitchKeymapAction);
@@ -45,6 +53,10 @@ export class SwitchKeymapAction extends KeyAction {
return `<SwitchKeymapAction keymapAbbreviation="${this.keymapAbbreviation}">`;
}
// TODO: It is a bad pattern the method should have same behavior
// Not good if sometimes return with the same keymap and sometime a new instance
// for the consistent behavior it should be throw and error if
// oldAbbr not equal with current keymapAbbreviation
renameKeymap(oldAbbr: string, newAbbr: string): KeyAction {
if (this.keymapAbbreviation !== oldAbbr) {
return this;
@@ -57,6 +69,10 @@ export class SwitchKeymapAction extends KeyAction {
}
}
// TODO: This is unnecessary object.
// move the fromBinary() method to the SwitchKeymapAction
// and append the resolve() method logic to the new fromBinary()
// I checked and hard to delete this class.
export class UnresolvedSwitchKeymapAction extends KeyAction {
@assertUInt8

View File

@@ -0,0 +1,33 @@
import { binaryDefaultHelper, jsonDefaultHelper } from '../../../../test/serializer-test-helper';
import { SwitchLayerAction } from './switch-layer-action';
// TODO: Add null, undefined, empty object, empty buffer test cases
describe('switch-layer-action', () => {
const action = new SwitchLayerAction(<SwitchLayerAction>{layer: 0, isLayerToggleable: false});
it('should be instantiate', () => {
expect(new SwitchLayerAction()).toBeTruthy();
});
describe('toString', () => {
it('should return <SwitchLayerAction layer="0" toggle="false">', () => {
expect(action.toString()).toEqual('<SwitchLayerAction layer="0" toggle="false">');
});
});
describe('getName', () => {
it('should return with "SwitchLayerAction"', () => {
expect(action.getName()).toEqual('SwitchLayerAction');
});
});
describe('full serialization', () => {
it('should json match', () => {
jsonDefaultHelper(action);
});
it('should binary match', () => {
binaryDefaultHelper(action);
});
});
});

View File

@@ -57,6 +57,7 @@ export class Module {
if (keyAction && (macros || !(keyAction instanceof PlayMacroAction || keyAction instanceof SwitchKeymapAction))) {
return keyAction.toJsonObject(macros);
}
return null;
})
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
export * from './util';
export * from './models';
export * from './services';
export * from './config-serializer';

View File

@@ -0,0 +1,19 @@
import { UhkBuffer } from '../src/config-serializer';
export function jsonDefaultHelper(baseObject: any, serializationParam?: any, deserializationParam?: any): void {
const json = baseObject.toJsonObject(serializationParam);
const newObject = new baseObject.constructor;
newObject.fromJsonObject(json, deserializationParam);
expect(newObject).toEqual(baseObject);
}
export function binaryDefaultHelper(baseObject: any, serializerParam?: any, deserializationParam?: any): void {
const buffer = new UhkBuffer();
baseObject.toBinary(buffer, serializerParam);
buffer.offset = 0;
const newObject = new baseObject.constructor;
newObject.fromBinary(buffer, deserializationParam);
expect(newObject).toEqual(baseObject);
}