Skip to content

Commit

Permalink
Create a unit framework testing infrastructure (#99)
Browse files Browse the repository at this point in the history
* test(create-webstone-app): write unit tests for the `create-webstone-app` package

* test: run tests for changed packages in a pre-commit git hook

* ci: add a tests workflow

* chore: remove the package-lock.json file at the root
  • Loading branch information
mikenikles authored Oct 17, 2021
1 parent 131b954 commit 0b94911
Show file tree
Hide file tree
Showing 20 changed files with 719 additions and 2,389 deletions.
6 changes: 6 additions & 0 deletions .changeset/breezy-forks-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@webstone/cli": minor
"create-webstone-app": minor
---

Write unit tests for the `create-webstone-app` package.
25 changes: 25 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Tests

on: pull_request

jobs:
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master

- name: Setup Node.js 14.x
uses: actions/setup-node@master
with:
node-version: 14.x

- name: Install pnpm globally
run: npm install -g pnpm

- name: Install Dependencies
run: pnpm install --frozen-lockfile

- name: Run all tests
run: pnpm test
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
coverage
node_modules
package-lock.json
packages/**/dist
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
"private": true,
"devDependencies": {
"@changesets/cli": "^2.14.1",
"@types/fs-extra": "^9.0.13",
"@types/sinon": "^10.0.4",
"c8": "^7.10.0",
"commitizen": "^4.2.3",
"cz-conventional-changelog": "^3.3.0",
"husky": "^6.0.0",
"lint-staged": "^10.5.4",
"prettier": "^2.2.1"
"prettier": "^2.2.1",
"sinon": "^11.1.2",
"tsm": "^2.1.2",
"uvu": "^0.5.2"
},
"scripts": {
"build": "pnpm --recursive --parallel build",
Expand All @@ -19,7 +25,9 @@
"preinstall": "npx only-allow pnpm",
"prepare": "husky install",
"release": "changeset publish",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "pnpm test:unit",
"test:unit": "c8 --all --include=**/src --reporter=html pnpm test:unit:only",
"test:unit:only": "uvu -r tsm packages tests"
},
"repository": {
"type": "git",
Expand All @@ -37,6 +45,7 @@
}
},
"lint-staged": {
"*.{js,ts}": "pnpm test --filter \"...[origin/main]\"",
"*.{css,js,md,ts}": "prettier --write"
}
}
17 changes: 0 additions & 17 deletions packages/cli/__tests__/cli-integration.test.ts

This file was deleted.

14 changes: 3 additions & 11 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
"format": "prettier --write **/*.{js,ts,tsx,json}",
"lint": "tslint -p .",
"prepublishOnly": "pnpm build",
"test": "jest",
"test:coverage": "jest --coverage",
"test:snapupdate": "jest --updateSnapshot",
"test:watch": "jest --watch"
"test": "pnpm test:unit",
"test:unit": "c8 --all --include=src --reporter=html pnpm test:unit:only",
"test:unit:only": "uvu -r tsm tests"
},
"watch": {
"copy-templates": {
Expand All @@ -36,20 +35,13 @@
"gluegun": "^4.7.0"
},
"devDependencies": {
"@types/jest": "^24.0.18",
"@types/node": "^12.7.11",
"jest": "^24.1.0",
"npm-watch": "^0.11.0",
"prettier": "^1.12.1",
"ts-jest": "^24.1.0",
"ts-node": "^8.4.1",
"tslint": "^5.12.0",
"tslint-config-prettier": "^1.17.0",
"tslint-config-standard": "^8.0.1",
"typescript": "^3.6.3"
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node"
}
}
11 changes: 5 additions & 6 deletions packages/cli/src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { build } = require("gluegun");
import { WebstoneToolbox } from "./extensions/web";
import { build } from "gluegun";

async function run() {
export const run = async () => {
const cli = build()
.brand("webstone")
.src(__dirname)
Expand All @@ -21,10 +22,8 @@ async function run() {
// "template",
])
.create();
const toolbox = await cli.run(process.argv);
const toolbox = (await cli.run(process.argv)) as WebstoneToolbox;

// Return to use it in tests
return toolbox;
}

module.exports = { run };
};
2 changes: 1 addition & 1 deletion packages/cli/src/commands/webstone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ const command: GluegunCommand = {
},
};

