diff options
Diffstat (limited to 'test/background')
48 files changed, 1583 insertions, 183 deletions
diff --git a/test/background/mock/MockBrowserSettingRepository.ts b/test/background/mock/MockBrowserSettingRepository.ts new file mode 100644 index 0000000..22e7084 --- /dev/null +++ b/test/background/mock/MockBrowserSettingRepository.ts @@ -0,0 +1,10 @@ +import BrowserSettingRepository from "../../../src/background/repositories/BrowserSettingRepository"; + +export default class MockBrowserSettingRepository + implements BrowserSettingRepository { + constructor(private readonly homepageUrls: string[]) {} + + getHomepageUrls(): Promise<string[]> { + return Promise.resolve(this.homepageUrls); + } +} diff --git a/test/background/mock/MockConsoleClient.ts b/test/background/mock/MockConsoleClient.ts new file mode 100644 index 0000000..d1f8fc3 --- /dev/null +++ b/test/background/mock/MockConsoleClient.ts @@ -0,0 +1,23 @@ +import ConsoleClient from "../../../src/background/infrastructures/ConsoleClient"; + +export default class MockConsoleClient implements ConsoleClient { + hide(_tabId: number): Promise<any> { + throw new Error("not implemented"); + } + + showCommand(_tabId: number, _command: string): Promise<any> { + throw new Error("not implemented"); + } + + showError(_tabId: number, _message: string): Promise<any> { + throw new Error("not implemented"); + } + + showFind(_tabId: number): Promise<any> { + throw new Error("not implemented"); + } + + showInfo(_tabId: number, _message: string): Promise<any> { + throw new Error("not implemented"); + } +} diff --git a/test/background/mock/MockNavigateClient.ts b/test/background/mock/MockNavigateClient.ts new file mode 100644 index 0000000..d9442a4 --- /dev/null +++ b/test/background/mock/MockNavigateClient.ts @@ -0,0 +1,19 @@ +import NavigateClient from "../../../src/background/clients/NavigateClient"; + +export default class MockNavigateClient implements NavigateClient { + historyNext(_tabId: number): Promise<void> { + throw new Error("not implemented"); + } + + historyPrev(_tabId: number): Promise<void> { + throw new Error("not implemented"); + } + + linkNext(_tabId: number): Promise<void> { + throw new Error("not implemented"); + } + + linkPrev(_tabId: number): Promise<void> { + throw new Error("not implemented"); + } +} diff --git a/test/background/mock/MockRepeatRepository.ts b/test/background/mock/MockRepeatRepository.ts new file mode 100644 index 0000000..1a686c8 --- /dev/null +++ b/test/background/mock/MockRepeatRepository.ts @@ -0,0 +1,14 @@ +import RepeatRepository from "../../../src/background/repositories/RepeatRepository"; +import { Operation } from "../../../src/shared/operations"; + +export default class MockRepeatRepository implements RepeatRepository { + private op: Operation | undefined = undefined; + + getLastOperation(): Operation | undefined { + return this.op; + } + + setLastOperation(op: Operation): void { + this.op = op; + } +} diff --git a/test/background/mock/MockTabPresenter.ts b/test/background/mock/MockTabPresenter.ts new file mode 100644 index 0000000..22fb947 --- /dev/null +++ b/test/background/mock/MockTabPresenter.ts @@ -0,0 +1,179 @@ +import TabPresenter from "../../../src/background/presenters/TabPresenter"; + +export default class MockTabPresenter implements TabPresenter { + private readonly tabs: browser.tabs.Tab[] = []; + private readonly zooms: number[] = []; + private nextid = 0; + + private readonly lastSelectedId: number | undefined; + + private static defaultTabOptions = { + hidden: false, + highlighted: false, + incognito: false, + isArticle: false, + isInReaderMode: false, + lastAccessed: 0, + pinned: false, + selected: false, + windowId: 0, + }; + + create( + url: string, + opts?: { + active?: boolean; + cookieStoreId?: string; + index?: number; + openerTabId?: number; + pinned?: boolean; + windowId?: number; + } + ): Promise<browser.tabs.Tab> { + const tab = { + ...MockTabPresenter.defaultTabOptions, + ...opts, + id: this.nextid++, + active: false, + title: "welcome, world", + url, + index: this.tabs.length, + }; + if (opts?.active || this.tabs.length === 0) { + this.tabs.forEach((t) => (t.active = false)); + tab.active = true; + } + this.tabs.push(tab); + this.zooms.push(1); + return Promise.resolve(tab); + } + + duplicate(id: number): Promise<browser.tabs.Tab> { + const src = this.tabs.find((t) => t.id === id); + if (!src) { + throw new Error(`tab ${id} not found`); + } + this.tabs.forEach((t) => (t.active = false)); + const tab = { ...src, id: this.nextid++, active: true }; + this.tabs.push(tab); + this.zooms.push(1); + + return Promise.resolve(tab); + } + + getAll(): Promise<browser.tabs.Tab[]> { + return Promise.resolve([...this.tabs]); + } + + getByKeyword( + keyword: string, + excludePinned: boolean + ): Promise<browser.tabs.Tab[]> { + const tabs = this.tabs + + .filter((t) => { + return ( + (t.url && t.url.toLowerCase().includes(keyword.toLowerCase())) || + (t.title && t.title.toLowerCase().includes(keyword.toLowerCase())) + ); + }) + .filter((t) => { + return !(excludePinned && t.pinned); + }); + return Promise.resolve(tabs); + } + + getCurrent(): Promise<browser.tabs.Tab> { + const tab = this.tabs.find((t) => t.active); + if (!tab) { + throw new Error("active tab not found"); + } + return Promise.resolve(tab); + } + + getLastSelectedId(): Promise<number | undefined> { + return Promise.resolve(this.lastSelectedId); + } + + getZoom(tabId: number): Promise<number> { + const index = this.tabs.findIndex((t) => t.id === tabId); + if (index === -1) { + throw new Error(`tab ${tabId} not found`); + } + return Promise.resolve(this.zooms[index]); + } + + onSelected( + _listener: (arg: { tabId: number; windowId: number }) => void + ): void { + throw new Error("not implemented"); + } + + open(url: string, tabId?: number): Promise<browser.tabs.Tab> { + let tab = this.tabs.find((t) => t.active); + if (!tab) { + throw new Error(`active tab not found`); + } + if (tabId !== undefined) { + tab = this.tabs.find((t) => t.id === tabId); + } + if (!tab) { + throw new Error(`tab ${tabId} not found`); + } + tab.url = url; + return Promise.resolve(tab); + } + + reload(_tabId: number, _cache: boolean): Promise<void> { + throw new Error("not implemented"); + } + + remove(ids: number[]): Promise<void> { + for (const id of ids) { + const index = this.tabs.findIndex((t) => t.id === id); + if (index === -1) { + throw new Error(`tab ${id} not found`); + } + const tab = this.tabs[index]; + this.tabs.splice(index, 1); + this.zooms.splice(index, 1); + if (tab.active) { + this.tabs[Math.min(index, this.tabs.length - 1)].active = true; + } + } + + return Promise.resolve(undefined); + } + + reopen(): Promise<void> { + throw new Error("not implemented"); + } + + select(tabId: number): Promise<void> { + const tab = this.tabs.find((t) => t.id === tabId); + if (!tab) { + throw new Error(`tab ${tabId} not found`); + } + this.tabs.forEach((t) => (t.active = false)); + tab.active = true; + return Promise.resolve(undefined); + } + + setPinned(tabId: number, pinned: boolean): Promise<void> { + const tab = this.tabs.find((t) => t.id === tabId); + if (!tab) { + throw new Error(`tab ${tabId} not found`); + } + tab.pinned = pinned; + return Promise.resolve(); + } + + setZoom(tabId: number, factor: number): Promise<void> { + const index = this.tabs.findIndex((t) => t.id === tabId); + if (index === -1) { + throw new Error(`tab ${tabId} not found`); + } + this.zooms[index] = factor; + return Promise.resolve(); + } +} diff --git a/test/background/mock/MockWindowPresenter.ts b/test/background/mock/MockWindowPresenter.ts new file mode 100644 index 0000000..420ae8b --- /dev/null +++ b/test/background/mock/MockWindowPresenter.ts @@ -0,0 +1,7 @@ +import WindowPresenter from "../../../src/background/presenters/WindowPresenter"; + +export default class MockWindowPresenter implements WindowPresenter { + create(_url: string): Promise<void> { + throw new Error("not implemented"); + } +} diff --git a/test/background/mock/MockZoomPresenter.ts b/test/background/mock/MockZoomPresenter.ts new file mode 100644 index 0000000..53d1980 --- /dev/null +++ b/test/background/mock/MockZoomPresenter.ts @@ -0,0 +1,15 @@ +import ZoomPresenter from "../../../src/background/presenters/ZoomPresenter"; + +export default class MockZoomPresenter implements ZoomPresenter { + resetZoom(): Promise<void> { + throw new Error("not implemented"); + } + + zoomIn(): Promise<void> { + throw new Error("not implemented"); + } + + zoomOut(): Promise<void> { + throw new Error("not implemented"); + } +} diff --git a/test/background/operators/impls/CancelOperator.test.ts b/test/background/operators/impls/CancelOperator.test.ts new file mode 100644 index 0000000..915becf --- /dev/null +++ b/test/background/operators/impls/CancelOperator.test.ts @@ -0,0 +1,24 @@ +import sinon from "sinon"; +import CancelOperator from "../../../../src/background/operators/impls/CancelOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("CancelOperator", () => { + describe("#run", () => { + it("hides console", async () => { + const tabPresenter = new MockTabPresenter(); + const currenTab = await tabPresenter.create("https://example.com/"); + + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("hide") + .withArgs(currenTab?.id); + const sut = new CancelOperator(tabPresenter, consoleClient); + + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/CloseTabOperator.test.ts b/test/background/operators/impls/CloseTabOperator.test.ts new file mode 100644 index 0000000..ba9cbfe --- /dev/null +++ b/test/background/operators/impls/CloseTabOperator.test.ts @@ -0,0 +1,61 @@ +import { expect } from "chai"; +import CloseTabOperator from "../../../../src/background/operators/impls/CloseTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("CloseTabOperator", () => { + describe("#run", () => { + it("close a current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new CloseTabOperator(tabPresenter); + + await sut.run(); + + const tabs = await tabPresenter.getAll(); + expect(tabs.map((t) => t.url)).to.deep.equal([ + "https://example.com/1", + "https://example.com/3", + ]); + }); + + it("close a current tab forcely", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { + pinned: true, + active: false, + }); + await tabPresenter.create("https://example.com/2", { + pinned: true, + active: true, + }); + await tabPresenter.create("https://example.com/3", { + pinned: true, + active: false, + }); + const sut = new CloseTabOperator(tabPresenter, true); + + await sut.run(); + + const tabs = await tabPresenter.getAll(); + expect(tabs.map((t) => t.url)).to.deep.equal([ + "https://example.com/1", + "https://example.com/3", + ]); + }); + + it("close a current tab and select left of the closed tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new CloseTabOperator(tabPresenter, false, true); + + await sut.run(); + + const tab = await tabPresenter.getCurrent(); + expect(tab.url).to.equal("https://example.com/1"); + }); + }); +}); diff --git a/test/background/operators/impls/CloseTabRightOperator.test.ts b/test/background/operators/impls/CloseTabRightOperator.test.ts new file mode 100644 index 0000000..c2a106c --- /dev/null +++ b/test/background/operators/impls/CloseTabRightOperator.test.ts @@ -0,0 +1,24 @@ +import { expect } from "chai"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import CloseTabRightOperator from "../../../../src/background/operators/impls/CloseTabRightOperator"; + +describe("CloseTabRightOperator", () => { + describe("#run", () => { + it("close the right of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + await tabPresenter.create("https://example.com/4", { active: false }); + const sut = new CloseTabRightOperator(tabPresenter); + + await sut.run(); + + const tabs = await tabPresenter.getAll(); + expect(tabs.map((t) => t.url)).to.deep.equal([ + "https://example.com/1", + "https://example.com/2", + ]); + }); + }); +}); diff --git a/test/background/operators/impls/CommandOperatorFactoryChain.test.ts b/test/background/operators/impls/CommandOperatorFactoryChain.test.ts new file mode 100644 index 0000000..e481c5a --- /dev/null +++ b/test/background/operators/impls/CommandOperatorFactoryChain.test.ts @@ -0,0 +1,42 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import CommandOperatorFactoryChain from "../../../../src/background/operators/impls/CommandOperatorFactoryChain"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; +import * as operations from "../../../../src/shared/operations"; +import ShowCommandOperator from "../../../../src/background/operators/impls/ShowCommandOperator"; +import ShowTabOpenCommandOperator from "../../../../src/background/operators/impls/ShowTabOpenCommandOperator"; +import ShowWinOpenCommandOperator from "../../../../src/background/operators/impls/ShowWinOpenCommandOperator"; +import ShowBufferCommandOperator from "../../../../src/background/operators/impls/ShowBufferCommandOperator"; +import ShowAddBookmarkOperator from "../../../../src/background/operators/impls/ShowAddBookmarkOperator"; +import StartFindOperator from "../../../../src/background/operators/impls/StartFindOperator"; + +describe("CommandOperatorFactoryChain", () => { + describe("#create", () => { + it("returns a operator for the operation", async () => { + const tabPresenter = new MockTabPresenter(); + const consoleClient = new MockConsoleClient(); + const sut = new CommandOperatorFactoryChain(tabPresenter, consoleClient); + + expect(sut.create({ type: operations.COMMAND_SHOW })).to.be.instanceOf( + ShowCommandOperator + ); + expect( + sut.create({ type: operations.COMMAND_SHOW_TABOPEN, alter: true }) + ).to.be.instanceOf(ShowTabOpenCommandOperator); + expect( + sut.create({ type: operations.COMMAND_SHOW_WINOPEN, alter: true }) + ).to.be.instanceOf(ShowWinOpenCommandOperator); + expect( + sut.create({ type: operations.COMMAND_SHOW_BUFFER }) + ).to.be.instanceOf(ShowBufferCommandOperator); + expect( + sut.create({ type: operations.COMMAND_SHOW_ADDBOOKMARK, alter: true }) + ).to.be.instanceOf(ShowAddBookmarkOperator); + expect(sut.create({ type: operations.FIND_START })).to.be.instanceOf( + StartFindOperator + ); + expect(sut.create({ type: operations.CANCEL })).to.be.null; + }); + }); +}); diff --git a/test/background/operators/impls/DuplicateTabOperator.test.ts b/test/background/operators/impls/DuplicateTabOperator.test.ts new file mode 100644 index 0000000..ce2c19d --- /dev/null +++ b/test/background/operators/impls/DuplicateTabOperator.test.ts @@ -0,0 +1,25 @@ +import { expect } from "chai"; +import DuplicateTabOperator from "../../../../src/background/operators/impls/DuplicateTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("DuplicateTabOperator", () => { + describe("#run", () => { + it("duplicate a tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new DuplicateTabOperator(tabPresenter); + + await sut.run(); + + const tabs = await tabPresenter.getAll(); + expect(tabs.map((t) => t.url)).to.deep.equal([ + "https://example.com/1", + "https://example.com/2", + "https://example.com/3", + "https://example.com/2", + ]); + }); + }); +}); diff --git a/test/background/operators/impls/InternalOpenURLOperator.test.ts b/test/background/operators/impls/InternalOpenURLOperator.test.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/background/operators/impls/InternalOpenURLOperator.test.ts diff --git a/test/background/operators/impls/InternalOperatorFactoryChain.test.ts b/test/background/operators/impls/InternalOperatorFactoryChain.test.ts new file mode 100644 index 0000000..09029db --- /dev/null +++ b/test/background/operators/impls/InternalOperatorFactoryChain.test.ts @@ -0,0 +1,37 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import InternalOperatorFactoryChain from "../../../../src/background/operators/impls/InternalOperatorFactoryChain"; +import MockWindowPresenter from "../../mock/MockWindowPresenter"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; +import CancelOperator from "../../../../src/background/operators/impls/CancelOperator"; +import InternalOpenURLOperator from "../../../../src/background/operators/impls/InternalOpenURLOperator"; +import * as operations from "../../../../src/shared/operations"; + +describe("InternalOperatorFactoryChain", () => { + describe("#create", () => { + it("returns a operator for the operation", async () => { + const windowPresenter = new MockWindowPresenter(); + const tabPresenter = new MockTabPresenter(); + const consoleClient = new MockConsoleClient(); + const sut = new InternalOperatorFactoryChain( + windowPresenter, + tabPresenter, + consoleClient + ); + + expect(sut.create({ type: operations.CANCEL })).to.be.instanceOf( + CancelOperator + ); + expect( + sut.create({ + type: operations.INTERNAL_OPEN_URL, + url: "https://example.com", + newTab: false, + newWindow: false, + }) + ).to.be.instanceOf(InternalOpenURLOperator); + expect(sut.create({ type: operations.COMMAND_SHOW })).to.be.null; + }); + }); +}); diff --git a/test/background/operators/impls/NavigateHistoryNextOperator.test.ts b/test/background/operators/impls/NavigateHistoryNextOperator.test.ts new file mode 100644 index 0000000..de8f597 --- /dev/null +++ b/test/background/operators/impls/NavigateHistoryNextOperator.test.ts @@ -0,0 +1,25 @@ +import sinon from "sinon"; +import NavigateHistoryNextOperator from "../../../../src/background/operators/impls/NavigateHistoryNextOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockNavigateClient from "../../mock/MockNavigateClient"; + +describe("NavigateHistoryNextOperator", () => { + describe("#run", () => { + it("send a message to navigate next in the history", async () => { + const navigateClient = new MockNavigateClient(); + const mock = sinon + .mock(navigateClient) + .expects("historyNext") + .withArgs(1); + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new NavigateHistoryNextOperator(tabPresenter, navigateClient); + + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/NavigateHistoryPrevOperator.test.ts b/test/background/operators/impls/NavigateHistoryPrevOperator.test.ts new file mode 100644 index 0000000..6ebe71e --- /dev/null +++ b/test/background/operators/impls/NavigateHistoryPrevOperator.test.ts @@ -0,0 +1,25 @@ +import sinon from "sinon"; +import NavigateHistoryPrevOperator from "../../../../src/background/operators/impls/NavigateHistoryPrevOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockNavigateClient from "../../mock/MockNavigateClient"; + +describe("NavigateHistoryPrevOperator", () => { + describe("#run", () => { + it("send a message to navigate previous in the history", async () => { + const navigateClient = new MockNavigateClient(); + const mock = sinon + .mock(navigateClient) + .expects("historyPrev") + .withArgs(1); + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new NavigateHistoryPrevOperator(tabPresenter, navigateClient); + + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/NavigateLinkNextOperator.test.ts b/test/background/operators/impls/NavigateLinkNextOperator.test.ts new file mode 100644 index 0000000..09c4907 --- /dev/null +++ b/test/background/operators/impls/NavigateLinkNextOperator.test.ts @@ -0,0 +1,22 @@ +import sinon from "sinon"; +import NavigateLinkNextOperator from "../../../../src/background/operators/impls/NavigateLinkNextOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockNavigateClient from "../../mock/MockNavigateClient"; + +describe("NavigateLinkNextOperator", () => { + describe("#run", () => { + it("send a message to navigate next page", async () => { + const navigateClient = new MockNavigateClient(); + const mock = sinon.mock(navigateClient).expects("linkNext").withArgs(1); + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new NavigateLinkNextOperator(tabPresenter, navigateClient); + + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/NavigateLinkPrevOperator.test.ts b/test/background/operators/impls/NavigateLinkPrevOperator.test.ts new file mode 100644 index 0000000..6b7f791 --- /dev/null +++ b/test/background/operators/impls/NavigateLinkPrevOperator.test.ts @@ -0,0 +1,22 @@ +import sinon from "sinon"; +import NavigateLinkPrevOperator from "../../../../src/background/operators/impls/NavigateLinkPrevOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockNavigateClient from "../../mock/MockNavigateClient"; + +describe("NavigateLinkPrevOperator", () => { + describe("#run", () => { + it("send a message to navigate next page", async () => { + const navigateClient = new MockNavigateClient(); + const mock = sinon.mock(navigateClient).expects("linkPrev").withArgs(1); + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const sut = new NavigateLinkPrevOperator(tabPresenter, navigateClient); + + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/NavigateOperatorFactoryChain.test.ts b/test/background/operators/impls/NavigateOperatorFactoryChain.test.ts new file mode 100644 index 0000000..dfb5654 --- /dev/null +++ b/test/background/operators/impls/NavigateOperatorFactoryChain.test.ts @@ -0,0 +1,56 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import NavigateOperatorFactoryChain from "../../../../src/background/operators/impls/NavigateOperatorFactoryChain"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockNavigateClient from "../../mock/MockNavigateClient"; +import MockBrowserSettingRepository from "../../mock/MockBrowserSettingRepository"; +import NavigateHistoryPrevOperator from "../../../../src/background/operators/impls/NavigateHistoryPrevOperator"; +import NavigateHistoryNextOperator from "../../../../src/background/operators/impls/NavigateHistoryNextOperator"; +import NavigateLinkPrevOperator from "../../../../src/background/operators/impls/NavigateLinkPrevOperator"; +import NavigateLinkNextOperator from "../../../../src/background/operators/impls/NavigateLinkNextOperator"; +import NavigateParentOperator from "../../../../src/background/operators/impls/NavigateParentOperator"; +import NavigateRootOperator from "../../../../src/background/operators/impls/NavigateRootOperator"; +import OpenHomeOperator from "../../../../src/background/operators/impls/OpenHomeOperator"; +import OpenSourceOperator from "../../../../src/background/operators/impls/OpenSourceOperator"; +import * as operations from "../../../../src/shared/operations"; + +describe("NavigateOperatorFactoryChain", () => { + describe("#create", () => { + it("returns a operator for the operation", async () => { + const tabPresenter = new MockTabPresenter(); + const navigateClient = new MockNavigateClient(); + const browserSettingRepository = new MockBrowserSettingRepository([]); + const sut = new NavigateOperatorFactoryChain( + tabPresenter, + navigateClient, + browserSettingRepository + ); + + expect( + sut.create({ type: operations.NAVIGATE_HISTORY_PREV }) + ).to.be.instanceOf(NavigateHistoryPrevOperator); + expect( + sut.create({ type: operations.NAVIGATE_HISTORY_NEXT }) + ).to.be.instanceOf(NavigateHistoryNextOperator); + expect( + sut.create({ type: operations.NAVIGATE_LINK_PREV }) + ).to.be.instanceOf(NavigateLinkPrevOperator); + expect( + sut.create({ type: operations.NAVIGATE_LINK_NEXT }) + ).to.be.instanceOf(NavigateLinkNextOperator); + expect(sut.create({ type: operations.NAVIGATE_PARENT })).to.be.instanceOf( + NavigateParentOperator + ); + expect(sut.create({ type: operations.NAVIGATE_ROOT })).to.be.instanceOf( + NavigateRootOperator + ); + expect(sut.create({ type: operations.PAGE_SOURCE })).to.be.instanceOf( + OpenSourceOperator + ); + expect( + sut.create({ type: operations.PAGE_HOME, newTab: false }) + ).to.be.instanceOf(OpenHomeOperator); + expect(sut.create({ type: operations.CANCEL })).to.be.null; + }); + }); +}); diff --git a/test/background/operators/impls/NavigateParentOperator.test.ts b/test/background/operators/impls/NavigateParentOperator.test.ts new file mode 100644 index 0000000..cc57f17 --- /dev/null +++ b/test/background/operators/impls/NavigateParentOperator.test.ts @@ -0,0 +1,53 @@ +import { expect } from "chai"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import NavigateParentOperator from "../../../../src/background/operators/impls/NavigateParentOperator"; + +describe("NavigateParentOperator", () => { + describe("#run", () => { + it("opens a parent directory of the file in the URL", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/fruits/yellow/banana", { + active: true, + }); + const sut = new NavigateParentOperator(tabPresenter); + + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.be.equal("https://example.com/fruits/yellow/"); + }); + + it("opens a parent directory of the directoryin the URL", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/fruits/yellow/"); + const sut = new NavigateParentOperator(tabPresenter); + + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.be.equal("https://example.com/fruits/"); + }); + + it("removes a hash in the URL", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/fruits/yellow/#top"); + const sut = new NavigateParentOperator(tabPresenter); + + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.be.equal("https://example.com/fruits/yellow/"); + }); + + it("removes query parameters in the URL", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/search?q=apple"); + const sut = new NavigateParentOperator(tabPresenter); + + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.be.equal("https://example.com/search"); + }); + }); +}); diff --git a/test/background/operators/impls/NavigateRootOperator.test.ts b/test/background/operators/impls/NavigateRootOperator.test.ts new file mode 100644 index 0000000..bbe574c --- /dev/null +++ b/test/background/operators/impls/NavigateRootOperator.test.ts @@ -0,0 +1,18 @@ +import { expect } from "chai"; +import NavigateRootOperator from "../../../../src/background/operators/impls/NavigateRootOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("NavigateRootOperator", () => { + describe("#run", () => { + it("opens root directory in the URL", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/search?q=apple#top"); + const sut = new NavigateRootOperator(tabPresenter); + + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.be.equal("https://example.com"); + }); + }); +}); diff --git a/test/background/operators/impls/OpenHomeOperator.test.ts b/test/background/operators/impls/OpenHomeOperator.test.ts new file mode 100644 index 0000000..3c9288f --- /dev/null +++ b/test/background/operators/impls/OpenHomeOperator.test.ts @@ -0,0 +1,70 @@ +import { expect } from "chai"; +import OpenHomeOperator from "../../../../src/background/operators/impls/OpenHomeOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockBrowserSettingRepository from "../../mock/MockBrowserSettingRepository"; + +describe("OpenHomeOperator", () => { + describe("#run", () => { + it("opens a home page of the browser into the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/"); + const browserSettingRepository = new MockBrowserSettingRepository([ + "https://example.net/", + ]); + const sut = new OpenHomeOperator( + tabPresenter, + browserSettingRepository, + false + ); + + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.be.equal("https://example.net/"); + }); + + it("opens a home page of the browser into a new tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/"); + const browserSettingRepository = new MockBrowserSettingRepository([ + "https://example.net/", + ]); + const sut = new OpenHomeOperator( + tabPresenter, + browserSettingRepository, + true + ); + + await sut.run(); + + const urls = (await tabPresenter.getAll()).map((t) => t.url); + expect(urls).to.be.deep.equal([ + "https://example.com/", + "https://example.net/", + ]); + }); + + it("opens home pages of the browser", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/"); + const browserSettingRepository = new MockBrowserSettingRepository([ + "https://example.net/", + "https://example.org/", + ]); + const sut = new OpenHomeOperator( + tabPresenter, + browserSettingRepository, + false + ); + + await sut.run(); + + const urls = (await tabPresenter.getAll()).map((t) => t.url); + expect(urls).to.be.deep.equal([ + "https://example.com/", + "https://example.net/", + "https://example.org/", + ]); + }); + }); +}); diff --git a/test/background/operators/impls/OpenSourceOperator.test.ts b/test/background/operators/impls/OpenSourceOperator.test.ts new file mode 100644 index 0000000..541032b --- /dev/null +++ b/test/background/operators/impls/OpenSourceOperator.test.ts @@ -0,0 +1,21 @@ +import { expect } from "chai"; +import OpenSourceOperator from "../../../../src/background/operators/impls/OpenSourceOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("OpenSourceOperator", () => { + describe("#run", () => { + it("opens view-source URL of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/"); + const sut = new OpenSourceOperator(tabPresenter); + + await sut.run(); + + const urls = (await tabPresenter.getAll()).map((t) => t.url); + expect(urls).to.be.deep.equal([ + "https://example.com/", + "view-source:https://example.com/", + ]); + }); + }); +}); diff --git a/test/background/operators/impls/PinTabOperator.test.ts b/test/background/operators/impls/PinTabOperator.test.ts new file mode 100644 index 0000000..0c940b6 --- /dev/null +++ b/test/background/operators/impls/PinTabOperator.test.ts @@ -0,0 +1,25 @@ +import { expect } from "chai"; +import PinTabOperator from "../../../../src/background/operators/impls/PinTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("PinTabOperator", () => { + describe("#run", () => { + it("make pinned to the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/", { + active: true, + pinned: false, + }); + await tabPresenter.create("https://example.com/", { + active: false, + pinned: false, + }); + const sut = new PinTabOperator(tabPresenter); + + await sut.run(); + + const pins = (await tabPresenter.getAll()).map((t) => t.pinned); + expect(pins).to.deep.equal([true, false]); + }); + }); +}); diff --git a/test/background/operators/impls/ReloadTabOperator.test.ts b/test/background/operators/impls/ReloadTabOperator.test.ts new file mode 100644 index 0000000..e87782b --- /dev/null +++ b/test/background/operators/impls/ReloadTabOperator.test.ts @@ -0,0 +1,34 @@ +import sinon from "sinon"; +import ReloadTabOperator from "../../../../src/background/operators/impls/ReloadTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("ReloadTabOperator", () => { + describe("#run", () => { + it("reloads the current tab with cache", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/", { active: true }); + await tabPresenter.create("https://example.com/", { active: false }); + const mock = sinon.mock(tabPresenter).expects("reload").withArgs(0, true); + + const sut = new ReloadTabOperator(tabPresenter, true); + await sut.run(); + + mock.verify(); + }); + + it("reloads the current tab without cache", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/", { active: true }); + await tabPresenter.create("https://example.com/", { active: false }); + const mock = sinon + .mock(tabPresenter) + .expects("reload") + .withArgs(0, false); + + const sut = new ReloadTabOperator(tabPresenter, false); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ReopenTabOperator.test.ts b/test/background/operators/impls/ReopenTabOperator.test.ts new file mode 100644 index 0000000..43b1575 --- /dev/null +++ b/test/background/operators/impls/ReopenTabOperator.test.ts @@ -0,0 +1,17 @@ +import sinon from "sinon"; +import ReopenTabOperator from "../../../../src/background/operators/impls/ReopenTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("ReopenTabOperator", () => { + describe("#run", () => { + it("reopens closed tabs", async () => { + const tabPresenter = new MockTabPresenter(); + const mock = sinon.mock(tabPresenter).expects("reopen"); + + const sut = new ReopenTabOperator(tabPresenter); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/RepeatLastOperator.test.ts b/test/background/operators/impls/RepeatLastOperator.test.ts new file mode 100644 index 0000000..57f1227 --- /dev/null +++ b/test/background/operators/impls/RepeatLastOperator.test.ts @@ -0,0 +1,56 @@ +import RepeatLastOperator from "../../../../src/background/operators/impls/RepeatLastOperator"; +import MockRepeatRepository from "../../mock/MockRepeatRepository"; +import OperatorFactory from "../../../../src/background/operators/OperatorFactory"; +import * as operations from "../../../../src/shared/operations"; +import Operator from "../../../../src/background/operators/Operator"; +import sinon from "sinon"; + +class MockOperatorFactory implements OperatorFactory { + create(_op: operations.Operation): Operator { + throw new Error("not implemented"); + } +} + +class MockOperator implements Operator { + run(): Promise<void> { + throw new Error("not implemented"); + } +} + +describe("RepeatLastOperator", () => { + describe("#run", () => { + it("repeat last operation", async () => { + const operator = new MockOperator(); + const operatorMock = sinon.mock(operator).expects("run").once(); + const repeatRepository = new MockRepeatRepository(); + repeatRepository.setLastOperation({ type: operations.CANCEL }); + + const operatorFactory = new MockOperatorFactory(); + const operatorFactoryMock = sinon + .mock(operatorFactory) + .expects("create") + .withArgs({ type: operations.CANCEL }); + operatorFactoryMock.returns(operator); + + const sut = new RepeatLastOperator(repeatRepository, operatorFactory); + await sut.run(); + + operatorFactoryMock.verify(); + operatorMock.verify(); + }); + + it("does nothing if no last operations", async () => { + const repeatRepository = new MockRepeatRepository(); + const operatorFactory = new MockOperatorFactory(); + const operatorFactoryMock = sinon + .mock(operatorFactory) + .expects("create") + .never(); + + const sut = new RepeatLastOperator(repeatRepository, operatorFactory); + await sut.run(); + + operatorFactoryMock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/RepeatOperatorFactoryChain.test.ts b/test/background/operators/impls/RepeatOperatorFactoryChain.test.ts new file mode 100644 index 0000000..e12d788 --- /dev/null +++ b/test/background/operators/impls/RepeatOperatorFactoryChain.test.ts @@ -0,0 +1,32 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import RepeatOperatorFactoryChain from "../../../../src/background/operators/impls/RepeatOperatorFactoryChain"; +import RepeatLastOperator from "../../../../src/background/operators/impls/RepeatLastOperator"; +import OperatorFactory from "../../../../src/background/operators/OperatorFactory"; +import MockRepeatRepository from "../../mock/MockRepeatRepository"; +import Operator from "../../../../src/content/operators/Operator"; +import * as operations from "../../../../src/shared/operations"; + +class MockOperatorFactory implements OperatorFactory { + create(_op: operations.Operation): Operator { + throw new Error("not implemented"); + } +} + +describe("RepeatOperatorFactoryChain", () => { + describe("#create", () => { + it("returns a operator for the operation", async () => { + const repeatRepository = new MockRepeatRepository(); + const operatorFactory = new MockOperatorFactory(); + const sut = new RepeatOperatorFactoryChain( + repeatRepository, + operatorFactory + ); + + expect(sut.create({ type: operations.REPEAT_LAST })).to.be.instanceOf( + RepeatLastOperator + ); + expect(sut.create({ type: operations.CANCEL })).to.be.null; + }); + }); +}); diff --git a/test/background/operators/impls/ResetZoomOperator.test.ts b/test/background/operators/impls/ResetZoomOperator.test.ts new file mode 100644 index 0000000..68cda05 --- /dev/null +++ b/test/background/operators/impls/ResetZoomOperator.test.ts @@ -0,0 +1,17 @@ +import sinon from "sinon"; +import ResetZoomOperator from "../../../../src/background/operators/impls/ResetZoomOperator"; +import MockZoomPresenter from "../../mock/MockZoomPresenter"; + +describe("ResetZoomOperator", () => { + describe("#run", () => { + it("resets zoom on the tab", async () => { + const zoomPresenter = new MockZoomPresenter(); + const mock = sinon.mock(zoomPresenter).expects("resetZoom").once(); + + const sut = new ResetZoomOperator(zoomPresenter); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/SelectFirstTabOperator.test.ts b/test/background/operators/impls/SelectFirstTabOperator.test.ts new file mode 100644 index 0000000..a3f1d7e --- /dev/null +++ b/test/background/operators/impls/SelectFirstTabOperator.test.ts @@ -0,0 +1,20 @@ +import { expect } from "chai"; +import SelectFirstTabOperator from "../../../../src/background/operators/impls/SelectFirstTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("SelectFirstTabOperator", () => { + describe("#run", () => { + it("select the leftmost tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + + const sut = new SelectFirstTabOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/1"); + }); + }); +}); diff --git a/test/background/operators/impls/SelectLastTabOperator.test.ts b/test/background/operators/impls/SelectLastTabOperator.test.ts new file mode 100644 index 0000000..b8cf5c4 --- /dev/null +++ b/test/background/operators/impls/SelectLastTabOperator.test.ts @@ -0,0 +1,20 @@ +import { expect } from "chai"; +import SelectLastTabOperator from "../../../../src/background/operators/impls/SelectLastTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("SelectLastTabOperator", () => { + describe("#run", () => { + it("select the rightmost tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + + const sut = new SelectLastTabOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/3"); + }); + }); +}); diff --git a/test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts b/test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts new file mode 100644 index 0000000..5e6cc73 --- /dev/null +++ b/test/background/operators/impls/SelectPreviousSelectedTabOperator.test.ts @@ -0,0 +1,38 @@ +import { expect } from "chai"; +import sinon from "sinon"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import SelectPreviousSelectedTabOperator from "../../../../src/background/operators/impls/SelectPreviousSelectedTabOperator"; + +describe("SelectPreviousSelectedTabOperator", () => { + describe("#run", () => { + it("select the last-selected tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + sinon.stub(tabPresenter, "getLastSelectedId").returns(Promise.resolve(0)); + + const sut = new SelectPreviousSelectedTabOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/1"); + }); + + it("do nothing if no last-selected tabs", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + sinon + .stub(tabPresenter, "getLastSelectedId") + .returns(Promise.resolve(undefined)); + const mock = sinon.mock(tabPresenter).expects("select").never(); + + const sut = new SelectPreviousSelectedTabOperator(tabPresenter); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/SelectTabNextOperator.test.ts b/test/background/operators/impls/SelectTabNextOperator.test.ts new file mode 100644 index 0000000..5952d92 --- /dev/null +++ b/test/background/operators/impls/SelectTabNextOperator.test.ts @@ -0,0 +1,35 @@ +import { expect } from "chai"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import SelectTabNextOperator from "../../../../src/background/operators/impls/SelectTabNextOperator"; + +describe("SelectTabNextOperator", () => { + describe("#run", () => { + it("select a right tab of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + + const sut = new SelectTabNextOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/3"); + }); + }); + + describe("#run", () => { + it("select a right tab of the current tab in rotation", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: false }); + await tabPresenter.create("https://example.com/3", { active: true }); + + const sut = new SelectTabNextOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/1"); + }); + }); +}); diff --git a/test/background/operators/impls/SelectTabPrevOperator.test.ts b/test/background/operators/impls/SelectTabPrevOperator.test.ts new file mode 100644 index 0000000..c9092fa --- /dev/null +++ b/test/background/operators/impls/SelectTabPrevOperator.test.ts @@ -0,0 +1,35 @@ +import { expect } from "chai"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import SelectTabPrevOperator from "../../../../src/background/operators/impls/SelectTabPrevOperator"; + +describe("SelectTabPrevOperator", () => { + describe("#run", () => { + it("select a left tab of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + + const sut = new SelectTabPrevOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/1"); + }); + }); + + describe("#run", () => { + it("select a left tab of the current tab in rotation", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: true }); + await tabPresenter.create("https://example.com/2", { active: false }); + await tabPresenter.create("https://example.com/3", { active: false }); + + const sut = new SelectTabPrevOperator(tabPresenter); + await sut.run(); + + const url = (await tabPresenter.getCurrent()).url; + expect(url).to.equal("https://example.com/3"); + }); + }); +}); diff --git a/test/background/operators/impls/ShowAddBookmarkOperator.test.ts b/test/background/operators/impls/ShowAddBookmarkOperator.test.ts new file mode 100644 index 0000000..1e083c2 --- /dev/null +++ b/test/background/operators/impls/ShowAddBookmarkOperator.test.ts @@ -0,0 +1,50 @@ +import sinon from "sinon"; +import ShowAddBookmarkOperator from "../../../../src/background/operators/impls/ShowAddBookmarkOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("ShowAddBookmarkOperator", () => { + describe("#run", () => { + it("show command with addbookmark command", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "addbookmark "); + + const sut = new ShowAddBookmarkOperator( + tabPresenter, + consoleClient, + false + ); + await sut.run(); + + mock.verify(); + }); + + it("show command with addbookmark command and an URL of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "addbookmark welcome, world"); + + const sut = new ShowAddBookmarkOperator( + tabPresenter, + consoleClient, + true + ); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ShowBufferCommandOperator.test.ts b/test/background/operators/impls/ShowBufferCommandOperator.test.ts new file mode 100644 index 0000000..91455b3 --- /dev/null +++ b/test/background/operators/impls/ShowBufferCommandOperator.test.ts @@ -0,0 +1,25 @@ +import sinon from "sinon"; +import ShowBufferCommandOperator from "../../../../src/background/operators/impls/ShowBufferCommandOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("ShowBufferCommandOperator", () => { + describe("#run", () => { + it("show command with buffer command", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "buffer "); + + const sut = new ShowBufferCommandOperator(tabPresenter, consoleClient); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ShowCommandOperator.test.ts b/test/background/operators/impls/ShowCommandOperator.test.ts new file mode 100644 index 0000000..83b028c --- /dev/null +++ b/test/background/operators/impls/ShowCommandOperator.test.ts @@ -0,0 +1,25 @@ +import sinon from "sinon"; +import ShowCommandOperator from "../../../../src/background/operators/impls/ShowCommandOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("ShowCommandOperator", () => { + describe("#run", () => { + it("show command with addbookmark command", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, ""); + + const sut = new ShowCommandOperator(tabPresenter, consoleClient); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ShowOpenCommandOperator.test.ts b/test/background/operators/impls/ShowOpenCommandOperator.test.ts new file mode 100644 index 0000000..2c2105a --- /dev/null +++ b/test/background/operators/impls/ShowOpenCommandOperator.test.ts @@ -0,0 +1,50 @@ +import sinon from "sinon"; +import ShowOpenCommandOperator from "../../../../src/background/operators/impls/ShowOpenCommandOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("ShowOpenCommandOperator", () => { + describe("#run", () => { + it("show command with open command", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "open "); + + const sut = new ShowOpenCommandOperator( + tabPresenter, + consoleClient, + false + ); + await sut.run(); + + mock.verify(); + }); + + it("show command with open command and an URL of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "open https://example.com/2"); + + const sut = new ShowOpenCommandOperator( + tabPresenter, + consoleClient, + true + ); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ShowTabOpenCommandOperator.test.ts b/test/background/operators/impls/ShowTabOpenCommandOperator.test.ts new file mode 100644 index 0000000..e291d05 --- /dev/null +++ b/test/background/operators/impls/ShowTabOpenCommandOperator.test.ts @@ -0,0 +1,50 @@ +import sinon from "sinon"; +import ShowTabOpenCommandOperator from "../../../../src/background/operators/impls/ShowTabOpenCommandOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("ShowTabOpenCommandOperator", () => { + describe("#run", () => { + it("show command with tabopen command", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "tabopen "); + + const sut = new ShowTabOpenCommandOperator( + tabPresenter, + consoleClient, + false + ); + await sut.run(); + + mock.verify(); + }); + + it("show command with tabopen command and an URL of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "tabopen https://example.com/2"); + + const sut = new ShowTabOpenCommandOperator( + tabPresenter, + consoleClient, + true + ); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ShowWinOpenCommandOperator.test.ts b/test/background/operators/impls/ShowWinOpenCommandOperator.test.ts new file mode 100644 index 0000000..c81a2d4 --- /dev/null +++ b/test/background/operators/impls/ShowWinOpenCommandOperator.test.ts @@ -0,0 +1,50 @@ +import sinon from "sinon"; +import ShowWinOpenCommandOperator from "../../../../src/background/operators/impls/ShowWinOpenCommandOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("ShowWinOpenCommandOperator", () => { + describe("#run", () => { + it("show command with winopen command", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "winopen "); + + const sut = new ShowWinOpenCommandOperator( + tabPresenter, + consoleClient, + false + ); + await sut.run(); + + mock.verify(); + }); + + it("show command with winopen command and an URL of the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon + .mock(consoleClient) + .expects("showCommand") + .withArgs(1, "winopen https://example.com/2"); + + const sut = new ShowWinOpenCommandOperator( + tabPresenter, + consoleClient, + true + ); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/StartFindOperator.test.ts b/test/background/operators/impls/StartFindOperator.test.ts new file mode 100644 index 0000000..7764520 --- /dev/null +++ b/test/background/operators/impls/StartFindOperator.test.ts @@ -0,0 +1,22 @@ +import sinon from "sinon"; +import StartFindOperator from "../../../../src/background/operators/impls/StartFindOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import MockConsoleClient from "../../mock/MockConsoleClient"; + +describe("StartFindOperator", () => { + describe("#run", () => { + it("show find console", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/1", { active: false }); + await tabPresenter.create("https://example.com/2", { active: true }); + await tabPresenter.create("https://example.com/3", { active: false }); + const consoleClient = new MockConsoleClient(); + const mock = sinon.mock(consoleClient).expects("showFind").withArgs(1); + + const sut = new StartFindOperator(tabPresenter, consoleClient); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/TabOperatorFactoryChain.test.ts b/test/background/operators/impls/TabOperatorFactoryChain.test.ts new file mode 100644 index 0000000..7ab5de0 --- /dev/null +++ b/test/background/operators/impls/TabOperatorFactoryChain.test.ts @@ -0,0 +1,71 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import TabOperatorFactoryChain from "../../../../src/background/operators/impls/TabOperatorFactoryChain"; +import MockTabPresenter from "../../mock/MockTabPresenter"; +import DuplicateTabOperator from "../../../../src/background/operators/impls/DuplicateTabOperator"; +import TogglePinnedTabOperator from "../../../../src/background/operators/impls/TogglePinnedTabOperator"; +import UnpinTabOperator from "../../../../src/background/operators/impls/UnpinTabOperator"; +import PinTabOperator from "../../../../src/background/operators/impls/PinTabOperator"; +import ReloadTabOperator from "../../../../src/background/operators/impls/ReloadTabOperator"; +import SelectPreviousSelectedTabOperator from "../../../../src/background/operators/impls/SelectPreviousSelectedTabOperator"; +import SelectLastTabOperator from "../../../../src/background/operators/impls/SelectLastTabOperator"; +import SelectFirstTabOperator from "../../../../src/background/operators/impls/SelectFirstTabOperator"; +import SelectTabNextOperator from "../../../../src/background/operators/impls/SelectTabNextOperator"; +import SelectTabPrevOperator from "../../../../src/background/operators/impls/SelectTabPrevOperator"; +import ReopenTabOperator from "../../../../src/background/operators/impls/ReopenTabOperator"; +import CloseTabOperator from "../../../../src/background/operators/impls/CloseTabOperator"; +import CloseTabRightOperator from "../../../../src/background/operators/impls/CloseTabRightOperator"; +import * as operations from "../../../../src/shared/operations"; + +describe("TabOperatorFactoryChain", () => { + describe("#create", () => { + it("returns a operator for the operation", async () => { + const tabPresenter = new MockTabPresenter(); + const sut = new TabOperatorFactoryChain(tabPresenter); + + expect(sut.create({ type: operations.TAB_CLOSE })).to.be.instanceOf( + CloseTabOperator + ); + expect(sut.create({ type: operations.TAB_CLOSE_RIGHT })).to.be.instanceOf( + CloseTabRightOperator + ); + expect(sut.create({ type: operations.TAB_CLOSE_FORCE })).to.be.instanceOf( + CloseTabOperator + ); + expect(sut.create({ type: operations.TAB_REOPEN })).to.be.instanceOf( + ReopenTabOperator + ); + expect(sut.create({ type: operations.TAB_PREV })).to.be.instanceOf( + SelectTabPrevOperator + ); + expect(sut.create({ type: operations.TAB_NEXT })).to.be.instanceOf( + SelectTabNextOperator + ); + expect(sut.create({ type: operations.TAB_FIRST })).to.be.instanceOf( + SelectFirstTabOperator + ); + expect( + sut.create({ type: operations.TAB_LAST, newTab: false }) + ).to.be.instanceOf(SelectLastTabOperator); + expect( + sut.create({ type: operations.TAB_PREV_SEL, newTab: false }) + ).to.be.instanceOf(SelectPreviousSelectedTabOperator); + expect( + sut.create({ type: operations.TAB_RELOAD, cache: false }) + ).to.be.instanceOf(ReloadTabOperator); + expect(sut.create({ type: operations.TAB_PIN })).to.be.instanceOf( + PinTabOperator + ); + expect(sut.create({ type: operations.TAB_UNPIN })).to.be.instanceOf( + UnpinTabOperator + ); + expect( + sut.create({ type: operations.TAB_TOGGLE_PINNED }) + ).to.be.instanceOf(TogglePinnedTabOperator); + expect(sut.create({ type: operations.TAB_DUPLICATE })).to.be.instanceOf( + DuplicateTabOperator + ); + expect(sut.create({ type: operations.CANCEL })).to.be.null; + }); + }); +}); diff --git a/test/background/operators/impls/TogglePinnedTabOperator.test.ts b/test/background/operators/impls/TogglePinnedTabOperator.test.ts new file mode 100644 index 0000000..f155f83 --- /dev/null +++ b/test/background/operators/impls/TogglePinnedTabOperator.test.ts @@ -0,0 +1,32 @@ +import { expect } from "chai"; +import TogglePinnedTabOperator from "../../../../src/background/operators/impls/TogglePinnedTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("TogglePinnedTabOperator", () => { + describe("#run", () => { + it("toggle pinned to the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/", { + active: true, + pinned: false, + }); + await tabPresenter.create("https://example.com/", { + active: false, + pinned: false, + }); + const sut = new TogglePinnedTabOperator(tabPresenter); + + await sut.run(); + expect((await tabPresenter.getAll()).map((t) => t.pinned)).to.deep.equal([ + true, + false, + ]); + + await sut.run(); + expect((await tabPresenter.getAll()).map((t) => t.pinned)).to.deep.equal([ + false, + false, + ]); + }); + }); +}); diff --git a/test/background/operators/impls/UnpinTabOperator.test.ts b/test/background/operators/impls/UnpinTabOperator.test.ts new file mode 100644 index 0000000..745f48c --- /dev/null +++ b/test/background/operators/impls/UnpinTabOperator.test.ts @@ -0,0 +1,25 @@ +import { expect } from "chai"; +import UnpinTabOperator from "../../../../src/background/operators/impls/UnpinTabOperator"; +import MockTabPresenter from "../../mock/MockTabPresenter"; + +describe("UnpinTabOperator", () => { + describe("#run", () => { + it("make unpinned to the current tab", async () => { + const tabPresenter = new MockTabPresenter(); + await tabPresenter.create("https://example.com/", { + active: true, + pinned: true, + }); + await tabPresenter.create("https://example.com/", { + active: false, + pinned: true, + }); + const sut = new UnpinTabOperator(tabPresenter); + + await sut.run(); + + const pins = (await tabPresenter.getAll()).map((t) => t.pinned); + expect(pins).to.deep.equal([false, true]); + }); + }); +}); diff --git a/test/background/operators/impls/ZoomInOperator.test.ts b/test/background/operators/impls/ZoomInOperator.test.ts new file mode 100644 index 0000000..097e760 --- /dev/null +++ b/test/background/operators/impls/ZoomInOperator.test.ts @@ -0,0 +1,17 @@ +import sinon from "sinon"; +import ZoomInOperator from "../../../../src/background/operators/impls/ZoomInOperator"; +import MockZoomPresenter from "../../mock/MockZoomPresenter"; + +describe("ZoomInOperator", () => { + describe("#run", () => { + it("zoom-out the current tab", async () => { + const zoomPresenter = new MockZoomPresenter(); + const mock = sinon.mock(zoomPresenter).expects("zoomIn").once(); + + const sut = new ZoomInOperator(zoomPresenter); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/operators/impls/ZoomOperatorFactoryChain.test.ts b/test/background/operators/impls/ZoomOperatorFactoryChain.test.ts new file mode 100644 index 0000000..10c1cee --- /dev/null +++ b/test/background/operators/impls/ZoomOperatorFactoryChain.test.ts @@ -0,0 +1,28 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import ZoomOperatorFactoryChain from "../../../../src/background/operators/impls/ZoomOperatorFactoryChain"; +import MockZoomPresenter from "../../mock/MockZoomPresenter"; +import ZoomInOperator from "../../../../src/background/operators/impls/ZoomInOperator"; +import ZoomOutOperator from "../../../../src/background/operators/impls/ZoomOutOperator"; +import ResetZoomOperator from "../../../../src/background/operators/impls/ResetZoomOperator"; +import * as operations from "../../../../src/shared/operations"; + +describe("ZoomOperatorFactoryChain", () => { + describe("#create", () => { + it("returns a operator for the operation", async () => { + const zoomPresenter = new MockZoomPresenter(); + const sut = new ZoomOperatorFactoryChain(zoomPresenter); + + expect(sut.create({ type: operations.ZOOM_IN })).to.be.instanceOf( + ZoomInOperator + ); + expect(sut.create({ type: operations.ZOOM_OUT })).to.be.instanceOf( + ZoomOutOperator + ); + expect(sut.create({ type: operations.ZOOM_NEUTRAL })).to.be.instanceOf( + ResetZoomOperator + ); + expect(sut.create({ type: operations.CANCEL })).to.be.null; + }); + }); +}); diff --git a/test/background/operators/impls/ZoomOutOperator.test.ts b/test/background/operators/impls/ZoomOutOperator.test.ts new file mode 100644 index 0000000..e0bbcd9 --- /dev/null +++ b/test/background/operators/impls/ZoomOutOperator.test.ts @@ -0,0 +1,17 @@ +import sinon from "sinon"; +import ZoomOutOperator from "../../../../src/background/operators/impls/ZoomOutOperator"; +import MockZoomPresenter from "../../mock/MockZoomPresenter"; + +describe("ZoomOutOperator", () => { + describe("#run", () => { + it("zoom-in the current tab", async () => { + const zoomPresenter = new MockZoomPresenter(); + const mock = sinon.mock(zoomPresenter).expects("zoomOut").once(); + + const sut = new ZoomOutOperator(zoomPresenter); + await sut.run(); + + mock.verify(); + }); + }); +}); diff --git a/test/background/usecases/NavigateUseCase.test.ts b/test/background/usecases/NavigateUseCase.test.ts deleted file mode 100644 index 086d6cd..0000000 --- a/test/background/usecases/NavigateUseCase.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -import "reflect-metadata"; -import TabPresenter from "../../../src/background/presenters/TabPresenter"; -import NavigateUseCase from "../../../src/background/usecases/NavigateUseCase"; -import NavigateClient from "../../../src/background/clients/NavigateClient"; -import * as sinon from "sinon"; - -class MockTabPresenter implements TabPresenter { - create(_url: string, _opts?: unknown): Promise<browser.tabs.Tab> { - throw new Error("not implemented"); - } - - duplicate(_id: number): Promise<browser.tabs.Tab> { - throw new Error("not implemented"); - } - - getAll(): Promise<browser.tabs.Tab[]> { - throw new Error("not implemented"); - } - - getByKeyword( - _keyword: string, - _excludePinned: boolean - ): Promise<browser.tabs.Tab[]> { - throw new Error("not implemented"); - } - - getCurrent(): Promise<browser.tabs.Tab> { - throw new Error("not implemented"); - } - - getLastSelectedId(): Promise<number | undefined> { - throw new Error("not implemented"); - } - - getZoom(_tabId: number): Promise<number> { - throw new Error("not implemented"); - } - - onSelected( - _listener: (arg: { tabId: number; windowId: number }) => void - ): void { - throw new Error("not implemented"); - } - - open(_url: string, _tabId?: number): Promise<browser.tabs.Tab> { - throw new Error("not implemented"); - } - - reload(_tabId: number, _cache: boolean): Promise<void> { - throw new Error("not implemented"); - } - - remove(_ids: number[]): Promise<void> { - throw new Error("not implemented"); - } - - reopen(): Promise<void> { - throw new Error("not implemented"); - } - - select(_tabId: number): Promise<void> { - throw new Error("not implemented"); - } - - setPinned(_tabId: number, _pinned: boolean): Promise<void> { - throw new Error("not implemented"); - } - - setZoom(_tabId: number, _factor: number): Promise<void> { - throw new Error("not implemented"); - } -} - -describe("NavigateUseCase", () => { - let sut: NavigateUseCase; - let tabPresenter: TabPresenter; - let navigateClient: NavigateClient; - - beforeEach(() => { - tabPresenter = new MockTabPresenter(); - navigateClient = new NavigateClient(); - sut = new NavigateUseCase(tabPresenter, navigateClient); - }); - - const newTab = (url: string): browser.tabs.Tab => { - return { - index: 0, - title: "dummy title", - url: url, - active: true, - hidden: false, - highlighted: false, - incognito: false, - isArticle: false, - isInReaderMode: false, - lastAccessed: 1585446733000, - pinned: false, - selected: false, - windowId: 0, - }; - }; - - describe("#openParent()", async () => { - it("opens parent directory of file", async () => { - sinon - .stub(tabPresenter, "getCurrent") - .returns( - Promise.resolve(newTab("https://google.com/fruits/yellow/banana")) - ); - - const mock = sinon - .mock(tabPresenter) - .expects("open") - .withArgs("https://google.com/fruits/yellow/"); - - await sut.openParent(); - - mock.verify(); - }); - - it("opens parent directory of directory", async () => { - sinon - .stub(tabPresenter, "getCurrent") - .returns(Promise.resolve(newTab("https://google.com/fruits/yellow/"))); - - const mock = sinon - .mock(tabPresenter) - .expects("open") - .withArgs("https://google.com/fruits/"); - - await sut.openParent(); - - mock.verify(); - }); - - it("removes hash", async () => { - sinon - .stub(tabPresenter, "getCurrent") - .returns(Promise.resolve(newTab("https://google.com/#top"))); - - const mock = sinon - .mock(tabPresenter) - .expects("open") - .withArgs("https://google.com/"); - - await sut.openParent(); - - mock.verify(); - }); - - it("removes search query", async () => { - sinon - .stub(tabPresenter, "getCurrent") - .returns(Promise.resolve(newTab("https://google.com/search?q=apple"))); - - const mock = sinon - .mock(tabPresenter) - .expects("open") - .withArgs("https://google.com/search"); - - await sut.openParent(); - - mock.verify(); - }); - }); - - describe("#openRoot()", () => { - it("opens root direectory", async () => { - sinon - .stub(tabPresenter, "getCurrent") - .returns(Promise.resolve(newTab("https://google.com/seach?q=apple"))); - - const mock = sinon - .mock(tabPresenter) - .expects("open") - .withArgs("https://google.com"); - - await sut.openRoot(); - - mock.verify(); - }); - }); -}); |