aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2021-03-22 20:44:07 +0900
committerGitHub <noreply@github.com>2021-03-22 20:44:07 +0900
commitfa733c1ff110054f673f3d4e8d4760eb90d5d1eb (patch)
tree0a7d9f041a01d29f0bc5972a343e4988dc71b468
parent3cbaf4a9f4245bd6be4eccdbff11e20ffaaf523a (diff)
parent690c9c080a2a511a30d555a90e5005e06b750351 (diff)
Merge pull request #1043 from ueokande/iframe-late-inject
iframe Late injection
-rw-r--r--e2e/lib/Page.ts47
-rw-r--r--manifest.json2
-rw-r--r--src/console/index.tsx2
-rw-r--r--src/content/Application.ts8
-rw-r--r--src/content/Bootstrap.ts27
-rw-r--r--src/content/index.ts33
-rw-r--r--src/content/operators/impls/AddonOperatorFactoryChain.ts14
-rw-r--r--src/content/operators/impls/DisableAddonOperator.ts5
-rw-r--r--src/content/operators/impls/EnableAddonOperator.ts5
-rw-r--r--src/content/operators/impls/ToggleAddonOperator.ts15
-rw-r--r--src/content/presenters/ConsoleFramePresenter.ts31
-rw-r--r--src/content/usecases/AddonEnabledUseCase.ts16
-rw-r--r--test/content/operators/impls/AddonOperatorFactoryChain.test.ts4
-rw-r--r--test/content/operators/impls/DisableAddonOperator.test.ts5
-rw-r--r--test/content/operators/impls/EnableAddonOperator.test.ts5
-rw-r--r--test/content/operators/impls/MockConsoleFramePresenter.ts26
-rw-r--r--test/content/operators/impls/ToggleAddonOperator.test.ts6
-rw-r--r--test/content/usecases/AddonEnabledUseCase.test.ts11
18 files changed, 207 insertions, 55 deletions
diff --git a/e2e/lib/Page.ts b/e2e/lib/Page.ts
index 6531f19..13bf70f 100644
--- a/e2e/lib/Page.ts
+++ b/e2e/lib/Page.ts
@@ -15,13 +15,13 @@ export default class Page {
private constructor(private webdriver: WebDriver) {}
static async currentContext(webdriver: WebDriver): Promise<Page> {
- await Page.waitForConsoleLoaded(webdriver);
+ await Page.waitForPageCompleted(webdriver);
return new Page(webdriver);
}
static async navigateTo(webdriver: WebDriver, url: string): Promise<Page> {
await webdriver.navigate().to(url);
- await Page.waitForConsoleLoaded(webdriver);
+ await Page.waitForPageCompleted(webdriver);
return new Page(webdriver);
}
@@ -34,18 +34,19 @@ export default class Page {
async navigateTo(url: string): Promise<Page> {
await this.webdriver.navigate().to(url);
- await Page.waitForConsoleLoaded(this.webdriver);
+ await Page.waitForPageCompleted(this.webdriver);
+
+ await new Promise((resolve) => setTimeout(resolve, 200));
+
return new Page(this.webdriver);
}
async showConsole(): Promise<Console> {
- const iframe = this.webdriver.findElement(
- By.css("#vimvixen-console-frame")
- );
-
await this.sendKeys(":");
+ const iframe = this.webdriver.findElement(By.id("vimvixen-console-frame"));
await this.webdriver.wait(until.elementIsVisible(iframe));
- await this.webdriver.switchTo().frame(0);
+
+ await this.webdriver.switchTo().frame(iframe);
await this.webdriver.wait(until.elementLocated(By.css("input")));
return new Console(this.webdriver);
}
@@ -54,9 +55,8 @@ export default class Page {
const iframe = this.webdriver.findElement(
By.css("#vimvixen-console-frame")
);
-
await this.webdriver.wait(until.elementIsVisible(iframe));
- await this.webdriver.switchTo().frame(0);
+ await this.webdriver.switchTo().frame(iframe);
return new Console(this.webdriver);
}
@@ -113,14 +113,35 @@ export default class Page {
return hints;
}
- private static async waitForConsoleLoaded(webdriver: WebDriver) {
+ private static async waitForPageCompleted(
+ webdriver: WebDriver
+ ): Promise<void> {
+ this.waitForDocumentCompleted(webdriver);
+
const topFrame = await webdriver.executeScript(() => window.top === window);
if (!topFrame) {
return;
}
+ // style tag is injected at end of add-on loading
+ await webdriver.wait(until.elementLocated(By.tagName("style")));
+
+ const iframe = await webdriver.findElements(
+ By.id("vimvixen-console-frame")
+ );
+ if (iframe.length === 0) {
+ return;
+ }
+
+ await webdriver.switchTo().frame(iframe[0]);
+ await Page.waitForDocumentCompleted(webdriver);
+ await webdriver.switchTo().parentFrame();
+ }
+
+ private static async waitForDocumentCompleted(webdriver: WebDriver) {
await webdriver.wait(
- until.elementLocated(By.css("iframe.vimvixen-console-frame"))
+ async () =>
+ (await webdriver.executeScript("return document.readyState")) ===
+ "complete"
);
- await new Promise((resolve) => setTimeout(resolve, 100));
}
}
diff --git a/manifest.json b/manifest.json
index 569d17b..4d3aebc 100644
--- a/manifest.json
+++ b/manifest.json
@@ -17,7 +17,7 @@
"all_frames": true,
"matches": [ "<all_urls>" ],
"js": [ "build/content.js" ],
- "run_at": "document_end",
+ "run_at": "document_start",
"match_about_blank": true
}
],
diff --git a/src/console/index.tsx b/src/console/index.tsx
index 228625e..f9313a0 100644
--- a/src/console/index.tsx
+++ b/src/console/index.tsx
@@ -11,7 +11,7 @@ import ReactDOM from "react-dom";
const store = createStore(reducers, applyMiddleware(promise));
-window.addEventListener("load", () => {
+window.addEventListener("DOMContentLoaded", () => {
const wrapper = document.getElementById("vimvixen-console");
ReactDOM.render(
<Provider store={store}>
diff --git a/src/content/Application.ts b/src/content/Application.ts
index 7c8e588..b09edfa 100644
--- a/src/content/Application.ts
+++ b/src/content/Application.ts
@@ -36,12 +36,12 @@ export default class Application {
private navigateController: NavigateController
) {}
- run() {
- this.routeCommonComponents();
+ init(): Promise<void> {
this.routeFocusEvents();
if (window.self === window.top) {
this.routeMasterComponents();
}
+ return this.routeCommonComponents();
}
private routeMasterComponents() {
@@ -76,7 +76,7 @@ export default class Application {
});
}
- private routeCommonComponents() {
+ private routeCommonComponents(): Promise<void> {
this.messageListener.onWebMessage((msg: Message) => {
switch (msg.type) {
case messages.FOLLOW_REQUEST_COUNT_TARGETS:
@@ -117,7 +117,7 @@ export default class Application {
inputDriver.onKey((key) => this.markKeyController.press(key));
inputDriver.onKey((key) => this.keymapController.press(key));
- this.settingController.initSettings();
+ return this.settingController.initSettings();
}
private routeFocusEvents() {
diff --git a/src/content/Bootstrap.ts b/src/content/Bootstrap.ts
new file mode 100644
index 0000000..62e1530
--- /dev/null
+++ b/src/content/Bootstrap.ts
@@ -0,0 +1,27 @@
+type Callback = () => void;
+
+export default class Bootstrap {
+ constructor() {}
+
+ isReady(): boolean {
+ return document.body !== null;
+ }
+
+ waitForReady(callback: Callback): void {
+ const observer = new MutationObserver(() => {
+ if (document.body != null) {
+ observer.disconnect();
+ callback();
+ }
+ });
+
+ observer.observe(document, {
+ attributes: false,
+ attributeOldValue: false,
+ characterData: false,
+ characterDataOldValue: false,
+ childList: true,
+ subtree: true,
+ });
+ }
+}
diff --git a/src/content/index.ts b/src/content/index.ts
index b575e0d..82f3a4c 100644
--- a/src/content/index.ts
+++ b/src/content/index.ts
@@ -1,22 +1,29 @@
import "reflect-metadata";
import Application from "./Application";
+import Bootstrap from "./Bootstrap";
import consoleFrameStyle from "./site-style";
-import { ConsoleFramePresenterImpl } from "./presenters/ConsoleFramePresenter";
import { container } from "tsyringe";
import "./di";
-if (window.self === window.top) {
- new ConsoleFramePresenterImpl().initialize();
-}
+const initDom = () => {
+ (async () => {
+ try {
+ const app = container.resolve(Application);
+ await app.init();
+ } catch (e) {
+ console.error(e);
+ }
+ })();
-try {
- const app = container.resolve(Application);
- app.run();
-} catch (e) {
- console.error(e);
-}
+ const style = window.document.createElement("style");
+ style.textContent = consoleFrameStyle;
+ window.document.head.appendChild(style);
+};
-const style = window.document.createElement("style");
-style.textContent = consoleFrameStyle;
-window.document.head.appendChild(style);
+const bootstrap = new Bootstrap();
+if (bootstrap.isReady()) {
+ initDom();
+} else {
+ bootstrap.waitForReady(() => initDom());
+}
diff --git a/src/content/operators/impls/AddonOperatorFactoryChain.ts b/src/content/operators/impls/AddonOperatorFactoryChain.ts
index 54880c4..5e464e8 100644
--- a/src/content/operators/impls/AddonOperatorFactoryChain.ts
+++ b/src/content/operators/impls/AddonOperatorFactoryChain.ts
@@ -7,6 +7,7 @@ import Operator from "../Operator";
import EnableAddonOperator from "./EnableAddonOperator";
import DisableAddonOperator from "./DisableAddonOperator";
import ToggleAddonOperator from "./ToggleAddonOperator";
+import ConsoleFramePresenter from "../../presenters/ConsoleFramePresenter";
@injectable()
export default class AddonOperatorFactoryChain implements OperatorFactoryChain {
@@ -14,7 +15,9 @@ export default class AddonOperatorFactoryChain implements OperatorFactoryChain {
@inject("AddonIndicatorClient")
private readonly addonIndicatorClient: AddonIndicatorClient,
@inject("AddonEnabledRepository")
- private readonly addonEnabledRepository: AddonEnabledRepository
+ private readonly addonEnabledRepository: AddonEnabledRepository,
+ @inject("ConsoleFramePresenter")
+ private readonly consoleFramePresenter: ConsoleFramePresenter
) {}
create(op: operations.Operation, _repeat: number): Operator | null {
@@ -22,17 +25,20 @@ export default class AddonOperatorFactoryChain implements OperatorFactoryChain {
case operations.ADDON_ENABLE:
return new EnableAddonOperator(
this.addonIndicatorClient,
- this.addonEnabledRepository
+ this.addonEnabledRepository,
+ this.consoleFramePresenter
);
case operations.ADDON_DISABLE:
return new DisableAddonOperator(
this.addonIndicatorClient,
- this.addonEnabledRepository
+ this.addonEnabledRepository,
+ this.consoleFramePresenter
);
case operations.ADDON_TOGGLE_ENABLED:
return new ToggleAddonOperator(
this.addonIndicatorClient,
- this.addonEnabledRepository
+ this.addonEnabledRepository,
+ this.consoleFramePresenter
);
}
return null;
diff --git a/src/content/operators/impls/DisableAddonOperator.ts b/src/content/operators/impls/DisableAddonOperator.ts
index 28811fe..a92e04b 100644
--- a/src/content/operators/impls/DisableAddonOperator.ts
+++ b/src/content/operators/impls/DisableAddonOperator.ts
@@ -1,15 +1,18 @@
import Operator from "../Operator";
import AddonIndicatorClient from "../../client/AddonIndicatorClient";
import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+import ConsoleFramePresenter from "../../presenters/ConsoleFramePresenter";
export default class DisableAddonOperator implements Operator {
constructor(
private readonly indicator: AddonIndicatorClient,
- private readonly repository: AddonEnabledRepository
+ private readonly repository: AddonEnabledRepository,
+ private readonly consoleFramePresenter: ConsoleFramePresenter
) {}
async run(): Promise<void> {
this.repository.set(false);
+ this.consoleFramePresenter.detach();
await this.indicator.setEnabled(false);
}
}
diff --git a/src/content/operators/impls/EnableAddonOperator.ts b/src/content/operators/impls/EnableAddonOperator.ts
index b5b1d79..fe2b771 100644
--- a/src/content/operators/impls/EnableAddonOperator.ts
+++ b/src/content/operators/impls/EnableAddonOperator.ts
@@ -1,15 +1,18 @@
import Operator from "../Operator";
import AddonIndicatorClient from "../../client/AddonIndicatorClient";
import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+import ConsoleFramePresenter from "../../presenters/ConsoleFramePresenter";
export default class EnableAddonOperator implements Operator {
constructor(
private readonly indicator: AddonIndicatorClient,
- private readonly repository: AddonEnabledRepository
+ private readonly repository: AddonEnabledRepository,
+ private readonly consoleFramePresenter: ConsoleFramePresenter
) {}
async run(): Promise<void> {
this.repository.set(true);
+ this.consoleFramePresenter.attach();
await this.indicator.setEnabled(true);
}
}
diff --git a/src/content/operators/impls/ToggleAddonOperator.ts b/src/content/operators/impls/ToggleAddonOperator.ts
index 2a249d6..1019b8b 100644
--- a/src/content/operators/impls/ToggleAddonOperator.ts
+++ b/src/content/operators/impls/ToggleAddonOperator.ts
@@ -1,16 +1,23 @@
import Operator from "../Operator";
import AddonIndicatorClient from "../../client/AddonIndicatorClient";
import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+import ConsoleFramePresenter from "../../presenters/ConsoleFramePresenter";
export default class ToggleAddonOperator implements Operator {
constructor(
private readonly indicator: AddonIndicatorClient,
- private readonly repository: AddonEnabledRepository
+ private readonly repository: AddonEnabledRepository,
+ private readonly consoleFramePresenter: ConsoleFramePresenter
) {}
async run(): Promise<void> {
- const current = this.repository.get();
- this.repository.set(!current);
- await this.indicator.setEnabled(!current);
+ const enabled = !this.repository.get();
+ this.repository.set(enabled);
+ if (enabled) {
+ this.consoleFramePresenter.attach();
+ } else {
+ this.consoleFramePresenter.detach();
+ }
+ await this.indicator.setEnabled(enabled);
}
}
diff --git a/src/content/presenters/ConsoleFramePresenter.ts b/src/content/presenters/ConsoleFramePresenter.ts
index ccc196b..0db58f0 100644
--- a/src/content/presenters/ConsoleFramePresenter.ts
+++ b/src/content/presenters/ConsoleFramePresenter.ts
@@ -1,24 +1,43 @@
export default interface ConsoleFramePresenter {
- initialize(): void;
+ attach(): void;
+
+ detach(): void;
blur(): void;
resize(width: number, height: number): void;
+
+ isTopWindow(): boolean;
}
export class ConsoleFramePresenterImpl implements ConsoleFramePresenter {
- initialize(): void {
+ private static readonly IframeId = "vimvixen-console-frame" as const;
+
+ attach(): void {
+ const ele = document.getElementById("vimvixen-console-frame");
+ if (ele) {
+ return;
+ }
+
const iframe = document.createElement("iframe");
iframe.src = browser.runtime.getURL("build/console.html");
- iframe.id = "vimvixen-console-frame";
+ iframe.id = ConsoleFramePresenterImpl.IframeId;
iframe.className = "vimvixen-console-frame";
document.body.append(iframe);
}
+ detach(): void {
+ const ele = document.getElementById(ConsoleFramePresenterImpl.IframeId);
+ if (!ele) {
+ return;
+ }
+ ele.remove();
+ }
+
blur(): void {
const ele = document.getElementById("vimvixen-console-frame");
if (!ele) {
- throw new Error("console frame not created");
+ return;
}
ele.blur();
}
@@ -30,4 +49,8 @@ export class ConsoleFramePresenterImpl implements ConsoleFramePresenter {
}
ele.style.height = `${height}px`;
}
+
+ isTopWindow(): boolean {
+ return window.top === window;
+ }
}
diff --git a/src/content/usecases/AddonEnabledUseCase.ts b/src/content/usecases/AddonEnabledUseCase.ts
index f7e78c5..f49fde5 100644
--- a/src/content/usecases/AddonEnabledUseCase.ts
+++ b/src/content/usecases/AddonEnabledUseCase.ts
@@ -1,15 +1,17 @@
import { injectable, inject } from "tsyringe";
import AddonIndicatorClient from "../client/AddonIndicatorClient";
import AddonEnabledRepository from "../repositories/AddonEnabledRepository";
+import ConsoleFramePresenter from "../presenters/ConsoleFramePresenter";
@injectable()
export default class AddonEnabledUseCase {
constructor(
@inject("AddonIndicatorClient")
- private indicator: AddonIndicatorClient,
-
+ private readonly indicator: AddonIndicatorClient,
@inject("AddonEnabledRepository")
- private repository: AddonEnabledRepository
+ private readonly repository: AddonEnabledRepository,
+ @inject("ConsoleFramePresenter")
+ private readonly consoleFramePresenter: ConsoleFramePresenter
) {}
async enable(): Promise<void> {
@@ -31,6 +33,14 @@ export default class AddonEnabledUseCase {
private async setEnabled(on: boolean): Promise<void> {
this.repository.set(on);
+
+ if (this.consoleFramePresenter.isTopWindow()) {
+ if (on) {
+ this.consoleFramePresenter.attach();
+ } else {
+ this.consoleFramePresenter.detach();
+ }
+ }
await this.indicator.setEnabled(on);
}
}
diff --git a/test/content/operators/impls/AddonOperatorFactoryChain.test.ts b/test/content/operators/impls/AddonOperatorFactoryChain.test.ts
index c064bb9..dde5a35 100644
--- a/test/content/operators/impls/AddonOperatorFactoryChain.test.ts
+++ b/test/content/operators/impls/AddonOperatorFactoryChain.test.ts
@@ -6,13 +6,15 @@ import * as operations from "../../../../src/shared/operations";
import { expect } from "chai";
import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+import MockConsoleFramePresenter from "./MockConsoleFramePresenter";
describe("AddonOperatorFactoryChain", () => {
describe("#create", () => {
it("returns an operator", () => {
const sut = new AddonOperatorFactoryChain(
new MockAddonIndicatorClient(),
- new MockAddonEnabledRepository()
+ new MockAddonEnabledRepository(),
+ new MockConsoleFramePresenter(false)
);
expect(sut.create({ type: operations.ADDON_ENABLE }, 0)).to.be.instanceOf(
EnableAddonOperator
diff --git a/test/content/operators/impls/DisableAddonOperator.test.ts b/test/content/operators/impls/DisableAddonOperator.test.ts
index 358ae44..e05d1f1 100644
--- a/test/content/operators/impls/DisableAddonOperator.test.ts
+++ b/test/content/operators/impls/DisableAddonOperator.test.ts
@@ -2,18 +2,21 @@ import { expect } from "chai";
import DisableAddonOperator from "../../../../src/content/operators/impls/DisableAddonOperator";
import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+import MockConsoleFramePresenter from "./MockConsoleFramePresenter";
describe("DisableAddonOperator", () => {
describe("#run", () => {
it("disables addon", async () => {
const client = new MockAddonIndicatorClient(true);
const repository = new MockAddonEnabledRepository(true);
- const sut = new DisableAddonOperator(client, repository);
+ const presenter = new MockConsoleFramePresenter(true);
+ const sut = new DisableAddonOperator(client, repository, presenter);
await sut.run();
expect(client.enabled).to.be.false;
expect(repository.enabled).to.be.false;
+ expect(presenter.attached).to.be.false;
});
});
});
diff --git a/test/content/operators/impls/EnableAddonOperator.test.ts b/test/content/operators/impls/EnableAddonOperator.test.ts
index a6ca31b..6025608 100644
--- a/test/content/operators/impls/EnableAddonOperator.test.ts
+++ b/test/content/operators/impls/EnableAddonOperator.test.ts
@@ -2,18 +2,21 @@ import { expect } from "chai";
import EnableAddonOperator from "../../../../src/content/operators/impls/EnableAddonOperator";
import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+import MockConsoleFramePresenter from "./MockConsoleFramePresenter";
describe("EnableAddonOperator", () => {
describe("#run", () => {
it("enabled addon", async () => {
const client = new MockAddonIndicatorClient(false);
const repository = new MockAddonEnabledRepository(false);
- const sut = new EnableAddonOperator(client, repository);
+ const presenter = new MockConsoleFramePresenter(false);
+ const sut = new EnableAddonOperator(client, repository, presenter);
await sut.run();
expect(client.enabled).to.be.true;
expect(repository.enabled).to.be.true;
+ expect(presenter.attached).to.be.true;
});
});
});
diff --git a/test/content/operators/impls/MockConsoleFramePresenter.ts b/test/content/operators/impls/MockConsoleFramePresenter.ts
new file mode 100644
index 0000000..23bc27f
--- /dev/null
+++ b/test/content/operators/impls/MockConsoleFramePresenter.ts
@@ -0,0 +1,26 @@
+import ConsoleFramePresenter from "../../../../src/content/presenters/ConsoleFramePresenter";
+
+export default class MockConsoleFramePresenter
+ implements ConsoleFramePresenter {
+ constructor(public attached: boolean) {}
+
+ attach(): void {
+ this.attached = true;
+ }
+
+ detach(): void {
+ this.attached = false;
+ }
+
+ blur(): void {
+ throw new Error("not implemented");
+ }
+
+ resize(_width: number, _height: number): void {
+ throw new Error("not implemented");
+ }
+
+ isTopWindow(): boolean {
+ return true;
+ }
+}
diff --git a/test/content/operators/impls/ToggleAddonOperator.test.ts b/test/content/operators/impls/ToggleAddonOperator.test.ts
index 6026eb1..1f291b5 100644
--- a/test/content/operators/impls/ToggleAddonOperator.test.ts
+++ b/test/content/operators/impls/ToggleAddonOperator.test.ts
@@ -2,23 +2,27 @@ import { expect } from "chai";
import ToggleAddonOperator from "../../../../src/content/operators/impls/ToggleAddonOperator";
import MockAddonIndicatorClient from "../../mock/MockAddonIndicatorClient";
import MockAddonEnabledRepository from "../../mock/MockAddonEnabledRepository";
+import MockConsoleFramePresenter from "./MockConsoleFramePresenter";
describe("ToggleAddonOperator", () => {
describe("#run", () => {
it("toggles addon-enabled state", async () => {
const client = new MockAddonIndicatorClient(true);
const repository = new MockAddonEnabledRepository(true);
- const sut = new ToggleAddonOperator(client, repository);
+ const presenter = new MockConsoleFramePresenter(true);
+ const sut = new ToggleAddonOperator(client, repository, presenter);
await sut.run();
expect(client.enabled).to.be.false;
expect(repository.enabled).to.be.false;
+ expect(presenter.attached).to.be.false;
await sut.run();
expect(client.enabled).to.be.true;
expect(repository.enabled).to.be.true;
+ expect(presenter.attached).to.be.true;
});
});
});
diff --git a/test/content/usecases/AddonEnabledUseCase.test.ts b/test/content/usecases/AddonEnabledUseCase.test.ts
index 885da83..8a614c5 100644
--- a/test/content/usecases/AddonEnabledUseCase.test.ts
+++ b/test/content/usecases/AddonEnabledUseCase.test.ts
@@ -2,6 +2,7 @@ import AddonEnabledRepository from "../../../src/content/repositories/AddonEnabl
import AddonEnabledUseCase from "../../../src/content/usecases/AddonEnabledUseCase";
import AddonIndicatorClient from "../../../src/content/client/AddonIndicatorClient";
import { expect } from "chai";
+import MockConsoleFramePresenter from "../operators/impls/MockConsoleFramePresenter";
class MockAddonEnabledRepository implements AddonEnabledRepository {
private enabled: boolean;
@@ -35,12 +36,14 @@ class MockAddonIndicatorClient implements AddonIndicatorClient {
describe("AddonEnabledUseCase", () => {
let repository: MockAddonEnabledRepository;
let indicator: MockAddonIndicatorClient;
+ let presenter: MockConsoleFramePresenter;
let sut: AddonEnabledUseCase;
beforeEach(() => {
- repository = new MockAddonEnabledRepository(true);
+ repository = new MockAddonEnabledRepository(false);
indicator = new MockAddonIndicatorClient(false);
- sut = new AddonEnabledUseCase(indicator, repository);
+ presenter = new MockConsoleFramePresenter(false);
+ sut = new AddonEnabledUseCase(indicator, repository, presenter);
});
describe("#enable", () => {
@@ -49,6 +52,7 @@ describe("AddonEnabledUseCase", () => {
expect(repository.get()).to.be.true;
expect(indicator.enabled).to.be.true;
+ expect(presenter.attached).to.be.true;
});
});
@@ -58,6 +62,7 @@ describe("AddonEnabledUseCase", () => {
expect(repository.get()).to.be.false;
expect(indicator.enabled).to.be.false;
+ expect(presenter.attached).to.be.false;
});
});
@@ -68,6 +73,7 @@ describe("AddonEnabledUseCase", () => {
expect(repository.get()).to.be.false;
expect(indicator.enabled).to.be.false;
+ expect(presenter.attached).to.be.false;
repository.set(false);
@@ -75,6 +81,7 @@ describe("AddonEnabledUseCase", () => {
expect(repository.get()).to.be.true;
expect(indicator.enabled).to.be.true;
+ expect(presenter.attached).to.be.true;
});
});