module.exports = command;
export default command;
Empty file added packages/cli/tests/.keep
Empty file.
4 changes: 3 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"version": "0.0.13",
"scripts": {
"clean": "rm -fr ./node_modules",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "pnpm test:unit",
"test:unit": "c8 --all --include=src --reporter=html pnpm test:unit:only",
"test:unit:only": "uvu -r tsm tests"
},
"author": "Mike Nikles, @mikenikles",
"license": "MIT",
Expand Down
Empty file added packages/core/tests/.keep
Empty file.
Empty file modified packages/create-webstone-app/bin
100644 → 100755
Empty file.
4 changes: 3 additions & 1 deletion packages/create-webstone-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"dev": "node ./scripts/esbuild.js dev",
"prepublishOnly": "pnpm build",
"prepare": "pnpm build",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "pnpm test:unit",
"test:unit": "c8 --all --include=src --reporter=html pnpm test:unit:only",
"test:unit:only": "uvu -r tsm tests"
},
"keywords": [
"svelte",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@ const KEY_SEQUENCE_DOWN = "\u001b[B";
const KEY_SEQUENCE_ENTER = "\n";
const KEY_SEQUENCE_RIGHT = "\u001b[C";

const pipe = (...functions) => (input) =>
functions.reduce((chain, func) => chain.then(func), Promise.resolve(input));
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const displayWelcome = () =>
new Promise((resolve) => {
export const displayWelcome = () =>
new Promise<void>((resolve) => {
// https://textfancy.com/ascii-art/
console.log(`
▄ ▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄ ▄ ▄▄▄▄▄▄▄
Expand All @@ -28,7 +25,7 @@ const displayWelcome = () =>
resolve();
});

const createAppDir = async (appName = process.argv[2]) => {
export const createAppDir = async (appName: string = process.argv[2]) => {
console.log(`Creating app directory...`);
const appDir = appName ? appName.toLowerCase().replace(/\s/g, "-") : ".";

Expand All @@ -42,24 +39,27 @@ const createAppDir = async (appName = process.argv[2]) => {
});

if (!response.value) {
process.exit(1);
throw new Error(
`Exiting, please empty the ./${appDir} directory or choose a different one to create the Webstone app.`
);
}

fs.rmSync(appDir, { recursive: true, force: true });
await fs.rm(appDir, { recursive: true, force: true });
}
}
fs.mkdirSync(appDir, { recursive: true });
return appDir;
};

const copyTemplate = (appDir) => {
console.log(`Copying template...`);
const templateDir = path.join(__dirname, "..", "template");
fs.copySync(templateDir, appDir);
return appDir;
};
export const copyTemplate = (appDir: string) =>
new Promise((resolve) => {
console.log(`Copying template...`);
const templateDir = path.join(__dirname, "..", "template");
fs.copySync(templateDir, appDir);
resolve(appDir);
});

const installWebApp = async (appDir) => {
export const installWebApp = async (appDir: string) => {
const webAppDir = `${appDir}/services/web`;
console.log(`Installing web app in ${webAppDir}...`);

Expand Down Expand Up @@ -105,7 +105,7 @@ const installWebApp = async (appDir) => {
}
};

const installDependencies = async (appDir) => {
export const installDependencies = async (appDir: string) => {
console.log(`Installing dependencies...`);
try {
await execa("pnpm", ["install"], {
Expand All @@ -119,8 +119,8 @@ const installDependencies = async (appDir) => {
}
};

const displayNextSteps = (appDir) =>
new Promise((resolve) => {
export const displayNextSteps = (appDir: string) =>
new Promise<void>((resolve) => {
console.log(`
===================================================
Congratulations 🎉! Your Webstone project is ready.
Expand All @@ -138,12 +138,3 @@ Next steps:
`);
resolve();
});

pipe(
displayWelcome,
createAppDir,
copyTemplate,
installWebApp,
installDependencies,
displayNextSteps
)();
22 changes: 22 additions & 0 deletions packages/create-webstone-app/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
createAppDir,
copyTemplate,
displayNextSteps,
displayWelcome,
installDependencies,
installWebApp,
} from "./helpers";

const pipe = (...functions: ((input?: any) => Promise<any>)[]) => (
input?: any
) =>
functions.reduce((chain, func) => chain.then(func), Promise.resolve(input));

pipe(
displayWelcome,
createAppDir,
copyTemplate,
installWebApp,
installDependencies,
displayNextSteps
)();
25 changes: 25 additions & 0 deletions packages/create-webstone-app/tests/helpers/copy-template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import fs from "fs-extra";
import path from "path";
import sinon from "sinon";
import { test } from "uvu";
import * as assert from "uvu/assert";
import { copyTemplate } from "../../src/helpers";

test.after.each(() => {
sinon.restore();
});

test("copy the template to the correct location", async () => {
const fakePathJoin = sinon.fake.returns("../template");
sinon.replace(path, "join", fakePathJoin);

const fakeFsCopySync = sinon.fake();
sinon.replace(fs, "copySync", fakeFsCopySync);

const appDir = await copyTemplate("test-dir");
assert.is(appDir, "test-dir");
assert.is(fakeFsCopySync.firstCall.firstArg, "../template");
assert.is(fakeFsCopySync.firstCall.lastArg, "test-dir");
});

test.run();
Loading

0 comments on commit 0b94911

Please sign in to comment.