diff options
Diffstat (limited to 'test/content')
-rw-r--r-- | test/content/domains/KeySequence.test.ts | 166 | ||||
-rw-r--r-- | test/content/usecases/KeymapUseCase.test.ts | 204 |
2 files changed, 321 insertions, 49 deletions
diff --git a/test/content/domains/KeySequence.test.ts b/test/content/domains/KeySequence.test.ts new file mode 100644 index 0000000..bc16189 --- /dev/null +++ b/test/content/domains/KeySequence.test.ts @@ -0,0 +1,166 @@ +import KeySequence from '../../../src/content/domains/KeySequence'; +import { expect } from 'chai' +import Key from "../../../src/shared/settings/Key"; + +describe("KeySequence", () => { + describe('#push', () => { + it('append a key to the sequence', () => { + let seq = new KeySequence([]); + seq.push(Key.fromMapKey('g')); + seq.push(Key.fromMapKey('<S-U>')); + + expect(seq.keys[0].key).to.equal('g'); + expect(seq.keys[1].key).to.equal('U'); + expect(seq.keys[1].shift).to.be.true; + }) + }); + + describe('#startsWith', () => { + it('returns true if the key sequence starts with param', () => { + let seq = new KeySequence([ + Key.fromMapKey('g'), + Key.fromMapKey('<S-U>'), + ]); + + expect(seq.startsWith(new KeySequence([ + ]))).to.be.true; + expect(seq.startsWith(new KeySequence([ + Key.fromMapKey('g'), + ]))).to.be.true; + expect(seq.startsWith(new KeySequence([ + Key.fromMapKey('g'), Key.fromMapKey('<S-U>'), + ]))).to.be.true; + expect(seq.startsWith(new KeySequence([ + Key.fromMapKey('g'), Key.fromMapKey('<S-U>'), Key.fromMapKey('x'), + ]))).to.be.false; + expect(seq.startsWith(new KeySequence([ + Key.fromMapKey('h'), + ]))).to.be.false; + }); + + it('returns true if the empty sequence starts with an empty sequence', () => { + let seq = new KeySequence([]); + + expect(seq.startsWith(new KeySequence([]))).to.be.true; + expect(seq.startsWith(new KeySequence([ + Key.fromMapKey('h'), + ]))).to.be.false; + }) + }); + + describe('#isDigitOnly', () => { + it('returns true the keys are only digits', () => { + expect(new KeySequence([ + new Key({ key: '4' }), + new Key({ key: '0' }), + ]).isDigitOnly()).to.be.true; + expect(new KeySequence([ + new Key({ key: '4' }), + new Key({ key: '0' }), + new Key({ key: 'z' }), + ]).isDigitOnly()).to.be.false; + }) + }); + + describe('#repeatCount', () => { + it('returns repeat count with a numeric prefix', () => { + let seq = new KeySequence([ + new Key({ key: '1' }), new Key({ key: '0' }) , + new Key({ key: 'g' }), new Key({ key: 'g' }) , + ]); + expect(seq.repeatCount()).to.equal(10); + + seq = new KeySequence([ + new Key({ key: '0' }), new Key({ key: '5' }) , + new Key({ key: 'g' }), new Key({ key: 'g' }) , + ]); + expect(seq.repeatCount()).to.equal(5); + }); + + it('returns 1 if no numeric prefix', () => { + let seq = new KeySequence([ + new Key({ key: 'g' }), new Key({ key: 'g' }) , + ]); + expect(seq.repeatCount()).to.equal(1); + + seq = new KeySequence([]); + expect(seq.repeatCount()).to.equal(1); + }); + + it('returns whole keys if digits only sequence', () => { + let seq = new KeySequence([ + new Key({ key: '1' }), new Key({ key: '0' }) , + ]); + expect(seq.repeatCount()).to.equal(10); + + seq = new KeySequence([ + new Key({ key: '0' }), new Key({ key: '5' }) , + ]); + expect(seq.repeatCount()).to.equal(5); + }); + }); + + describe('#trimNumericPrefix', () => { + it('removes numeric prefix', () => { + let seq = new KeySequence([ + new Key({ key: '1' }), new Key({ key: '0' }) , + new Key({ key: 'g' }), new Key({ key: 'g' }) , new Key({ key: '3' }) , + ]).trimNumericPrefix(); + expect(seq.keys.map(key => key.key)).to.deep.equal(['g', 'g', '3']); + }); + + it('returns empty if keys contains only digis', () => { + let seq = new KeySequence([ + new Key({ key: '1' }), new Key({ key: '0' }) , + ]).trimNumericPrefix(); + expect(seq.trimNumericPrefix().keys).to.be.empty; + }); + + it('returns itself if no numeric prefix', () => { + let seq = new KeySequence([ + new Key({ key: 'g' }), new Key({ key: 'g' }) , new Key({ key: '3' }) , + ]).trimNumericPrefix(); + + expect(seq.keys.map(key => key.key)).to.deep.equal(['g', 'g', '3']); + }); + }); + + describe('#splitNumericPrefix', () => { + it('splits numeric prefix', () => { + expect(KeySequence.fromMapKeys('10gg').splitNumericPrefix()).to.deep.equal([ + KeySequence.fromMapKeys('10'), + KeySequence.fromMapKeys('gg'), + ]); + expect(KeySequence.fromMapKeys('10').splitNumericPrefix()).to.deep.equal([ + KeySequence.fromMapKeys('10'), + new KeySequence([]), + ]); + expect(KeySequence.fromMapKeys('gg').splitNumericPrefix()).to.deep.equal([ + new KeySequence([]), + KeySequence.fromMapKeys('gg'), + ]); + }); + }); + + describe('#fromMapKeys', () => { + it('returns mapped keys for Shift+Esc', () => { + let keys = KeySequence.fromMapKeys('<S-Esc>').keys; + expect(keys).to.have.lengthOf(1); + expect(keys[0].key).to.equal('Esc'); + expect(keys[0].shift).to.be.true; + }); + + it('returns mapped keys for a<C-B><A-C>d<M-e>', () => { + let keys = KeySequence.fromMapKeys('a<C-B><A-C>d<M-e>').keys; + expect(keys).to.have.lengthOf(5); + expect(keys[0].key).to.equal('a'); + expect(keys[1].ctrl).to.be.true; + expect(keys[1].key).to.equal('b'); + expect(keys[2].alt).to.be.true; + expect(keys[2].key).to.equal('c'); + expect(keys[3].key).to.equal('d'); + expect(keys[4].meta).to.be.true; + expect(keys[4].key).to.equal('e'); + }); + }) +}); diff --git a/test/content/usecases/KeymapUseCase.test.ts b/test/content/usecases/KeymapUseCase.test.ts index 5f2feba..598d5a3 100644 --- a/test/content/usecases/KeymapUseCase.test.ts +++ b/test/content/usecases/KeymapUseCase.test.ts @@ -1,3 +1,4 @@ +import "reflect-metadata"; import KeymapUseCase from '../../../src/content/usecases/KeymapUseCase'; import {expect} from 'chai'; import SettingRepository from "../../../src/content/repositories/SettingRepository"; @@ -50,7 +51,7 @@ class MockAddressRepository implements AddressRepository { describe('KeymapUseCase', () => { - it('returns matched operation', () => { + context('with no-digis keymaps', () => { let settings = Settings.fromJSON({ keymaps: { k: {type: 'scroll.vertically', count: -1}, @@ -58,21 +59,117 @@ describe('KeymapUseCase', () => { gg: {type: 'scroll.top'}, }, }); - let sut = new KeymapUseCase( - new KeymapRepositoryImpl(), - new MockSettingRepository(settings), - new MockAddonEnabledRepository(true), - new MockAddressRepository(new URL('https://example.com')), - ); - - expect(sut.nextOp(Key.fromMapKey('k'))).to.deep.equal({type: 'scroll.vertically', count: -1}); - expect(sut.nextOp(Key.fromMapKey('j'))).to.deep.equal({type: 'scroll.vertically', count: 1}); - expect(sut.nextOp(Key.fromMapKey('g'))).to.be.null; - expect(sut.nextOp(Key.fromMapKey('g'))).to.deep.equal({type: 'scroll.top'}); - expect(sut.nextOp(Key.fromMapKey('z'))).to.be.null; + + let sut: KeymapUseCase; + + before(() => { + sut = new KeymapUseCase( + new KeymapRepositoryImpl(), + new MockSettingRepository(settings), + new MockAddonEnabledRepository(true), + new MockAddressRepository(new URL('https://example.com')), + ); + }); + + it('returns matched operation', () => { + expect(sut.nextOps(Key.fromMapKey('k'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.vertically', count: -1}}); + expect(sut.nextOps(Key.fromMapKey('j'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.vertically', count: 1}}); + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.top'}}); + expect(sut.nextOps(Key.fromMapKey('z'))).to.be.null; + }); + + it('repeats n-times by numeric prefix and multiple key operations', () => { + expect(sut.nextOps(Key.fromMapKey('1'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('0'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.deep.equal({ repeat: 10, op: {type: "scroll.top"}}); + }); + }); + + context('when keymaps containing numeric mappings', () => { + let settings = Settings.fromJSON({ + keymaps: { + 20: {type: "scroll.top"}, + g5: {type: 'scroll.bottom'}, + }, + }); + + let sut: KeymapUseCase; + + before(() => { + sut = new KeymapUseCase( + new KeymapRepositoryImpl(), + new MockSettingRepository(settings), + new MockAddonEnabledRepository(true), + new MockAddressRepository(new URL('https://example.com')), + ); + }); + + it('returns the matched operation ends with digit', () => { + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('5'))).to.be.deep.equal({ repeat: 1, op: { type: 'scroll.bottom'}}); + }); + + it('returns an operation matched the operation with digit keymaps', () => { + expect(sut.nextOps(Key.fromMapKey('2'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('0'))).to.be.deep.equal({ repeat: 1, op: { type: 'scroll.top'}}); + }); + + it('returns operations repeated by numeric prefix', () => { + expect(sut.nextOps(Key.fromMapKey('2'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('5'))).to.be.deep.equal({ repeat: 2, op: { type: 'scroll.bottom'}}); + }); + + it('does not matches with digit operation with numeric prefix', () => { + expect(sut.nextOps(Key.fromMapKey('3'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('2'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('0'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('5'))).to.be.deep.equal({ repeat: 320, op: { type: 'scroll.bottom'}}); + }); }); - it('returns only ADDON_ENABLE and ADDON_TOGGLE_ENABLED operation', () => { + context('when the keys are mismatched with the operations', () => { + let settings = Settings.fromJSON({ + keymaps: { + gg: {type: "scroll.top"}, + G: {type: "scroll.bottom"}, + }, + }); + + let sut: KeymapUseCase; + + before(() => { + sut = new KeymapUseCase( + new KeymapRepositoryImpl(), + new MockSettingRepository(settings), + new MockAddonEnabledRepository(true), + new MockAddressRepository(new URL('https://example.com')), + ); + }); + + it('clears input keys with no-matched operations', () => { + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('x'))).to.be.null; // clear + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.deep.equal({repeat: 1, op: {type: "scroll.top"}}); + }); + + it('clears input keys and the prefix with no-matched operations', () => { + expect(sut.nextOps(Key.fromMapKey('1'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('0'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('x'))).to.be.null; // clear + expect(sut.nextOps(Key.fromMapKey('1'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('0'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.deep.equal({ repeat: 10, op: {type: "scroll.top"}}); + }); + }); + + context('when the site matches to the blacklist', () => { let settings = Settings.fromJSON({ keymaps: { k: {type: 'scroll.vertically', count: -1}, @@ -80,25 +177,32 @@ describe('KeymapUseCase', () => { b: {type: 'addon.toggle.enabled'}, }, }); - let sut = new KeymapUseCase( - new KeymapRepositoryImpl(), - new MockSettingRepository(settings), - new MockAddonEnabledRepository(false), - new MockAddressRepository(new URL('https://example.com')), - ); - expect(sut.nextOp(Key.fromMapKey('k'))).to.be.null; - expect(sut.nextOp(Key.fromMapKey('a'))).to.deep.equal({type: 'addon.enable'}); - expect(sut.nextOp(Key.fromMapKey('b'))).to.deep.equal({type: 'addon.toggle.enabled'}); + let sut: KeymapUseCase; + + before(() => { + sut = new KeymapUseCase( + new KeymapRepositoryImpl(), + new MockSettingRepository(settings), + new MockAddonEnabledRepository(false), + new MockAddressRepository(new URL('https://example.com')), + ); + }); + + it('returns only ADDON_ENABLE and ADDON_TOGGLE_ENABLED operation', () => { + expect(sut.nextOps(Key.fromMapKey('k'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('a'))).to.deep.equal({ repeat: 1, op: {type: 'addon.enable'}}); + expect(sut.nextOps(Key.fromMapKey('b'))).to.deep.equal({ repeat: 1, op: {type: 'addon.toggle.enabled'}}); + }); }); - it('blocks keys in the partial blacklist', () => { + context('when the site matches to the partial blacklist', () => { let settings = Settings.fromJSON({ keymaps: { k: {type: 'scroll.vertically', count: -1}, j: {type: 'scroll.vertically', count: 1}, - gg: {"type": "scroll.top"}, - G: {"type": "scroll.bottom"}, + gg: {type: "scroll.top"}, + G: {type: "scroll.bottom"}, }, blacklist: [ { url: "example.com", keys: ['g'] }, @@ -106,28 +210,30 @@ describe('KeymapUseCase', () => { ], }); - let sut = new KeymapUseCase( - new KeymapRepositoryImpl(), - new MockSettingRepository(settings), - new MockAddonEnabledRepository(true), - new MockAddressRepository(new URL('https://example.com')), - ); - - expect(sut.nextOp(Key.fromMapKey('k'))).to.deep.equal({type: 'scroll.vertically', count: -1}); - expect(sut.nextOp(Key.fromMapKey('j'))).to.deep.equal({type: 'scroll.vertically', count: 1}); - expect(sut.nextOp(Key.fromMapKey('g'))).to.be.null; - expect(sut.nextOp(Key.fromMapKey('g'))).to.be.null; - expect(sut.nextOp(Key.fromMapKey('G'))).to.deep.equal({type: 'scroll.bottom'}); - - sut = new KeymapUseCase( - new KeymapRepositoryImpl(), - new MockSettingRepository(settings), - new MockAddonEnabledRepository(true), - new MockAddressRepository(new URL('https://example.org')), - ); - - expect(sut.nextOp(Key.fromMapKey('g'))).to.be.null; - expect(sut.nextOp(Key.fromMapKey('g'))).to.deep.equal({type: 'scroll.top'}); - expect(sut.nextOp(Key.fromMapKey('G'))).to.be.null; + it('blocks keys in the partial blacklist', () => { + let sut = new KeymapUseCase( + new KeymapRepositoryImpl(), + new MockSettingRepository(settings), + new MockAddonEnabledRepository(true), + new MockAddressRepository(new URL('https://example.com')), + ); + + expect(sut.nextOps(Key.fromMapKey('k'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.vertically', count: -1}}); + expect(sut.nextOps(Key.fromMapKey('j'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.vertically', count: 1}}); + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('G'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.bottom'}}); + + sut = new KeymapUseCase( + new KeymapRepositoryImpl(), + new MockSettingRepository(settings), + new MockAddonEnabledRepository(true), + new MockAddressRepository(new URL('https://example.org')), + ); + + expect(sut.nextOps(Key.fromMapKey('g'))).to.be.null; + expect(sut.nextOps(Key.fromMapKey('g'))).to.deep.equal({ repeat: 1, op: {type: 'scroll.top'}}); + expect(sut.nextOps(Key.fromMapKey('G'))).to.be.null; + }); }); }); |