aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--manifest.json3
-rw-r--r--src/background/Application.ts32
-rw-r--r--src/background/di.ts6
-rw-r--r--src/background/infrastructures/FindPortListener.ts23
-rw-r--r--src/background/operators/impls/FindNextOperator.ts93
-rw-r--r--src/background/operators/impls/FindOperatorFactoryChain.ts10
-rw-r--r--src/background/operators/impls/FindPrevOperator.ts94
-rw-r--r--src/background/presenters/FramePresenter.ts12
-rw-r--r--src/background/repositories/FindRepository.ts3
-rw-r--r--src/background/repositories/ReadyFrameRepository.ts70
-rw-r--r--src/background/usecases/StartFindUseCase.ts23
-rw-r--r--src/content/Application.ts16
-rw-r--r--test/background/mock/MockReadyFrameRepository.ts15
-rw-r--r--test/background/operators/impls/FindNextOperator.test.ts30
-rw-r--r--test/background/operators/impls/FindPrevOperator.test.ts30
-rw-r--r--test/background/repositories/FindRepository.test.ts4
-rw-r--r--test/background/repositories/ReadyFrameRepository.test.ts33
-rw-r--r--test/background/usecases/StartFindUseCase.test.ts16
18 files changed, 338 insertions, 175 deletions
diff --git a/manifest.json b/manifest.json
index e3a021d..ea9730c 100644
--- a/manifest.json
+++ b/manifest.json
@@ -34,8 +34,7 @@
"clipboardRead",
"notifications",
"bookmarks",
- "browserSettings",
- "webNavigation"
+ "browserSettings"
],
"web_accessible_resources": [
"build/console.html",
diff --git a/src/background/Application.ts b/src/background/Application.ts
index 2006965..b439d19 100644
--- a/src/background/Application.ts
+++ b/src/background/Application.ts
@@ -1,9 +1,11 @@
import { injectable, inject } from "tsyringe";
import ContentMessageListener from "./infrastructures/ContentMessageListener";
+import FindPortListener from "./infrastructures/FindPortListener";
import SettingController from "./controllers/SettingController";
import VersionController from "./controllers/VersionController";
import SettingRepository from "./repositories/SettingRepository";
import FindRepositoryImpl from "./repositories/FindRepository";
+import ReadyFrameRepository from "./repositories/ReadyFrameRepository";
@injectable()
export default class Application {
@@ -14,9 +16,16 @@ export default class Application {
@inject("SyncSettingRepository")
private syncSettingRepository: SettingRepository,
@inject("FindRepository")
- private readonly findRepository: FindRepositoryImpl
+ private readonly findRepository: FindRepositoryImpl,
+ @inject("ReadyFrameRepository")
+ private readonly frameRepository: ReadyFrameRepository
) {}
+ private readonly findPortListener = new FindPortListener(
+ this.onFindPortConnect.bind(this),
+ this.onFindPortDisconnect.bind(this)
+ );
+
run() {
this.settingController.reload();
@@ -36,5 +45,26 @@ export default class Application {
this.syncSettingRepository.onChange(() => {
this.settingController.reload();
});
+ this.findPortListener.run();
+ }
+
+ private onFindPortConnect(port: browser.runtime.Port) {
+ const tabId = port.sender?.tab?.id;
+ const frameId = port.sender?.frameId;
+ if (typeof tabId === "undefined" || typeof frameId === "undefined") {
+ return;
+ }
+
+ this.frameRepository.addFrameId(tabId, frameId);
+ }
+
+ private onFindPortDisconnect(port: browser.runtime.Port) {
+ const tabId = port.sender?.tab?.id;
+ const frameId = port.sender?.frameId;
+ if (typeof tabId === "undefined" || typeof frameId === "undefined") {
+ return;
+ }
+
+ this.frameRepository.removeFrameId(tabId, frameId);
}
}
diff --git a/src/background/di.ts b/src/background/di.ts
index e97c4a8..495de7c 100644
--- a/src/background/di.ts
+++ b/src/background/di.ts
@@ -18,10 +18,10 @@ import { BrowserSettingRepositoryImpl } from "./repositories/BrowserSettingRepos
import { RepeatRepositoryImpl } from "./repositories/RepeatRepository";
import { ZoomPresenterImpl } from "./presenters/ZoomPresenter";
import { WindowPresenterImpl } from "./presenters/WindowPresenter";
-import { FramePresenterImpl } from "./presenters/FramePresenter";
import { FindClientImpl } from "./clients/FindClient";
import { ConsoleFrameClientImpl } from "./clients/ConsoleFrameClient";
import { FindRepositoryImpl } from "./repositories/FindRepository";
+import { ReadyFrameRepositoryImpl } from "./repositories/ReadyFrameRepository";
container.register("LocalSettingRepository", {
useClass: LocalSettingRepository,
@@ -43,10 +43,12 @@ container.register("TabRepository", { useClass: TabRepositoryImpl });
container.register("ZoomPresenter", { useClass: ZoomPresenterImpl });
container.register("TabPresenter", { useClass: TabPresenterImpl });
container.register("WindowPresenter", { useClass: WindowPresenterImpl });
-container.register("FramePresenter", { useClass: FramePresenterImpl });
container.register("FindRepository", { useClass: FindRepositoryImpl });
container.register("FindClient", { useClass: FindClientImpl });
container.register("NavigateClient", { useClass: NavigateClientImpl });
container.register("ConsoleClient", { useClass: ConsoleClientImpl });
container.register("ConsoleFrameClient", { useClass: ConsoleFrameClientImpl });
container.register("OperatorFactory", { useClass: OperatorFactoryImpl });
+container.register("ReadyFrameRepository", {
+ useClass: ReadyFrameRepositoryImpl,
+});
diff --git a/src/background/infrastructures/FindPortListener.ts b/src/background/infrastructures/FindPortListener.ts
new file mode 100644
index 0000000..ca82439
--- /dev/null
+++ b/src/background/infrastructures/FindPortListener.ts
@@ -0,0 +1,23 @@
+import { injectable } from "tsyringe";
+
+type OnConnectFunc = (port: browser.runtime.Port) => void;
+type OnDisconnectFunc = (port: browser.runtime.Port) => void;
+
+@injectable()
+export default class FindPortListener {
+ constructor(
+ private readonly onConnect: OnConnectFunc,
+ private readonly onDisconnect: OnDisconnectFunc
+ ) {}
+
+ run(): void {
+ browser.runtime.onConnect.addListener((port) => {
+ if (port.name !== "vimvixen-find") {
+ return;
+ }
+
+ port.onDisconnect.addListener(this.onDisconnect);
+ this.onConnect(port);
+ });
+ }
+}
diff --git a/src/background/operators/impls/FindNextOperator.ts b/src/background/operators/impls/FindNextOperator.ts
index 241f71d..99f1759 100644
--- a/src/background/operators/impls/FindNextOperator.ts
+++ b/src/background/operators/impls/FindNextOperator.ts
@@ -3,7 +3,7 @@ import TabPresenter from "../../presenters/TabPresenter";
import FindRepository from "../../repositories/FindRepository";
import FindClient from "../../clients/FindClient";
import ConsoleClient from "../../infrastructures/ConsoleClient";
-import FramePresenter from "../../presenters/FramePresenter";
+import ReadyFrameRepository from "../../repositories/ReadyFrameRepository";
export default class FindNextOperator implements Operator {
constructor(
@@ -11,7 +11,7 @@ export default class FindNextOperator implements Operator {
private readonly findRepository: FindRepository,
private readonly findClient: FindClient,
private readonly consoleClient: ConsoleClient,
- private readonly framePresenter: FramePresenter
+ private readonly frameRepository: ReadyFrameRepository
) {}
async run(): Promise<void> {
@@ -21,67 +21,64 @@ export default class FindNextOperator implements Operator {
return;
}
+ const frameIds = await this.frameRepository.getFrameIds(tabId);
+ if (typeof frameIds === "undefined") {
+ // No frames are ready
+ return;
+ }
+
const state = await this.findRepository.getLocalState(tabId);
if (state) {
- // Start to find the keyword from the current frame which last found on,
- // and concat it to end of frame ids to perform a wrap-search
- //
- // ,- keyword should be in this frame
- // |
- // [100, 101, 0, 100]
- // |
- // `- continue from frame id 100
- //
- const targetFrameIds = state.frameIds
- .slice(state.framePos)
- .concat(
- state.frameIds.slice(0, state.framePos),
- state.frameIds[state.framePos]
- );
+ const framePos = frameIds.indexOf(state.frameId);
+ if (framePos !== -1) {
+ // Start to find the keyword from the current frame which last found on,
+ // and concat it to end of frame ids to perform a wrap-search
+ //
+ // ,- keyword should be in this frame
+ // |
+ // [100, 101, 0, 100]
+ // |
+ // `- continue from frame id 100
+ //
+ const targetFrameIds = frameIds
+ .slice(framePos)
+ .concat(frameIds.slice(0, framePos), frameIds[framePos]);
- for (let i = 0; i < targetFrameIds.length; ++i) {
- const found = await this.findClient.findNext(
+ for (const frameId of targetFrameIds) {
+ const found = await this.findClient.findNext(
+ tabId,
+ frameId,
+ state.keyword
+ );
+ if (found) {
+ this.findRepository.setLocalState(tabId, {
+ keyword: state.keyword,
+ frameId,
+ });
+ return;
+ }
+ this.findClient.clearSelection(tabId, frameId);
+ }
+
+ // The keyword is gone.
+ this.consoleClient.showError(
tabId,
- targetFrameIds[i],
- state.keyword
+ "Pattern not found: " + state.keyword
);
- if (found) {
- this.findRepository.setLocalState(tabId, {
- ...state,
- framePos: (i + state.framePos) % state.frameIds.length, // save current frame position or first
- });
- return;
- }
- this.findClient.clearSelection(tabId, targetFrameIds[i]);
+ return;
}
-
- // The keyword is gone.
- this.consoleClient.showError(
- tabId,
- "Pattern not found: " + state.keyword
- );
- return;
}
const keyword = await this.findRepository.getGlobalKeyword();
if (keyword) {
- const frameIds = await this.framePresenter.getAllFrameIds(tabId);
for (const frameId of frameIds) {
await this.findClient.clearSelection(tabId, frameId);
}
- for (let framePos = 0; framePos < frameIds.length; ++framePos) {
- const found = await this.findClient.findNext(
- tabId,
- frameIds[framePos],
- keyword
- );
+ for (const frameId of frameIds) {
+ const found = await this.findClient.findNext(tabId, frameId, keyword);
if (found) {
- await this.findRepository.setLocalState(tabId, {
- frameIds,
- framePos,
- keyword,
- });
+ await this.findRepository.setLocalState(tabId, { frameId, keyword });
await this.consoleClient.showInfo(tabId, "Pattern found: " + keyword);
return;
}
diff --git a/src/background/operators/impls/FindOperatorFactoryChain.ts b/src/background/operators/impls/FindOperatorFactoryChain.ts
index b71f032..cc169dd 100644
--- a/src/background/operators/impls/FindOperatorFactoryChain.ts
+++ b/src/background/operators/impls/FindOperatorFactoryChain.ts
@@ -7,8 +7,8 @@ import FindNextOperator from "./FindNextOperator";
import FindPrevOperator from "./FindPrevOperator";
import FindRepository from "../../repositories/FindRepository";
import FindClient from "../../clients/FindClient";
-import FramePresenter from "../../presenters/FramePresenter";
import ConsoleClient from "../../infrastructures/ConsoleClient";
+import ReadyFrameRepository from "../../repositories/ReadyFrameRepository";
@injectable()
export default class FindOperatorFactoryChain implements OperatorFactoryChain {
@@ -21,8 +21,8 @@ export default class FindOperatorFactoryChain implements OperatorFactoryChain {
private readonly findClient: FindClient,
@inject("ConsoleClient")
private readonly consoleClient: ConsoleClient,
- @inject("FramePresenter")
- private readonly framePresenter: FramePresenter
+ @inject("ReadyFrameRepository")
+ private readonly frameRepository: ReadyFrameRepository
) {}
create(op: operations.Operation): Operator | null {
@@ -33,7 +33,7 @@ export default class FindOperatorFactoryChain implements OperatorFactoryChain {
this.findRepository,
this.findClient,
this.consoleClient,
- this.framePresenter
+ this.frameRepository
);
case operations.FIND_PREV:
return new FindPrevOperator(
@@ -41,7 +41,7 @@ export default class FindOperatorFactoryChain implements OperatorFactoryChain {
this.findRepository,
this.findClient,
this.consoleClient,
- this.framePresenter
+ this.frameRepository
);
}
return null;
diff --git a/src/background/operators/impls/FindPrevOperator.ts b/src/background/operators/impls/FindPrevOperator.ts
index 822c386..f8506b9 100644
--- a/src/background/operators/impls/FindPrevOperator.ts
+++ b/src/background/operators/impls/FindPrevOperator.ts
@@ -3,7 +3,7 @@ import TabPresenter from "../../presenters/TabPresenter";
import FindRepository from "../../repositories/FindRepository";
import FindClient from "../../clients/FindClient";
import ConsoleClient from "../../infrastructures/ConsoleClient";
-import FramePresenter from "../../presenters/FramePresenter";
+import ReadyFrameRepository from "../../repositories/ReadyFrameRepository";
export default class FindPrevOperator implements Operator {
constructor(
@@ -11,7 +11,7 @@ export default class FindPrevOperator implements Operator {
private readonly findRepository: FindRepository,
private readonly findClient: FindClient,
private readonly consoleClient: ConsoleClient,
- private readonly framePresenter: FramePresenter
+ private readonly frameRepository: ReadyFrameRepository
) {}
async run(): Promise<void> {
@@ -21,67 +21,65 @@ export default class FindPrevOperator implements Operator {
return;
}
+ let frameIds = await this.frameRepository.getFrameIds(tabId);
+ if (typeof frameIds === "undefined") {
+ // No frames are ready
+ return;
+ }
+ frameIds = frameIds.slice(0).reverse();
+
const state = await this.findRepository.getLocalState(tabId);
if (state) {
- // Start to find the keyword from the current frame which last found on,
- // and concat it to end of frame ids to perform a wrap-search
- //
- // ,- keyword should be in this frame
- // |
- // [100, 101, 0, 100]
- // |
- // `- continue from frame id 100
- //
- const targetFrameIds = state.frameIds
- .slice(state.framePos)
- .concat(
- state.frameIds.slice(0, state.framePos),
- state.frameIds[state.framePos]
- );
+ const framePos = frameIds.indexOf(state.frameId);
+ if (framePos !== -1) {
+ // Start to find the keyword from the current frame which last found on,
+ // and concat it to end of frame ids to perform a wrap-search
+ //
+ // ,- keyword should be in this frame
+ // |
+ // [100, 101, 0, 100]
+ // |
+ // `- continue from frame id 100
+ //
+ const targetFrameIds = frameIds
+ .slice(framePos)
+ .concat(frameIds.slice(0, framePos), frameIds[framePos]);
- for (let i = targetFrameIds.length - 1; i >= 0; --i) {
- const found = await this.findClient.findPrev(
+ for (const frameId of targetFrameIds) {
+ const found = await this.findClient.findPrev(
+ tabId,
+ frameId,
+ state.keyword
+ );
+ if (found) {
+ this.findRepository.setLocalState(tabId, {
+ keyword: state.keyword,
+ frameId,
+ });
+ return;
+ }
+ this.findClient.clearSelection(tabId, frameId);
+ }
+
+ // The keyword is gone.
+ this.consoleClient.showError(
tabId,
- targetFrameIds[i],
- state.keyword
+ "Pattern not found: " + state.keyword
);
- if (found) {
- this.findRepository.setLocalState(tabId, {
- ...state,
- framePos: (i + state.framePos) % state.frameIds.length, // save current frame position or first
- });
- return;
- }
- this.findClient.clearSelection(tabId, targetFrameIds[i]);
+ return;
}
-
- // The keyword is gone.
- this.consoleClient.showError(
- tabId,
- "Pattern not found: " + state.keyword
- );
- return;
}
const keyword = await this.findRepository.getGlobalKeyword();
if (keyword) {
- const frameIds = await this.framePresenter.getAllFrameIds(tabId);
for (const frameId of frameIds) {
await this.findClient.clearSelection(tabId, frameId);
}
- for (let framePos = frameIds.length - 1; framePos >= 0; --framePos) {
- const found = await this.findClient.findPrev(
- tabId,
- frameIds[framePos],
- keyword
- );
+ for (const frameId of frameIds) {
+ const found = await this.findClient.findPrev(tabId, frameId, keyword);
if (found) {
- await this.findRepository.setLocalState(tabId, {
- frameIds,
- framePos,
- keyword,
- });
+ await this.findRepository.setLocalState(tabId, { frameId, keyword });
await this.consoleClient.showInfo(tabId, "Pattern found: " + keyword);
return;
}
diff --git a/src/background/presenters/FramePresenter.ts b/src/background/presenters/FramePresenter.ts
deleted file mode 100644
index c94f8dd..0000000
--- a/src/background/presenters/FramePresenter.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export default interface FramePresenter {
- getAllFrameIds(tabId: number): Promise<Array<number>>;
-}
-
-export class FramePresenterImpl implements FramePresenter {
- async getAllFrameIds(tabId: number): Promise<Array<number>> {
- const frames = await browser.webNavigation.getAllFrames({ tabId: tabId });
- return frames
- .filter((f) => !f.url.startsWith("moz-extension://"))
- .map((f) => f.frameId);
- }
-}
diff --git a/src/background/repositories/FindRepository.ts b/src/background/repositories/FindRepository.ts
index 46ee390..3492759 100644
--- a/src/background/repositories/FindRepository.ts
+++ b/src/background/repositories/FindRepository.ts
@@ -6,8 +6,7 @@ const FIND_LOCAL_KEYWORD_KEY = "find-local-keyword";
export type FindState = {
keyword: string;
- framePos: number;
- frameIds: number[];
+ frameId: number;
};
export default interface FindRepository {
diff --git a/src/background/repositories/ReadyFrameRepository.ts b/src/background/repositories/ReadyFrameRepository.ts
new file mode 100644
index 0000000..c993858
--- /dev/null
+++ b/src/background/repositories/ReadyFrameRepository.ts
@@ -0,0 +1,70 @@
+import MemoryStorage from "../infrastructures/MemoryStorage";
+
+const REPOSITORY_KEY = "readyFrameRepository";
+
+type State = { [tabId: number]: { [frameId: number]: number } };
+
+export default interface ReadyFrameRepository {
+ addFrameId(tabId: number, frameId: number): Promise<void>;
+
+ removeFrameId(tabId: number, frameId: number): Promise<void>;
+
+ getFrameIds(tabId: number): Promise<number[] | undefined>;
+}
+
+export class ReadyFrameRepositoryImpl implements ReadyFrameRepository {
+ private cache: MemoryStorage;
+
+ constructor() {
+ this.cache = new MemoryStorage();
+ }
+
+ addFrameId(tabId: number, frameId: number): Promise<void> {
+ let state: State | undefined = this.cache.get(REPOSITORY_KEY);
+ if (typeof state === "undefined") {
+ state = {};
+ }
+ const tab = state[tabId] || {};
+ tab[frameId] = (tab[frameId] || 0) + 1;
+ state[tabId] = tab;
+ this.cache.set(REPOSITORY_KEY, state);
+ return Promise.resolve();
+ }
+
+ removeFrameId(tabId: number, frameId: number): Promise<void> {
+ const state: State | undefined = this.cache.get(REPOSITORY_KEY);
+ if (typeof state === "undefined") {
+ return Promise.resolve();
+ }
+ const ids = state[tabId];
+ if (typeof ids === "undefined") {
+ return Promise.resolve();
+ }
+ const tab = state[tabId] || {};
+ tab[frameId] = (tab[frameId] || 0) - 1;
+ if (tab[frameId] == 0) {
+ delete tab[frameId];
+ }
+ if (Object.keys(tab).length === 0) {
+ delete state[tabId];
+ }
+
+ this.cache.set(REPOSITORY_KEY, state);
+ return Promise.resolve();
+ }
+
+ getFrameIds(tabId: number): Promise<number[] | undefined> {
+ const state: State | undefined = this.cache.get(REPOSITORY_KEY);
+ if (typeof state === "undefined") {
+ return Promise.resolve(undefined);
+ }
+ const tab = state[tabId];
+ if (typeof tab === "undefined") {
+ return Promise.resolve(undefined);
+ }
+ const frameIds = Object.keys(tab)
+ .map((v) => Number(v))
+ .sort();
+ return Promise.resolve(frameIds);
+ }
+}
diff --git a/src/background/usecases/StartFindUseCase.ts b/src/background/usecases/StartFindUseCase.ts
index 066d930..6aad962 100644
--- a/src/background/usecases/StartFindUseCase.ts
+++ b/src/background/usecases/StartFindUseCase.ts
@@ -2,7 +2,7 @@ import { inject, injectable } from "tsyringe";
import ConsoleClient from "../infrastructures/ConsoleClient";
import FindRepositoryImpl from "../repositories/FindRepository";
import FindClient from "../clients/FindClient";
-import FramePresenter from "../presenters/FramePresenter";
+import ReadyFrameRepository from "../repositories/ReadyFrameRepository";
@injectable()
export default class StartFindUseCase {
@@ -13,8 +13,8 @@ export default class StartFindUseCase {
private readonly findRepository: FindRepositoryImpl,
@inject("ConsoleClient")
private readonly consoleClient: ConsoleClient,
- @inject("FramePresenter")
- private readonly framePresenter: FramePresenter
+ @inject("ReadyFrameRepository")
+ private readonly frameRepository: ReadyFrameRepository
) {}
async startFind(tabId: number, keyword?: string): Promise<void> {
@@ -31,21 +31,20 @@ export default class StartFindUseCase {
this.findRepository.setGlobalKeyword(keyword);
- const frameIds = await this.framePresenter.getAllFrameIds(tabId);
+ const frameIds = await this.frameRepository.getFrameIds(tabId);
+ if (typeof frameIds === "undefined") {
+ // No frames are ready
+ return;
+ }
for (const frameId of frameIds) {
await this.findClient.clearSelection(tabId, frameId);
}
- for (let framePos = 0; framePos < frameIds.length; ++framePos) {
- const found = await this.findClient.findNext(
- tabId,
- frameIds[framePos],
- keyword
- );
+ for (const frameId of frameIds) {
+ const found = await this.findClient.findNext(tabId, frameId, keyword);
if (found) {
await this.findRepository.setLocalState(tabId, {
- frameIds,
- framePos,
+ frameId,
keyword,
});
await this.consoleClient.showInfo(tabId, "Pattern found: " + keyword);
diff --git a/src/content/Application.ts b/src/content/Application.ts
index a12c3c6..6b881fe 100644
--- a/src/content/Application.ts
+++ b/src/content/Application.ts
@@ -41,7 +41,21 @@ export default class Application {
if (window.self === window.top) {
this.routeMasterComponents();
}
- return this.routeCommonComponents();
+ this.routeCommonComponents();
+ // Make sure the background script sends a message to the content script by
+ // establishing a connection. If the background script tries to send a
+ // message to a frame on which cannot run the content script, it fails with
+ // a message "Could not establish connection."
+ //
+ // The port is never used, and the messages are delivered via
+ // `browser.tabs.sendMessage` API because sending a message via port cannot
+ // receive returned value.
+ //
+ // /* on background script */
+ // port.sendMessage({ type: "do something" }); <- returns void
+ //
+ browser.runtime.connect(undefined, { name: "vimvixen-find" });
+ return Promise.resolve();
}
private routeMasterComponents() {
diff --git a/test/background/mock/MockReadyFrameRepository.ts b/test/background/mock/MockReadyFrameRepository.ts
new file mode 100644
index 0000000..4a5ec52
--- /dev/null
+++ b/test/background/mock/MockReadyFrameRepository.ts
@@ -0,0 +1,15 @@
+import ReadyFrameRepository from "../../../src/background/repositories/ReadyFrameRepository";
+
+export default class MockReadyFrameRepository implements ReadyFrameRepository {
+ addFrameId(_tabId: number, _fraemId: number): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ removeFrameId(_tabId: number, _frameId: number): Promise<void> {
+ throw new Error("not implemented");
+ }
+
+ getFrameIds(_tabId: number): Promise<number[] | undefined> {
+ throw new Error("not implemented");
+ }
+}
diff --git a/test/background/operators/impls/FindNextOperator.test.ts b/test/background/operators/impls/FindNextOperator.test.ts
index 0bee3f5..7509ef4 100644
--- a/test/background/operators/impls/FindNextOperator.test.ts
+++ b/test/background/operators/impls/FindNextOperator.test.ts
@@ -4,7 +4,7 @@ import FindNextOperator from "../../../../src/background/operators/impls/FindNex
import MockFindRepository from "../../mock/MockFindRepository";
import MockFindClient from "../../mock/MockFindClient";
import MockConsoleClient from "../../mock/MockConsoleClient";
-import MockFramePresenter from "../../mock/MockFramePresenter";
+import MockReadyFrameRepository from "../../mock/MockReadyFrameRepository";
describe("FindNextOperator", () => {
const keyword = "hello";
@@ -14,13 +14,13 @@ describe("FindNextOperator", () => {
const findRepository = new MockFindRepository();
const findClient = new MockFindClient();
const consoleClient = new MockConsoleClient();
- const framePresenter = new MockFramePresenter();
+ const frameRepository = new MockReadyFrameRepository();
const sut = new FindNextOperator(
tabPresenter,
findRepository,
findClient,
consoleClient,
- framePresenter
+ frameRepository
);
let currentTabId: number;
@@ -32,6 +32,10 @@ describe("FindNextOperator", () => {
active: true,
});
currentTabId = currentTab.id!;
+
+ sinon
+ .stub(frameRepository, "getFrameIds")
+ .returns(Promise.resolve(frameIds));
});
describe("#run", () => {
@@ -54,8 +58,7 @@ describe("FindNextOperator", () => {
sinon.stub(findRepository, "getLocalState").returns(
Promise.resolve({
keyword,
- frameIds,
- framePos: 1,
+ frameId: 100,
})
);
@@ -68,7 +71,7 @@ describe("FindNextOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 1 });
+ .withArgs(currentTabId, { keyword, frameId: 100 });
await sut.run();
@@ -80,8 +83,7 @@ describe("FindNextOperator", () => {
sinon.stub(findRepository, "getLocalState").returns(
Promise.resolve({
keyword,
- frameIds,
- framePos: 1,
+ frameId: 100,
})
);
@@ -102,7 +104,7 @@ describe("FindNextOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 2 });
+ .withArgs(currentTabId, { keyword, frameId: 101 });
await sut.run();
@@ -114,8 +116,7 @@ describe("FindNextOperator", () => {
sinon.stub(findRepository, "getLocalState").returns(
Promise.resolve({
keyword,
- frameIds,
- framePos: 2,
+ frameId: 101,
})
);
@@ -136,7 +137,7 @@ describe("FindNextOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 0 });
+ .withArgs(currentTabId, { keyword, frameId: 0 });
await sut.run();
@@ -151,9 +152,6 @@ describe("FindNextOperator", () => {
sinon
.stub(findRepository, "getGlobalKeyword")
.returns(Promise.resolve(keyword));
- sinon
- .stub(framePresenter, "getAllFrameIds")
- .returns(Promise.resolve(frameIds));
sinon.stub(consoleClient, "showInfo").returns(Promise.resolve());
const mockFindClient = sinon.mock(findClient);
@@ -168,7 +166,7 @@ describe("FindNextOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 0 });
+ .withArgs(currentTabId, { keyword, frameId: 0 });
await sut.run();
diff --git a/test/background/operators/impls/FindPrevOperator.test.ts b/test/background/operators/impls/FindPrevOperator.test.ts
index ebac0dc..090f815 100644
--- a/test/background/operators/impls/FindPrevOperator.test.ts
+++ b/test/background/operators/impls/FindPrevOperator.test.ts
@@ -4,7 +4,7 @@ import FindPrevOperator from "../../../../src/background/operators/impls/FindPre
import MockFindRepository from "../../mock/MockFindRepository";
import MockFindClient from "../../mock/MockFindClient";
import MockConsoleClient from "../../mock/MockConsoleClient";
-import MockFramePresenter from "../../mock/MockFramePresenter";
+import MockReadyFrameRepository from "../../mock/MockReadyFrameRepository";
describe("FindPrevOperator", () => {
const keyword = "hello";
@@ -14,13 +14,13 @@ describe("FindPrevOperator", () => {
const findRepository = new MockFindRepository();
const findClient = new MockFindClient();
const consoleClient = new MockConsoleClient();
- const framePresenter = new MockFramePresenter();
+ const frameRepository = new MockReadyFrameRepository();
const sut = new FindPrevOperator(
tabPresenter,
findRepository,
findClient,
consoleClient,
- framePresenter
+ frameRepository
);
let currentTabId: number;
@@ -32,6 +32,10 @@ describe("FindPrevOperator", () => {
active: true,
});
currentTabId = currentTab.id!;
+
+ sinon
+ .stub(frameRepository, "getFrameIds")
+ .returns(Promise.resolve(frameIds.slice(0)));
});
describe("#run", () => {
@@ -54,8 +58,7 @@ describe("FindPrevOperator", () => {
sinon.stub(findRepository, "getLocalState").returns(
Promise.resolve({
keyword,
- frameIds,
- framePos: 1,
+ frameId: 100,
})
);
@@ -68,7 +71,7 @@ describe("FindPrevOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 1 });
+ .withArgs(currentTabId, { keyword, frameId: 100 });
await sut.run();
@@ -80,8 +83,7 @@ describe("FindPrevOperator", () => {
sinon.stub(findRepository, "getLocalState").returns(
Promise.resolve({
keyword,
- frameIds,
- framePos: 1,
+ frameId: 100,
})
);
@@ -102,7 +104,7 @@ describe("FindPrevOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 0 });
+ .withArgs(currentTabId, { keyword, frameId: 0 });
await sut.run();
@@ -114,8 +116,7 @@ describe("FindPrevOperator", () => {
sinon.stub(findRepository, "getLocalState").returns(
Promise.resolve({
keyword,
- frameIds,
- framePos: 0,
+ frameId: 0,
})
);
@@ -136,7 +137,7 @@ describe("FindPrevOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 2 });
+ .withArgs(currentTabId, { keyword, frameId: 101 });
await sut.run();
@@ -151,9 +152,6 @@ describe("FindPrevOperator", () => {
sinon
.stub(findRepository, "getGlobalKeyword")
.returns(Promise.resolve(keyword));
- sinon
- .stub(framePresenter, "getAllFrameIds")
- .returns(Promise.resolve(frameIds));
sinon.stub(consoleClient, "showInfo").returns(Promise.resolve());
const mockFindClient = sinon.mock(findClient);
@@ -168,7 +166,7 @@ describe("FindPrevOperator", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { keyword, frameIds, framePos: 2 });
+ .withArgs(currentTabId, { keyword, frameId: 101 });
await sut.run();
diff --git a/test/background/repositories/FindRepository.test.ts b/test/background/repositories/FindRepository.test.ts
index a08dc6d..d8c9506 100644
--- a/test/background/repositories/FindRepository.test.ts
+++ b/test/background/repositories/FindRepository.test.ts
@@ -25,12 +25,12 @@ describe("background/repositories/FindRepositoryImpl", () => {
await sut.setLocalState(10, {
keyword: "Hello, world",
- frameIds: [20, 21],
- framePos: 0,
+ frameId: 11,
});
const state = await sut.getLocalState(10);
expect(state?.keyword).to.equal("Hello, world");
+ expect(state?.frameId).to.equal(11);
expect(await sut.getLocalState(20)).to.be.undefined;
});
diff --git a/test/background/repositories/ReadyFrameRepository.test.ts b/test/background/repositories/ReadyFrameRepository.test.ts
new file mode 100644
index 0000000..71f20af
--- /dev/null
+++ b/test/background/repositories/ReadyFrameRepository.test.ts
@@ -0,0 +1,33 @@
+import { expect } from "chai";
+import { ReadyFrameRepositoryImpl } from "../../../src/background/repositories/ReadyFrameRepository";
+
+describe("background/repositories/ReadyFrameRepositoryImpl", () => {
+ let sut: ReadyFrameRepositoryImpl;
+
+ beforeEach(() => {
+ sut = new ReadyFrameRepositoryImpl();
+ });
+
+ it("get and set a keyword", async () => {
+ expect(await sut.getFrameIds(1)).to.be.undefined;
+
+ await sut.addFrameId(1, 10);
+ await sut.addFrameId(1, 12);
+ await sut.addFrameId(1, 11);
+ await sut.addFrameId(2, 20);
+ await sut.addFrameId(2, 21);
+ await sut.addFrameId(2, 21);
+
+ expect(await sut.getFrameIds(1)).to.deep.equal([10, 11, 12]);
+ expect(await sut.getFrameIds(2)).to.deep.equal([20, 21]);
+
+ await sut.removeFrameId(2, 21);
+ expect(await sut.getFrameIds(2)).to.deep.equal([20, 21]);
+
+ await sut.removeFrameId(2, 21);
+ expect(await sut.getFrameIds(2)).to.deep.equal([20]);
+
+ await sut.removeFrameId(2, 20);
+ expect(await sut.getFrameIds(2)).to.be.undefined;
+ });
+});
diff --git a/test/background/usecases/StartFindUseCase.test.ts b/test/background/usecases/StartFindUseCase.test.ts
index 22ff9a5..24e1fdc 100644
--- a/test/background/usecases/StartFindUseCase.test.ts
+++ b/test/background/usecases/StartFindUseCase.test.ts
@@ -2,7 +2,7 @@ import * as sinon from "sinon";
import MockFindClient from "../mock/MockFindClient";
import MockFindRepository from "../mock/MockFindRepository";
import MockConsoleClient from "../mock/MockConsoleClient";
-import MockFramePresenter from "../mock/MockFramePresenter";
+import MockReadyFrameRepository from "../mock/MockReadyFrameRepository";
import StartFindUseCase from "../../../src/background/usecases/StartFindUseCase";
describe("StartFindUseCase", () => {
@@ -13,19 +13,19 @@ describe("StartFindUseCase", () => {
const findClient = new MockFindClient();
const findRepository = new MockFindRepository();
const consoleClient = new MockConsoleClient();
- const framePresenter = new MockFramePresenter();
+ const frameRepository = new MockReadyFrameRepository();
const sut = new StartFindUseCase(
findClient,
findRepository,
consoleClient,
- framePresenter
+ frameRepository
);
beforeEach(async () => {
sinon.restore();
sinon
- .stub(framePresenter, "getAllFrameIds")
+ .stub(frameRepository, "getFrameIds")
.returns(Promise.resolve(frameIds));
});
@@ -46,7 +46,7 @@ describe("StartFindUseCase", () => {
const mockFindRepository = sinon.mock(findRepository);
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { frameIds, framePos: 1, keyword });
+ .withArgs(currentTabId, { keyword, frameId: 100 });
const mockConsoleClient = sinon.mock(consoleClient);
mockConsoleClient
.expects("showInfo")
@@ -76,10 +76,10 @@ describe("StartFindUseCase", () => {
mockFindRepository
.expects("getLocalState")
.withArgs(currentTabId)
- .returns(Promise.resolve({ keyword, frameIds, framePos: 0 }));
+ .returns(Promise.resolve({ keyword, frameId: 0 }));
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { frameIds, framePos: 1, keyword });
+ .withArgs(currentTabId, { keyword, frameId: 100 });
const mockConsoleClient = sinon.mock(consoleClient);
mockConsoleClient
.expects("showInfo")
@@ -115,7 +115,7 @@ describe("StartFindUseCase", () => {
.returns(Promise.resolve(keyword));
mockFindRepository
.expects("setLocalState")
- .withArgs(currentTabId, { frameIds, framePos: 1, keyword });
+ .withArgs(currentTabId, { keyword, frameId: 100 });
const mockConsoleClient = sinon.mock(consoleClient);
mockConsoleClient
.expects("showInfo")