diff options
| author | Shin'ya Ueoka <ueokande@i-beam.org> | 2019-12-22 10:47:00 +0900 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-22 10:47:00 +0900 | 
| commit | b2dcdedad729ff7087867da50e20578f9fc8fb29 (patch) | |
| tree | 033ecffbd7db9b6db8000464a68d748fcae1dc3d /test/content | |
| parent | 3c7230c3036e8bb2b2e9a752be9b0ef4a0a7349d (diff) | |
| parent | 75f86907fc2699c0f0661d4780c38249a18f849b (diff) | |
Merge pull request #689 from ueokande/n-times-repeat-operations
Repeat commands n-times
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; +    });    });  }); | 
