Skip to content

Commit

Permalink
chore: test coverage (#19)
Browse files Browse the repository at this point in the history
* test: util base

* chore: upgrade dev deps

* test: coverage

* chore: setup sinon chrome

* chore: absolute imports for test

* test: setup chrome

* chore: setup types dir

* test: chrome tabs

* test: add sinon chrome type def

* test: windows

* fix: use window position for move

* test: window positioning

* test: declare sinon chrome module

* refactor: skip undefined windows in compare

* test: get selected tabs in window

* test: cover last branch chrome utils

* chore: some clean up

* test: wip background handler

* test: move action with active tabs

* test: move to window fail handle

* test: undoes last action

* test: jest mock prop

* test: undo limit

* test: actions

* refactor: single listener

* test: background index

* test: options page

* test: background index missing branches
  • Loading branch information
iamogbz committed Apr 20, 2019
1 parent 83625f5 commit 425b0d0
Show file tree
Hide file tree
Showing 25 changed files with 957 additions and 884 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
name: commitlint
script: npm run commitlint
- name: test
script: npm run test
script: jest --coverage --coverageReporters=text-lcov | coveralls
- name: build
script: npm run build
- stage: deploy
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![Greenkeeper badge](https://badges.greenkeeper.io/iamogbz/chrome-alt-tabs.svg)](https://greenkeeper.io/)
[![Dependencies](https://david-dm.org/iamogbz/chrome-alt-tabs.svg)](https://github.com/iamogbz/chrome-alt-tabs.svg)
[![Build Status](https://travis-ci.org/iamogbz/chrome-alt-tabs.svg?branch=master)](https://travis-ci.org/iamogbz/chrome-alt-tabs.svg)
[![Coverage Status](https://coveralls.io/repos/github/iamogbz/chrome-alt-tabs/badge.svg?branch=master)](https://coveralls.io/github/iamogbz/chrome-alt-tabs)

> speeds up tab management with simple shortcuts
Expand Down
3 changes: 3 additions & 0 deletions config/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as chrome from "sinon-chrome";

Object.assign(global, { chrome });
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Alt Tab Shortcuts",
"version": "1.1.0",
"version": "0.0.0",

"description": "Speeds up tab management with simple shortcuts",
"icons": {
Expand Down
1,127 changes: 292 additions & 835 deletions package-lock.json

Large diffs are not rendered by default.

29 changes: 21 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
"scripts": {
"commitlint": "commitlint-travis",
"build": "webpack --mode=production",
"watch": "webpack --mode=development --watch",
"build-watch": "webpack --mode=development --watch",
"test": "jest",
"test-watch": "jest --watch",
"typecheck": "tsc --noEmit",
"commit": "git-cz",
"release": "semantic-release"
Expand Down Expand Up @@ -32,22 +33,32 @@
]
},
"jest": {
"preset": "ts-jest",
"moduleDirectories": [
"./src",
"./tests",
"./node_modules"
],
"setupFilesAfterEnv": [
"./config/setupTests.ts"
],
"testPathIgnorePatterns": [
"./artifacts/",
"./node_modules/"
],
"coverageDirectory": "./artifacts/coverage",
"transform": {
"^.+\\.tsx?$": "ts-jest"
"\\.html$": "jest-raw-loader"
},
"coverageDirectory": "./artifacts/coverage",
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
"moduleFileExtensions": [
"node",
"js",
"jsx",
"json",
"ts",
"tsx"
"tsx",
"html"
]
},
"lint-staged": {
Expand Down Expand Up @@ -106,7 +117,6 @@
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-typescript": "^7.3.3",
"@commitlint/cli": "^7.5.2",
"@commitlint/config-conventional": "^7.5.0",
Expand All @@ -115,7 +125,6 @@
"@types/copy-webpack-plugin": "^4.4.3",
"@types/jest": "^24.0.9",
"@types/node": "^11.12.2",
"@types/source-map": "^0.5.2",
"@types/webpack": "^4.4.25",
"acorn": "^6.1.1",
"ajv": "^5.5.2",
Expand All @@ -124,17 +133,21 @@
"babel-runtime": "^6.26.0",
"commitizen": "^3.0.7",
"copy-webpack-plugin": "^5.0.0",
"coveralls": "^3.0.3",
"cz-conventional-changelog": "^2.1.0",
"eslint": "^5.16.0",
"husky": "^1.3.1",
"jest": "^24.1.0",
"jest-mock-props": "^1.0.4",
"jest-raw-loader": "^1.0.1",
"lint-staged": "^8.1.5",
"prettier": "^1.16.4",
"prettier": "^1.17.0",
"prettier-eslint": "^8.8.2",
"prettier-tslint": "^0.4.2",
"rxjs": "^6.4.0",
"semantic-release": "^15.13.8",
"semantic-release": "^15.13.12",
"semantic-release-chrome": "^1.1.1",
"sinon-chrome": "^3.0.1",
"ts-jest": "^24.0.0",
"ts-node": "^8.0.2",
"tslint": "^5.13.0",
Expand Down
2 changes: 2 additions & 0 deletions src/globals.d.ts → src/@types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ interface Action {
}

type ActionHandler = (action: Action) => Promise<boolean>;

declare module "options/index.html";
4 changes: 2 additions & 2 deletions src/background/handler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { log } from "../utils/base";
import { log } from "utils/base";
import {
createWindow,
focusOnTab,
focusOnWindow,
moveTabsToWindow,
selectTabs,
} from "../utils/chrome";
} from "utils/chrome";
import { MOVE_TABS, UNDO, moveTabs } from "./actions";
import { UNDO_LIMIT } from "./constants";

Expand Down
23 changes: 13 additions & 10 deletions src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
getWindowIdAfter,
getWindowIdBefore,
onCommand,
} from "../utils/chrome";
} from "utils/chrome";
import { moveTabs, undo } from "./actions";
import { COMMANDS } from "./constants";
import { handleAction } from "./handler";
Expand Down Expand Up @@ -37,29 +37,32 @@ const withCommandContext = (fn: (...args: any[]) => void) => async () => {
return fn({ windowId: currentWindow.id, selectedTabs, isAllTabsSelected });
};

const commandActions = {
export const commandActions = {
[COMMANDS.OUT]: withCommandContext(
({ windowId, selectedTabs: tabs, isAllTabsSelected }) => {
async ({ windowId, selectedTabs: tabs, isAllTabsSelected }) => {
const from = isAllTabsSelected ? null : (windowId as number);
handleAction(moveTabs({ tabs, from }));
await handleAction(moveTabs({ tabs, from }));
},
),
[COMMANDS.NEXT]: withCommandContext(
async ({ windowId, selectedTabs: tabs, isAllTabsSelected }) => {
const from = isAllTabsSelected ? null : (windowId as number);
const to = await getWindowIdAfter(from);
handleAction(moveTabs({ tabs, from, to }));
await handleAction(moveTabs({ tabs, from, to }));
},
),
[COMMANDS.PREV]: withCommandContext(
async ({ windowId, selectedTabs: tabs, isAllTabsSelected }) => {
const from = isAllTabsSelected ? null : (windowId as number);
const to = await getWindowIdBefore(from);
handleAction(moveTabs({ tabs, from, to }));
await handleAction(moveTabs({ tabs, from, to }));
},
),
[COMMANDS.BACK]: () => handleAction(undo()),
[COMMANDS.BACK]: async () => {
await handleAction(undo());
},
};
Object.keys(commandActions).forEach(type =>
onCommand(type, commandActions[type]),
);
const noop = (): void => undefined;
export const commandListener = (command: string): void =>
(commandActions[command] || noop)();
onCommand(commandListener);
2 changes: 1 addition & 1 deletion src/options/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { changeTabUrl, getAllCommands } from "../utils/chrome";
import { changeTabUrl, getAllCommands } from "utils/chrome";

document.addEventListener("DOMContentLoaded", async () => {
const changeShortcutsButton = document.getElementById("change-btn");
Expand Down
6 changes: 1 addition & 5 deletions src/utils/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,4 @@ export const wrapIndex = ({
}: {
index: number;
size: number;
}): number => {
if (index >= size) return size - index;
if (index < 0) return size + index;
return index;
};
}): number => (index < 0 ? size : 0) + (index % size);
22 changes: 5 additions & 17 deletions src/utils/chrome.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
import { wrapIndex } from "./base";

/**
* Bind single oncommand listener and switch based on received
* Register callback to be run on command received
*/
const listeners: { [key: string]: Set<() => any> } = {};
chrome.commands.onCommand.addListener(command => {
(listeners[command] || []).forEach((callback: () => any) => callback());
});

/**
* Register callback to be run on specific command
*/
export const onCommand = (command: string, callback: () => any): void => {
if (!Object.keys(listeners).includes(command)) {
listeners[command] = new Set();
}
listeners[command].add(callback);
};
export const onCommand = (callback: (command: string) => any): void =>
chrome.commands.onCommand.addListener(callback);

/**
* Get all registered chrome commands
Expand Down Expand Up @@ -142,7 +130,7 @@ const compareWindowPositions = (
): number => {
const props = ["left", "top", "width", "height", "id"];
while (props.length) {
const prop = props.pop();
const prop = props.shift();
const valueA: number = windowA[prop];
const valueB: number = windowB[prop];
if (valueA !== undefined && valueB !== undefined && valueA !== valueB) {
Expand All @@ -158,7 +146,7 @@ const compareWindowPositions = (
const getSortedWindowIds = async (): Promise<number[]> => {
const windows = await getAllWindows();
windows.sort(compareWindowPositions);
return windows.map(({ id }) => id);
return windows.map(({ id }) => id).filter(id => id);
};

/**
Expand Down
Empty file removed tests/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions tests/@types/jest-mock-props.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "jest-mock-props";
1 change: 1 addition & 0 deletions tests/@types/sinon-chrome.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "sinon-chrome";
55 changes: 55 additions & 0 deletions tests/background/__snapshots__/actions.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`actions move tabs creates valid action with no source 1`] = `
Object {
"payload": Object {
"from": undefined,
"tabs": Array [
Object {
"id": 33,
},
Object {
"id": 22,
},
Object {
"id": 11,
},
],
"to": 2,
},
"type": "move-tabs",
}
`;

exports[`actions move tabs creates valid action with no target 1`] = `
Object {
"payload": Object {
"from": 1,
"tabs": Array [
Object {
"id": 33,
},
Object {
"id": 22,
},
Object {
"id": 11,
},
],
"to": null,
},
"type": "move-tabs",
}
`;

exports[`actions move tabs fails to create invalid action for tabs: 1`] = `"Invalid Action Definition: move (1 => 2)"`;

exports[`actions move tabs fails to create invalid action for tabs:null 1`] = `"Invalid Action Definition: move null (1 => 2)"`;

exports[`actions move tabs fails to create invalid action for tabs:undefined 1`] = `"Invalid Action Definition: move undefined (1 => 2)"`;

exports[`actions undo creates valid action 1`] = `
Object {
"type": "undo",
}
`;
31 changes: 31 additions & 0 deletions tests/background/actions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { moveTabs, undo } from "background/actions";

describe("actions", () => {
describe("move tabs", () => {
const tabIds = [33, 22, 11];
const mockTabs = tabIds.map(id => ({ id } as ChromeTab));

it("creates valid action with no target", () => {
expect(moveTabs({ tabs: mockTabs, from: 1 })).toMatchSnapshot();
});

it("creates valid action with no source", () => {
expect(moveTabs({ tabs: mockTabs, to: 2 })).toMatchSnapshot();
});

it.each([null, undefined, []].map(v => [v]))(
"fails to create invalid action for tabs:%s",
async tabs => {
expect(() => {
moveTabs({ tabs, from: 1, to: 2 });
}).toThrowErrorMatchingSnapshot();
},
);
});

describe("undo", () => {
it("creates valid action", () => {
expect(undo()).toMatchSnapshot();
});
});
});
Loading

0 comments on commit 425b0d0

Please sign in to comment.