Skip to content

Commit 6d3b960

Browse files
committed
Update tests to cover more failure cases
1 parent 0c719b8 commit 6d3b960

4 files changed

Lines changed: 116 additions & 35 deletions

File tree

test/end-to-end/src/test-helpers.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,54 @@ export function addTestResult(testValues: any[], resultName: string, resultValue
2323
testValues.push(data);
2424
}
2525

26+
export function addErrorResult(testValues: any[], errorMessage: string) {
27+
testValues.push({
28+
resultName: "test-error",
29+
resultValue: errorMessage,
30+
expectedValue: "no-error",
31+
});
32+
}
33+
34+
export function formatError(err: any): string {
35+
if (!err) {
36+
return "Unknown error (null/undefined)";
37+
}
38+
39+
const parts: string[] = [];
40+
41+
if (err.message) {
42+
parts.push(`Message: ${err.message}`);
43+
} else {
44+
parts.push(`${err}`);
45+
}
46+
47+
if (err.code) {
48+
parts.push(`Code: ${err.code}`);
49+
}
50+
51+
if (err.debugInfo) {
52+
if (err.debugInfo.code) {
53+
parts.push(`DebugCode: ${err.debugInfo.code}`);
54+
}
55+
if (err.debugInfo.message) {
56+
parts.push(`DebugMessage: ${err.debugInfo.message}`);
57+
}
58+
if (err.debugInfo.errorLocation) {
59+
parts.push(`Location: ${err.debugInfo.errorLocation}`);
60+
}
61+
if (err.debugInfo.innerError) {
62+
const inner = err.debugInfo.innerError;
63+
parts.push(`InnerError: ${inner.code || ""} ${inner.message || JSON.stringify(inner)}`.trim());
64+
}
65+
}
66+
67+
if (err.stack) {
68+
parts.push(`Stack: ${err.stack}`);
69+
}
70+
71+
return parts.join(" | ");
72+
}
73+
2674
export async function closeDesktopApplication(): Promise<boolean> {
2775
const processName: string = "Excel";
2876

test/end-to-end/src/test-taskpane.ts

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,66 @@
11
import functionsJsonData from "./test-data.json";
22
import { pingTestServer, sendTestResults } from "office-addin-test-helpers";
3-
import { closeWorkbook, sleep } from "./test-helpers";
3+
import { addErrorResult, closeWorkbook, formatError, sleep } from "./test-helpers";
44

55
/* global Office, document, Excel, run, navigator */
66
const customFunctionsData = (<any>functionsJsonData).functions;
77
const port: number = 4201;
8-
let testValues = [];
8+
let testValues: any[] = [];
99

1010
Office.onReady(async () => {
1111
document.getElementById("sideload-msg").style.display = "none";
1212
document.getElementById("app-body").style.display = "flex";
1313
document.getElementById("run").onclick = run;
1414
addTestResult("UserAgent", navigator.userAgent);
1515

16-
const testServerResponse: object = await pingTestServer(port);
17-
if (testServerResponse["status"] === 200) {
18-
await runCfTests();
19-
await sendTestResults(testValues, port);
20-
await closeWorkbook();
16+
try {
17+
const testServerResponse: object = await pingTestServer(port);
18+
if (testServerResponse["status"] === 200) {
19+
await runCfTests();
20+
await sendTestResults(testValues, port);
21+
await closeWorkbook();
22+
} else {
23+
addErrorResult(testValues, `Ping failed: ${JSON.stringify(testServerResponse)}`);
24+
await sendTestResults(testValues, port).catch(() => {});
25+
}
26+
} catch (err) {
27+
testValues = [];
28+
addErrorResult(testValues, `Initialization failed: ${formatError(err)}`);
29+
await sendTestResults(testValues, port).catch(() => {});
2130
}
2231
});
2332

2433
async function runCfTests(): Promise<void> {
25-
// Exercise custom functions
26-
await Excel.run(async (context) => {
27-
for (let key in customFunctionsData) {
28-
const formula: string = customFunctionsData[key].formula;
29-
const range = context.workbook.getSelectedRange();
30-
range.formulas = [[formula]];
31-
await context.sync();
34+
try {
35+
await Excel.run(async (context) => {
36+
for (let key in customFunctionsData) {
37+
const formula: string = customFunctionsData[key].formula;
38+
const range = context.workbook.getSelectedRange();
39+
range.formulas = [[formula]];
40+
await context.sync();
3241

33-
await sleep(5000);
42+
await sleep(5000);
3443

35-
// Check to if this is a streaming function
36-
await readCFData(key, customFunctionsData[key].streaming != undefined ? 2 : 1);
37-
}
38-
});
44+
await readCFData(key, customFunctionsData[key].streaming != undefined ? 2 : 1);
45+
}
46+
});
47+
} catch (err) {
48+
testValues = [];
49+
addErrorResult(testValues, `runCfTests failed: ${formatError(err)}`);
50+
throw err;
51+
}
3952
}
4053

4154
export async function readCFData(cfName: string, readCount: number): Promise<void> {
4255
await Excel.run(async (context) => {
43-
// if this is a streaming function, we want to capture two values so we can
44-
// validate the function is indeed streaming
4556
for (let i = 0; i < readCount; i++) {
46-
try {
47-
const range = context.workbook.getSelectedRange();
48-
range.load("values");
49-
await context.sync();
57+
const range = context.workbook.getSelectedRange();
58+
range.load("values");
59+
await context.sync();
5060

51-
await sleep(5000);
61+
await sleep(5000);
5262

53-
addTestResult(cfName, range.values[0][0]);
54-
Promise.resolve();
55-
} catch {
56-
Promise.reject();
57-
}
63+
addTestResult(cfName, range.values[0][0]);
5864
}
5965
});
6066
}

test/end-to-end/tests.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const host: string = "excel";
1414
const manifestPath = path.resolve(`${process.cwd()}/test/end-to-end/test-manifest.xml`);
1515
const manifestPathDebugging = path.resolve(`${process.cwd()}/test/end-to-end/test-manifest-debugging.xml`);
1616
const port: number = 4201;
17+
const testResultsTimeout: number = 120000;
1718
const testDataFile: string = `${process.cwd()}/test/end-to-end/src/test-data.json`;
1819
const testJsonData = JSON.parse(fs.readFileSync(testDataFile).toString());
1920
const testServer = new officeAddinTestServer.TestServer(port);
@@ -43,9 +44,34 @@ describe("Test Excel Custom Functions", function () {
4344
});
4445
describe("Get test results for custom functions and validate results", function () {
4546
it("should get results from the taskpane application", async function () {
46-
this.timeout(0);
47+
this.timeout(testResultsTimeout + 10000);
48+
let timeoutId: ReturnType<typeof setTimeout>;
49+
const timeoutPromise = new Promise<never>((_, reject) => {
50+
timeoutId = setTimeout(
51+
() =>
52+
reject(
53+
new Error(
54+
`[${host}] Timed out after ${testResultsTimeout / 1000}s waiting for test results. The add-in likely failed to initialize or encountered an unhandled error.`
55+
)
56+
),
57+
testResultsTimeout
58+
);
59+
});
60+
61+
try {
62+
testValues = await Promise.race([testServer.getTestResults(), timeoutPromise]);
63+
} finally {
64+
clearTimeout(timeoutId);
65+
}
66+
67+
const errorResult = testValues.find((value: any) => value.resultName === "test-error");
68+
if (errorResult) {
69+
assert.fail(`[${host}] Taskpane reported error: ${errorResult.resultValue}`);
70+
}
71+
4772
// Expecting six result values + user agent
48-
testValues = await testServer.getTestResults();
73+
testValues = testValues.filter((value: any) => value.resultName !== "test-error");
74+
assert.strictEqual(testValues.length > 0, true, `No test results received from ${host} add-in`);
4975
console.log(`User Agent: ${testValues[0].Value}`);
5076
assert.strictEqual(testValues.length, 7);
5177
});

tsconfig.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
{
22
"compilerOptions": {
33
"allowJs": true,
4-
"baseUrl": ".",
54
"esModuleInterop": true,
65
"experimentalDecorators": true,
6+
"forceConsistentCasingInFileNames": true,
77
"jsx": "react",
88
"noEmitOnError": true,
99
"outDir": "lib",
1010
"sourceMap": true,
11-
"target": "es5",
11+
"strict": true,
12+
"target": "es6",
1213
"lib": [
1314
"es2015",
1415
"dom"

0 commit comments

Comments
 (0)