Skip to content

Commit c175163

Browse files
TCourtneyOwenakrantz
authored andcommitted
Add the ability to run tests (#34)
`npm run test` will now run tests using Mocha and Office.js to run the add-in and validate results.
1 parent 70c9f65 commit c175163

12 files changed

+1572
-464
lines changed

.vscode/launch.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,27 @@
44
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
55
"version": "0.2.0",
66
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "Debug Tests",
11+
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
12+
"args": [
13+
"-u",
14+
"tdd",
15+
"--timeout",
16+
"999999",
17+
"--colors",
18+
"${workspaceFolder}/test",
19+
"-r",
20+
"ts-node/register",
21+
"${workspaceFolder}/test/*.ts"
22+
],
23+
"internalConsoleOptions": "openOnSessionStart",
24+
"runtimeArgs": [
25+
"--preserve-symlinks"
26+
]
27+
},
728
{
829
"name": "Excel Desktop",
930
"type": "node",

convertToSingleHost.js

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
const convertTest = process.argv[3] === "convert-test";
12
const fs = require("fs");
23
const host = process.argv[2];
34
const hosts = ["excel", "onenote", "outlook", "powerpoint", "project", "word"];
5+
const path = require("path");
46
const util = require("util");
7+
const testPackages = ["@types/mocha", "@types/node", "current-processes", "mocha", "office-addin-test-helpers",
8+
"office-addin-test-server", "ts-node"];
59
const readFileAsync = util.promisify(fs.readFile);
610
const unlinkFileAsync = util.promisify(fs.unlink);
711
const writeFileAsync = util.promisify(fs.writeFile);
@@ -15,6 +19,9 @@ async function modifyProjectForSingleHost(host) {
1519
}
1620
await convertProjectToSingleHost(host);
1721
await updatePackageJsonForSingleHost(host);
22+
if (!convertTest) {
23+
await updateLaunchJsonFile();
24+
}
1825
}
1926

2027
async function convertProjectToSingleHost(host) {
@@ -26,8 +33,31 @@ async function convertProjectToSingleHost(host) {
2633
const srcContent = await readFileAsync(`./src/taskpane/${host}.ts`, "utf8");
2734
await writeFileAsync(`./src/taskpane/taskpane.ts`, srcContent);
2835

36+
// delete all test files by default for now - eventually we want to convert the tests by default
37+
if (convertTest && (host === "excel" || host === "word")) {
38+
// copy over host-specific taskpane test code to test-taskpane.ts
39+
const testTaskpaneContent = await readFileAsync(`./test/src/${host}-test-taskpane.ts`, "utf8");
40+
const updatedTestTaskpaneContent = testTaskpaneContent.replace(`../../src/taskpane/${host}`, `../../src/taskpane/taskpane`);
41+
await writeFileAsync(`./test/src/test-taskpane.ts`, updatedTestTaskpaneContent);
42+
43+
// update ui-test.ts to only run against specified host
44+
const testContent = await readFileAsync(`./test/ui-test.ts`, "utf8");
45+
const updatedTestContent = testContent.replace(`const hosts = ["Excel", "Word"]`, `const hosts = ["${host}"]`);
46+
await writeFileAsync(`./test/ui-test.ts`, updatedTestContent);
47+
48+
// delete all host-specific test files after converting to single host
49+
hosts.forEach(async function (host) {
50+
if (host == "excel" || host == "word") {
51+
await unlinkFileAsync(`./test/src/${host}-test-taskpane.ts`);
52+
}
53+
});
54+
}
55+
else {
56+
deleteFolder(path.resolve(`${process.cwd()}/test`));
57+
}
58+
2959
// delete all host-specific files
30-
hosts.forEach(async function(host) {
60+
hosts.forEach(async function (host) {
3161
await unlinkFileAsync(`./manifest.${host}.xml`);
3262
await unlinkFileAsync(`./src/taskpane/${host}.ts`);
3363
});
@@ -51,25 +81,69 @@ async function updatePackageJsonForSingleHost(host) {
5181
});
5282

5383
// remove scripts that are unrelated to the selected host
54-
Object.keys(content.scripts).forEach(function(key) {
55-
if (key.startsWith("sideload:")
56-
|| key.startsWith("unload:")
84+
Object.keys(content.scripts).forEach(function (key) {
85+
if (key.startsWith("sideload:")
86+
|| key.startsWith("unload:")
5787
|| key === "convert-to-single-host"
5888
) {
5989
delete content.scripts[key];
6090
}
6191
});
6292

93+
if (!convertTest) {
94+
// remove test-related scripts
95+
Object.keys(content.scripts).forEach(function (key) {
96+
if (key.includes("test")) {
97+
delete content.scripts[key];
98+
}
99+
});
100+
101+
// remove test-related packages
102+
Object.keys(content.devDependencies).forEach(function (key) {
103+
if (testPackages.includes(key)) {
104+
delete content.devDependencies[key]
105+
}
106+
});
107+
}
108+
63109
// write updated json to file
64110
await writeFileAsync(packageJson, JSON.stringify(content, null, 2));
65111
}
66112

113+
async function updateLaunchJsonFile() {
114+
// remove 'Debug Tests' configuration from launch.json
115+
const launchJson = `.vscode/launch.json`;
116+
const launchJsonContent = await readFileAsync(launchJson, "utf8");
117+
const regex = /"configurations": \[\r?\n(.*{(.*\r?\n)*?.*"name": "Debug Tests",\r?\n(.*\r?\n)*?.*},)/gm;
118+
const updatedContent = launchJsonContent.replace(regex, `"configurations": [`);
119+
await writeFileAsync(launchJson, updatedContent);
120+
}
121+
122+
function deleteFolder(folder) {
123+
try {
124+
if (fs.existsSync(folder)) {
125+
fs.readdirSync(folder).forEach(function (file, index) {
126+
const curPath = `${folder}/${file}`;
127+
128+
if (fs.lstatSync(curPath).isDirectory()) {
129+
deleteFolder(curPath);
130+
}
131+
else {
132+
fs.unlinkSync(curPath);
133+
}
134+
});
135+
fs.rmdirSync(folder);
136+
}
137+
} catch (err) {
138+
throw new Error(`Unable to delete folder "${folder}".\n${err}`);
139+
}
140+
}
67141

68142
/**
69143
* Modify the project so that it only supports a single host.
70144
* @param host The host to support.
71145
*/
72146
modifyProjectForSingleHost(host).catch(err => {
73-
console.error(`Error: ${err instanceof Error ? err.message : err}`);
74-
process.exitCode = 1;
147+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
148+
process.exitCode = 1;
75149
});

0 commit comments

Comments
 (0)