parent
e76ca380f7
commit
bacf83a320
16 changed files with 223 additions and 196 deletions
@ -1,28 +0,0 @@ |
||||
import * as actions from './index'; |
||||
import * as operations from '../../shared/operations'; |
||||
import * as messages from '../../shared/messages'; |
||||
import Settings, { Keymaps } from '../../shared/Settings'; |
||||
|
||||
const reservedKeymaps: Keymaps = { |
||||
'<Esc>': { type: operations.CANCEL }, |
||||
'<C-[>': { type: operations.CANCEL }, |
||||
}; |
||||
|
||||
const set = (settings: Settings): actions.SettingAction => { |
||||
return { |
||||
type: actions.SETTING_SET, |
||||
settings: { |
||||
...settings, |
||||
keymaps: { ...settings.keymaps, ...reservedKeymaps }, |
||||
} |
||||
}; |
||||
}; |
||||
|
||||
const load = async(): Promise<actions.SettingAction> => { |
||||
let settings = await browser.runtime.sendMessage({ |
||||
type: messages.SETTINGS_QUERY, |
||||
}); |
||||
return set(settings); |
||||
}; |
||||
|
||||
export { set, load }; |
@ -0,0 +1,17 @@ |
||||
import Settings from '../../shared/Settings'; |
||||
import * as messages from '../../shared/messages'; |
||||
|
||||
export default interface SettingClient { |
||||
load(): Promise<Settings>; |
||||
|
||||
// eslint-disable-next-line semi
|
||||
} |
||||
|
||||
export class SettingClientImpl { |
||||
async load(): Promise<Settings> { |
||||
let settings = await browser.runtime.sendMessage({ |
||||
type: messages.SETTINGS_QUERY, |
||||
}); |
||||
return settings as Settings; |
||||
} |
||||
} |
@ -1,40 +0,0 @@ |
||||
import * as actions from '../actions'; |
||||
import * as keyUtils from '../../shared/utils/keys'; |
||||
import * as operations from '../../shared/operations'; |
||||
import { Search, Properties, DefaultSetting } from '../../shared/Settings'; |
||||
|
||||
export interface State { |
||||
keymaps: { key: keyUtils.Key[], op: operations.Operation }[]; |
||||
search: Search; |
||||
properties: Properties; |
||||
} |
||||
|
||||
// defaultState does not refer due to the state is load from
|
||||
// background on load.
|
||||
const defaultState: State = { |
||||
keymaps: [], |
||||
search: DefaultSetting.search, |
||||
properties: DefaultSetting.properties, |
||||
}; |
||||
|
||||
export default function reducer( |
||||
state: State = defaultState, |
||||
action: actions.SettingAction, |
||||
): State { |
||||
switch (action.type) { |
||||
case actions.SETTING_SET: |
||||
return { |
||||
keymaps: Object.entries(action.settings.keymaps).map((entry) => { |
||||
return { |
||||
key: keyUtils.fromMapKeys(entry[0]), |
||||
op: entry[1], |
||||
}; |
||||
}), |
||||
properties: action.settings.properties, |
||||
search: action.settings.search, |
||||
}; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
||||
|
@ -0,0 +1,22 @@ |
||||
import Settings, { DefaultSetting } from '../../shared/Settings'; |
||||
|
||||
let current: Settings = DefaultSetting; |
||||
|
||||
export default interface SettingRepository { |
||||
set(setting: Settings): void; |
||||
|
||||
get(): Settings; |
||||
|
||||
// eslint-disable-next-line semi
|
||||
} |
||||
|
||||
export class SettingRepositoryImpl implements SettingRepository { |
||||
set(setting: Settings): void { |
||||
current = setting; |
||||
} |
||||
|
||||
get(): Settings { |
||||
return current; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,24 @@ |
||||
import SettingRepository, { SettingRepositoryImpl } |
||||
from '../repositories/SettingRepository'; |
||||
import SettingClient, { SettingClientImpl } from '../client/SettingClient'; |
||||
import Settings from '../../shared/Settings'; |
||||
|
||||
export default class SettingUseCase { |
||||
private repository: SettingRepository; |
||||
|
||||
private client: SettingClient; |
||||
|
||||
constructor({ |
||||
repository = new SettingRepositoryImpl(), |
||||
client = new SettingClientImpl(), |
||||
} = {}) { |
||||
this.repository = repository; |
||||
this.client = client; |
||||
} |
||||
|
||||
async reload(): Promise<Settings> { |
||||
let settings = await this.client.load(); |
||||
this.repository.set(settings); |
||||
return settings; |
||||
} |
||||
} |
@ -1,43 +0,0 @@ |
||||
import * as actions from 'content/actions'; |
||||
import * as settingActions from 'content/actions/setting'; |
||||
|
||||
describe("setting actions", () => { |
||||
describe("set", () => { |
||||
it('create SETTING_SET action', () => { |
||||
let action = settingActions.set({ |
||||
keymaps: { |
||||
'dd': 'remove current tab', |
||||
'z<C-A>': 'increment', |
||||
}, |
||||
search: { |
||||
default: "google", |
||||
engines: { |
||||
google: 'https://google.com/search?q={}', |
||||
} |
||||
}, |
||||
properties: { |
||||
hintchars: 'abcd1234', |
||||
}, |
||||
blacklist: [], |
||||
}); |
||||
expect(action.type).to.equal(actions.SETTING_SET); |
||||
expect(action.settings.properties.hintchars).to.equal('abcd1234'); |
||||
}); |
||||
|
||||
it('overrides cancel keys', () => { |
||||
let action = settingActions.set({ |
||||
keymaps: { |
||||
"k": { "type": "scroll.vertically", "count": -1 }, |
||||
"j": { "type": "scroll.vertically", "count": 1 }, |
||||
} |
||||
}); |
||||
let keymaps = action.settings.keymaps; |
||||
expect(action.settings.keymaps).to.deep.equals({ |
||||
"k": { type: "scroll.vertically", count: -1 }, |
||||
"j": { type: "scroll.vertically", count: 1 }, |
||||
'<Esc>': { type: 'cancel' }, |
||||
'<C-[>': { type: 'cancel' }, |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
@ -1,31 +0,0 @@ |
||||
import * as actions from 'content/actions'; |
||||
import settingReducer from 'content/reducers/setting'; |
||||
|
||||
describe("content setting reducer", () => { |
||||
it('return the initial state', () => { |
||||
let state = settingReducer(undefined, {}); |
||||
expect(state.keymaps).to.be.empty; |
||||
}); |
||||
|
||||
it('return next state for SETTING_SET', () => { |
||||
let newSettings = { red: 'apple', yellow: 'banana' }; |
||||
let action = { |
||||
type: actions.SETTING_SET, |
||||
settings: { |
||||
keymaps: { |
||||
"zz": { type: "zoom.neutral" }, |
||||
"<S-Esc>": { "type": "addon.toggle.enabled" } |
||||
}, |
||||
"blacklist": [] |
||||
} |
||||
} |
||||
let state = settingReducer(undefined, action); |
||||
expect(state.keymaps).to.have.deep.all.members([ |
||||
{ key: [{ key: 'z', shiftKey: false, ctrlKey: false, altKey: false, metaKey: false }, |
||||
{ key: 'z', shiftKey: false, ctrlKey: false, altKey: false, metaKey: false }], |
||||
op: { type: 'zoom.neutral' }}, |
||||
{ key: [{ key: 'Esc', shiftKey: true, ctrlKey: false, altKey: false, metaKey: false }], |
||||
op: { type: 'addon.toggle.enabled' }}, |
||||
]); |
||||
}); |
||||
}); |
@ -0,0 +1,30 @@ |
||||
import { SettingRepositoryImpl } from '../../../src/content/repositories/SettingRepository'; |
||||
import { expect } from 'chai'; |
||||
|
||||
describe('SettingRepositoryImpl', () => { |
||||
it('updates and gets current value', () => { |
||||
let sut = new SettingRepositoryImpl(); |
||||
|
||||
let settings = { |
||||
keymaps: {}, |
||||
search: { |
||||
default: 'google', |
||||
engines: { |
||||
google: 'https://google.com/?q={}', |
||||
} |
||||
}, |
||||
properties: { |
||||
hintchars: 'abcd1234', |
||||
smoothscroll: false, |
||||
complete: 'sbh', |
||||
}, |
||||
blacklist: [], |
||||
} |
||||
|
||||
sut.set(settings); |
||||
|
||||
let actual = sut.get(); |
||||
expect(actual.properties.hintchars).to.equal('abcd1234'); |
||||
}); |
||||
}); |
||||
|
@ -0,0 +1,71 @@ |
||||
import SettingRepository from '../../../src/content/repositories/SettingRepository'; |
||||
import SettingClient from '../../../src/content/client/SettingClient'; |
||||
import SettingUseCase from '../../../src/content/usecases/SettingUseCase'; |
||||
import Settings, { DefaultSetting } from '../../../src/shared/Settings'; |
||||
import { expect } from 'chai'; |
||||
|
||||
class MockSettingRepository implements SettingRepository { |
||||
private current: Settings; |
||||
|
||||
constructor() { |
||||
this.current = DefaultSetting; |
||||
} |
||||
|
||||
set(settings: Settings): void { |
||||
this.current= settings; |
||||
} |
||||
|
||||
get(): Settings { |
||||
return this.current; |
||||
} |
||||
} |
||||
|
||||
class MockSettingClient implements SettingClient { |
||||
private data: Settings; |
||||
|
||||
constructor(data: Settings) { |
||||
this.data = data; |
||||
} |
||||
|
||||
load(): Promise<Settings> { |
||||
return Promise.resolve(this.data); |
||||
} |
||||
} |
||||
|
||||
describe('AddonEnabledUseCase', () => { |
||||
let repository: MockSettingRepository; |
||||
let client: MockSettingClient; |
||||
let sut: SettingUseCase; |
||||
|
||||
beforeEach(() => { |
||||
let testSettings = { |
||||
keymaps: {}, |
||||
search: { |
||||
default: 'google', |
||||
engines: { |
||||
google: 'https://google.com/?q={}', |
||||
} |
||||
}, |
||||
properties: { |
||||
hintchars: 'abcd1234', |
||||
smoothscroll: false, |
||||
complete: 'sbh', |
||||
}, |
||||
blacklist: [], |
||||
}; |
||||
|
||||
repository = new MockSettingRepository(); |
||||
client = new MockSettingClient(testSettings); |
||||
sut = new SettingUseCase({ repository, client }); |
||||
}); |
||||
|
||||
describe('#reload', () => { |
||||
it('loads settings and store to repository', async() => { |
||||
let settings = await sut.reload(); |
||||
expect(settings.properties.hintchars).to.equal('abcd1234'); |
||||
|
||||
let saved = repository.get(); |
||||
expect(saved.properties.hintchars).to.equal('abcd1234'); |
||||
}); |
||||
}); |
||||
}); |
Reference in new issue