Make Settings class

jh-changes
Shin'ya UEOKA 5 years ago
parent b86b4680b6
commit 0dec6c641f
  1. 2
      src/background/controllers/SettingController.ts
  2. 3
      src/background/infrastructures/ContentMessageListener.ts
  3. 7
      src/background/repositories/SettingRepository.ts
  4. 2
      src/background/usecases/SettingUseCase.ts
  5. 4
      src/content/client/SettingClient.ts
  6. 2
      src/content/repositories/SettingRepository.ts
  7. 2
      src/content/usecases/SettingUseCase.ts
  8. 6
      src/shared/SettingData.ts
  9. 85
      src/shared/settings/Settings.ts
  10. 13
      test/content/repositories/SettingRepository.test.ts
  11. 2
      test/content/usecases/SettingUseCaase.test.ts
  12. 39
      test/shared/SettingData.test.ts
  13. 10
      test/shared/settings/Settings.test.ts

@ -1,7 +1,7 @@
import { injectable } from 'tsyringe'; import { injectable } from 'tsyringe';
import SettingUseCase from '../usecases/SettingUseCase'; import SettingUseCase from '../usecases/SettingUseCase';
import ContentMessageClient from '../infrastructures/ContentMessageClient'; import ContentMessageClient from '../infrastructures/ContentMessageClient';
import Settings from '../../shared/Settings'; import Settings from '../../shared/settings/Settings';
@injectable() @injectable()
export default class SettingController { export default class SettingController {

@ -8,7 +8,6 @@ import AddonEnabledController from '../controllers/AddonEnabledController';
import LinkController from '../controllers/LinkController'; import LinkController from '../controllers/LinkController';
import OperationController from '../controllers/OperationController'; import OperationController from '../controllers/OperationController';
import MarkController from '../controllers/MarkController'; import MarkController from '../controllers/MarkController';
import { toJSON } from '../../shared/Settings';
@injectable() @injectable()
export default class ContentMessageListener { export default class ContentMessageListener {
@ -103,7 +102,7 @@ export default class ContentMessageListener {
} }
async onSettingsQuery(): Promise<any> { async onSettingsQuery(): Promise<any> {
return toJSON(await this.settingController.getSetting()); return (await this.settingController.getSetting()).toJSON();
} }
onFindGetKeyword(): Promise<string> { onFindGetKeyword(): Promise<string> {

@ -1,6 +1,6 @@
import { injectable } from 'tsyringe'; import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage'; import MemoryStorage from '../infrastructures/MemoryStorage';
import Settings, { valueOf, toJSON } from '../../shared/Settings'; import Settings from '../../shared/settings/Settings';
import Properties from '../../shared/settings/Properties'; import Properties from '../../shared/settings/Properties';
const CACHED_SETTING_KEY = 'setting'; const CACHED_SETTING_KEY = 'setting';
@ -15,12 +15,11 @@ export default class SettingRepository {
get(): Promise<Settings> { get(): Promise<Settings> {
let data = this.cache.get(CACHED_SETTING_KEY); let data = this.cache.get(CACHED_SETTING_KEY);
return Promise.resolve(valueOf(data)); return Promise.resolve(Settings.fromJSON(data));
} }
update(value: Settings): void { update(value: Settings): void {
let data = toJSON(value); return this.cache.set(CACHED_SETTING_KEY, value.toJSON());
return this.cache.set(CACHED_SETTING_KEY, data);
} }
async setProperty( async setProperty(

@ -3,7 +3,7 @@ import PersistentSettingRepository
from '../repositories/PersistentSettingRepository'; from '../repositories/PersistentSettingRepository';
import SettingRepository from '../repositories/SettingRepository'; import SettingRepository from '../repositories/SettingRepository';
import { DefaultSettingData } from '../../shared/SettingData'; import { DefaultSettingData } from '../../shared/SettingData';
import Settings from '../../shared/Settings'; import Settings from '../../shared/settings/Settings';
import NotifyPresenter from '../presenters/NotifyPresenter'; import NotifyPresenter from '../presenters/NotifyPresenter';
@injectable() @injectable()

@ -1,4 +1,4 @@
import Settings, { valueOf } from '../../shared/Settings'; import Settings from '../../shared/settings/Settings';
import * as messages from '../../shared/messages'; import * as messages from '../../shared/messages';
export default interface SettingClient { export default interface SettingClient {
@ -10,6 +10,6 @@ export class SettingClientImpl {
let settings = await browser.runtime.sendMessage({ let settings = await browser.runtime.sendMessage({
type: messages.SETTINGS_QUERY, type: messages.SETTINGS_QUERY,
}); });
return valueOf(settings); return Settings.fromJSON(settings);
} }
} }

@ -1,4 +1,4 @@
import Settings, { DefaultSetting } from '../../shared/Settings'; import Settings, { DefaultSetting } from '../../shared/settings/Settings';
let current: Settings = DefaultSetting; let current: Settings = DefaultSetting;

@ -1,7 +1,7 @@
import { injectable, inject } from 'tsyringe'; import { injectable, inject } from 'tsyringe';
import SettingRepository from '../repositories/SettingRepository'; import SettingRepository from '../repositories/SettingRepository';
import SettingClient from '../client/SettingClient'; import SettingClient from '../client/SettingClient';
import Settings from '../../shared/Settings'; import Settings from '../../shared/settings/Settings';
@injectable() @injectable()
export default class SettingUseCase { export default class SettingUseCase {

@ -1,5 +1,5 @@
import * as operations from './operations'; import * as operations from './operations';
import Settings, * as settings from './Settings'; import Settings from './settings/Settings';
import Keymaps from './settings/Keymaps'; import Keymaps from './settings/Keymaps';
import Search from './settings/Search'; import Search from './settings/Search';
import Properties from './settings/Properties'; import Properties from './settings/Properties';
@ -118,7 +118,7 @@ export class JSONTextSettings {
} }
toSettings(): Settings { toSettings(): Settings {
return settings.valueOf(JSON.parse(this.json)); return Settings.fromJSON(JSON.parse(this.json));
} }
toJSONText(): string { toJSONText(): string {
@ -198,7 +198,7 @@ export class FormSettings {
} }
toSettings(): Settings { toSettings(): Settings {
return settings.valueOf({ return Settings.fromJSON({
keymaps: this.keymaps.toKeymaps().toJSON(), keymaps: this.keymaps.toKeymaps().toJSON(),
search: this.search.toSearchSettings().toJSON(), search: this.search.toSearchSettings().toJSON(),
properties: this.properties.toJSON(), properties: this.properties.toJSON(),

@ -1,49 +1,76 @@
import Keymaps from './settings/Keymaps'; import Keymaps, { KeymapsJSON } from './Keymaps';
import Search from './settings/Search'; import Search, { SearchJSON } from './Search';
import Properties from './settings/Properties'; import Properties, { PropertiesJSON } from './Properties';
import Blacklist from './settings/Blacklist'; import Blacklist, { BlacklistJSON } from './Blacklist';
export default interface Settings { export type SettingsJSON = {
keymaps: KeymapsJSON,
search: SearchJSON,
properties: PropertiesJSON,
blacklist: BlacklistJSON,
};
export default class Settings {
public keymaps: Keymaps;
public search: Search;
public properties: Properties;
public blacklist: Blacklist;
constructor({
keymaps,
search,
properties,
blacklist,
}: {
keymaps: Keymaps; keymaps: Keymaps;
search: Search; search: Search;
properties: Properties; properties: Properties;
blacklist: Blacklist; blacklist: Blacklist;
} }) {
this.keymaps = keymaps;
this.search = search;
this.properties = properties;
this.blacklist = blacklist;
}
export const valueOf = (o: any): Settings => { static fromJSON(json: any): Settings {
let settings = { ...DefaultSetting }; let settings = { ...DefaultSetting };
for (let key of Object.keys(o)) { for (let key of Object.keys(json)) {
switch (key) { switch (key) {
case 'keymaps': case 'keymaps':
settings.keymaps = Keymaps.fromJSON(o.keymaps); settings.keymaps = Keymaps.fromJSON(json.keymaps);
break; break;
case 'search': case 'search':
settings.search = Search.fromJSON(o.search); settings.search = Search.fromJSON(json.search);
break; break;
case 'properties': case 'properties':
settings.properties = Properties.fromJSON(o.properties); settings.properties = Properties.fromJSON(json.properties);
break; break;
case 'blacklist': case 'blacklist':
settings.blacklist = Blacklist.fromJSON(o.blacklist); settings.blacklist = Blacklist.fromJSON(json.blacklist);
break; break;
default: default:
throw new TypeError('unknown setting: ' + key); throw new TypeError('unknown setting: ' + key);
} }
} }
return settings; return new Settings(settings);
}; }
export const toJSON = (settings: Settings): any => { toJSON(): SettingsJSON {
return { return {
keymaps: settings.keymaps.toJSON(), keymaps: this.keymaps.toJSON(),
search: settings.search.toJSON(), search: this.search.toJSON(),
properties: settings.properties.toJSON(), properties: this.properties.toJSON(),
blacklist: settings.blacklist.toJSON(), blacklist: this.blacklist.toJSON(),
}; };
}; }
}
export const DefaultSetting: Settings = { export const DefaultSetting: Settings = Settings.fromJSON({
keymaps: Keymaps.fromJSON({ keymaps: {
'0': { 'type': 'scroll.home' }, '0': { 'type': 'scroll.home' },
':': { 'type': 'command.show' }, ':': { 'type': 'command.show' },
'o': { 'type': 'command.show.open', 'alter': false }, 'o': { 'type': 'command.show.open', 'alter': false },
@ -106,8 +133,8 @@ export const DefaultSetting: Settings = {
'N': { 'type': 'find.prev' }, 'N': { 'type': 'find.prev' },
'.': { 'type': 'repeat.last' }, '.': { 'type': 'repeat.last' },
'<S-Esc>': { 'type': 'addon.toggle.enabled' } '<S-Esc>': { 'type': 'addon.toggle.enabled' }
}), },
search: Search.fromJSON({ search: {
default: 'google', default: 'google',
engines: { engines: {
'google': 'https://google.com/search?q={}', 'google': 'https://google.com/search?q={}',
@ -117,11 +144,11 @@ export const DefaultSetting: Settings = {
'twitter': 'https://twitter.com/search?q={}', 'twitter': 'https://twitter.com/search?q={}',
'wikipedia': 'https://en.wikipedia.org/w/index.php?search={}' 'wikipedia': 'https://en.wikipedia.org/w/index.php?search={}'
} }
}), },
properties: Properties.fromJSON({ properties: {
hintchars: 'abcdefghijklmnopqrstuvwxyz', hintchars: 'abcdefghijklmnopqrstuvwxyz',
smoothscroll: false, smoothscroll: false,
complete: 'sbh' complete: 'sbh'
}), },
blacklist: Blacklist.fromJSON([]), blacklist: [],
}; });

@ -1,27 +1,26 @@
import { SettingRepositoryImpl } from '../../../src/content/repositories/SettingRepository'; import { SettingRepositoryImpl } from '../../../src/content/repositories/SettingRepository';
import { expect } from 'chai'; import { expect } from 'chai';
import Keymaps from '../../../src/shared/settings/Keymaps'; import Settings from '../../../src/shared/settings/Settings';
import Search from '../../../src/shared/settings/Search';
describe('SettingRepositoryImpl', () => { describe('SettingRepositoryImpl', () => {
it('updates and gets current value', () => { it('updates and gets current value', () => {
let sut = new SettingRepositoryImpl(); let sut = new SettingRepositoryImpl();
let settings = { let settings = Settings.fromJSON({
keymaps: Keymaps.fromJSON({}), keymaps: {},
search: Search.fromJSON({ search:{
default: 'google', default: 'google',
engines: { engines: {
google: 'https://google.com/?q={}', google: 'https://google.com/?q={}',
} }
}), },
properties: { properties: {
hintchars: 'abcd1234', hintchars: 'abcd1234',
smoothscroll: false, smoothscroll: false,
complete: 'sbh', complete: 'sbh',
}, },
blacklist: [], blacklist: [],
}; });
sut.set(settings); sut.set(settings);

@ -1,7 +1,7 @@
import SettingRepository from '../../../src/content/repositories/SettingRepository'; import SettingRepository from '../../../src/content/repositories/SettingRepository';
import SettingClient from '../../../src/content/client/SettingClient'; import SettingClient from '../../../src/content/client/SettingClient';
import SettingUseCase from '../../../src/content/usecases/SettingUseCase'; import SettingUseCase from '../../../src/content/usecases/SettingUseCase';
import Settings, { DefaultSetting } from '../../../src/shared/Settings'; import Settings, { DefaultSetting } from '../../../src/shared/settings/Settings';
import { expect } from 'chai'; import { expect } from 'chai';
class MockSettingRepository implements SettingRepository { class MockSettingRepository implements SettingRepository {

@ -1,12 +1,9 @@
import SettingData, { import SettingData, {
FormKeymaps, JSONTextSettings, FormSettings, FormKeymaps, JSONTextSettings, FormSettings,
} from '../../src/shared/SettingData'; } from '../../src/shared/SettingData';
import Settings from '../../src/shared/Settings'; import Settings from '../../src/shared/settings/Settings';
import { expect } from 'chai'; import { expect } from 'chai';
import Keymaps from '../../src/shared/settings/Keymaps'; import Keymaps from '../../src/shared/settings/Keymaps';
import Search from '../../src/shared/settings/Search';
import Properties from '../../src/shared/settings/Properties';
import Blacklist from '../../src/shared/settings/Blacklist'
describe('shared/SettingData', () => { describe('shared/SettingData', () => {
describe('FormKeymaps', () => { describe('FormKeymaps', () => {
@ -72,21 +69,21 @@ describe('shared/SettingData', () => {
describe('#fromSettings to #toJSON', () => { describe('#fromSettings to #toJSON', () => {
it('create from a Settings and create a JSON string', () => { it('create from a Settings and create a JSON string', () => {
let o = { let o = Settings.fromJSON({
keymaps: Keymaps.fromJSON({}), keymaps: {},
search: Search.fromJSON({ search: {
default: "google", default: "google",
engines: { engines: {
google: "https://google.com/search?q={}", google: "https://google.com/search?q={}",
}, },
}), },
properties: Properties.fromJSON({ properties: {
hintchars: "abcdefghijklmnopqrstuvwxyz", hintchars: "abcdefghijklmnopqrstuvwxyz",
smoothscroll: false, smoothscroll: false,
complete: "sbh" complete: "sbh"
}), },
blacklist: Blacklist.fromJSON([]), blacklist: [],
}; });
let json = JSONTextSettings.fromSettings(o).toJSONText(); let json = JSONTextSettings.fromSettings(o).toJSONText();
expect(JSON.parse(json)).to.deep.equal({ expect(JSON.parse(json)).to.deep.equal({
@ -150,24 +147,24 @@ describe('shared/SettingData', () => {
describe('#fromSettings to #toJSON', () => { describe('#fromSettings to #toJSON', () => {
it('create from a Settings and create a JSON string', () => { it('create from a Settings and create a JSON string', () => {
let data: Settings = { let data: Settings = Settings.fromJSON({
keymaps: Keymaps.fromJSON({ keymaps: {
'j': { type: 'scroll.vertically', count: 1 }, 'j': { type: 'scroll.vertically', count: 1 },
'0': { type: 'scroll.home' }, '0': { type: 'scroll.home' },
}), },
search: Search.fromJSON({ search: {
default: "google", default: "google",
engines: { engines: {
"google": "https://google.com/search?q={}" "google": "https://google.com/search?q={}"
} }
}), },
properties: Properties.fromJSON({ properties: {
hintchars: "abcdefghijklmnopqrstuvwxyz", hintchars: "abcdefghijklmnopqrstuvwxyz",
smoothscroll: false, smoothscroll: false,
complete: "sbh" complete: "sbh"
}), },
blacklist: Blacklist.fromJSON([]), blacklist: [],
}; });
let json = FormSettings.fromSettings(data).toJSON(); let json = FormSettings.fromSettings(data).toJSON();
expect(json).to.deep.equal({ expect(json).to.deep.equal({

@ -1,10 +1,10 @@
import * as settings from '../../src/shared/Settings'; import Settings from '../../../src/shared/settings/Settings';
import {expect} from 'chai'; import { expect } from 'chai';
describe('Settings', () => { describe('Settings', () => {
describe('#valueOf', () => { describe('#valueOf', () => {
it('returns settings by valid settings', () => { it('returns settings by valid settings', () => {
let x = settings.valueOf({ let x = Settings.fromJSON({
keymaps: {}, keymaps: {},
"search": { "search": {
"default": "google", "default": "google",
@ -39,7 +39,7 @@ describe('Settings', () => {
}); });
it('sets default settings', () => { it('sets default settings', () => {
let value = settings.valueOf({}); let value = Settings.fromJSON({});
expect(value.keymaps.toJSON()).to.not.be.empty; expect(value.keymaps.toJSON()).to.not.be.empty;
expect(value.properties.toJSON()).to.not.be.empty; expect(value.properties.toJSON()).to.not.be.empty;
expect(value.search.defaultEngine).to.be.a('string'); expect(value.search.defaultEngine).to.be.a('string');
@ -48,7 +48,7 @@ describe('Settings', () => {
}); });
it('throws a TypeError with an unknown field', () => { it('throws a TypeError with an unknown field', () => {
expect(() => settings.valueOf({ name: 'alice' })).to.throw(TypeError) expect(() => Settings.fromJSON({ name: 'alice' })).to.throw(TypeError)
}); });
}); });
}); });