Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
registry=https://packagefeedproxy.microsoft.io/npm/
registry=https://office.pkgs.visualstudio.com/_packaging/OfficeDev/npm/registry/
always-auth=true
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Custom functions enable you to add new functions to Excel by defining those func

This repository contains the source code used by the [Yo Office generator](https://github.com/OfficeDev/generator-office) when you create a new custom functions project. You can also use this repository as a sample to base your own custom functions project from if you choose not to use the generator. For more detailed information about custom functions in Excel, see the [Custom functions overview](https://learn.microsoft.com/office/dev/add-ins/excel/custom-functions-overview) article in the Office Add-ins documentation or see the [additional resources](#additional-resources) section of this repository.

## npm registry auth
Run the following command to get the authenticator for the first time:

`npm install --global @microsoft/artifacts-npm-credprovider --registry https://pkgs.dev.azure.com/artifacts-public/23934c1b-a3b5-4b70-9dd3-d1bef4cc72a0/_packaging/AzureArtifacts/npm/registry/`
Comment thread
millerds marked this conversation as resolved.

Run `artifacts-npm-credprovider` to authenticate for the npm registry.

## Debugging custom functions

This template supports debugging custom functions from [Visual Studio Code](https://code.visualstudio.com/). For more information see [Custom functions debugging](https://aka.ms/custom-functions-debug). For general information on debugging task panes and other Office Add-in parts, see [Test and debug Office Add-ins](https://learn.microsoft.com/office/dev/add-ins/testing/test-debug-office-add-ins).
Expand Down
7,069 changes: 3,786 additions & 3,283 deletions package-lock.json

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,30 @@
"@types/office-runtime": "^1.0.35",
"acorn": "^8.5.0",
"babel-loader": "^10.1.1",
"copy-webpack-plugin": "^12.0.2",
"copy-webpack-plugin": "^14.0.0",
"custom-functions-metadata-plugin": "^2.1.3",
"eslint-plugin-office-addins": "^4.0.3",
"eslint-plugin-office-addins": "^4.0.10",
"file-loader": "^6.2.0",
"html-loader": "^5.0.0",
"html-webpack-plugin": "^5.6.0",
"mocha": "^11.7.4",
"office-addin-cli": "^2.0.6",
"office-addin-debugging": "^6.0.6",
"office-addin-dev-certs": "^2.0.6",
"office-addin-lint": "^3.0.6",
"office-addin-manifest": "^2.1.2",
"office-addin-mock": "^3.0.6",
"office-addin-prettier-config": "^2.0.1",
"office-addin-test-helpers": "^2.0.3",
"office-addin-test-server": "^2.0.3",
"office-addin-cli": "^2.0.10",
"office-addin-debugging": "^6.1.2",
"office-addin-dev-certs": "^2.0.10",
"office-addin-lint": "^3.0.10",
"office-addin-manifest": "^2.1.6",
"office-addin-mock": "^3.0.10",
"office-addin-prettier-config": "^2.0.5",
"office-addin-test-helpers": "^2.0.7",
"office-addin-test-server": "^2.0.7",
"os-browserify": "^0.3.0",
"process": "^0.11.10",
"request": "^2.88.2",
"source-map-loader": "^5.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.2",
"webpack": "^5.105.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "5.2.5"
"webpack-dev-server": "^6.0.0"
},
"prettier": "office-addin-prettier-config",
"browserslist": [
Expand Down
21 changes: 12 additions & 9 deletions test/end-to-end/src/debugger-websocket.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import * as assert from "assert";
import { sleep } from "./test-helpers";
const WebSocket = require("ws");
const request = require("request");

/* global require, console */
let connectionOpened = false;
let messageId = 0;
const limitOfReconnectTries = 60;
let wsUrl: string | undefined;

function findUrl(jsonUrl: string): void {
let options = { json: true };

request(jsonUrl, options, (error: any, res: any, body: any) => {
if (!error && res.statusCode == 200) {
wsUrl = body[0].webSocketDebuggerUrl;
async function findUrl(jsonUrl: string): Promise<void> {
try {
const response = await fetch(jsonUrl, { signal: AbortSignal.timeout(1000) });
if (!response.ok) {
return;
}
});

const body = await response.json();
wsUrl = body?.[0]?.webSocketDebuggerUrl;
} catch {
// Debugger endpoint may not be ready yet. Retry loop handles this.
}
}

export async function connectToWebsocket(reconnectTry: number = 1): Promise<WebSocket | undefined> {
Expand All @@ -25,7 +28,7 @@ export async function connectToWebsocket(reconnectTry: number = 1): Promise<WebS

while (!wsUrl && reconnectTry < limitOfReconnectTries) {
console.log(`Attaching debugger to '${jsonUrl}'...`);
findUrl(jsonUrl);
await findUrl(jsonUrl);
reconnectTry++;
await sleep(1000);
}
Expand Down
10 changes: 5 additions & 5 deletions test/end-to-end/src/test-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ export async function closeWorkbook(): Promise<void> {
}
}

export function addTestResult(testValues: any[], resultName: string, resultValue: any, expectedValue: any) {
export function addTestResult(testValues: any[], name: string, value: any, expectedValue: any) {
testValues.push({
expectedValue,
resultName,
resultValue,
name,
value,
});
}

export function addErrorResult(testValues: any[], errorMessage: string) {
testValues.push({
expectedValue: "no-error",
resultName: "test-error",
resultValue: errorMessage,
name: "test-error",
value: errorMessage,
});
}

Expand Down
6 changes: 3 additions & 3 deletions test/end-to-end/src/test-taskpane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ export async function readCFData(readCount: number): Promise<any[]> {
});
}

function addTestResult(resultName: string, resultValue: any) {
function addTestResult(name: string, value: any) {
const data = {
Name: resultName,
Value: resultValue,
name: name,
value: value,
};
testValues.push(data);
}
36 changes: 18 additions & 18 deletions test/end-to-end/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,47 +65,47 @@ describe("Test Excel Custom Functions", function () {
clearTimeout(timeoutId);
}

const errorResult = testValues.find((value: any) => value.resultName === "test-error");
const errorResult = testValues.find((value: any) => value.name === "test-error");
if (errorResult) {
assert.fail(`Taskpane reported error: ${errorResult.resultValue}`);
assert.fail(`Taskpane reported error: ${errorResult.value}`);
}

testValues = testValues.filter((value: any) => value.resultName !== "test-error");
testValues = testValues.filter((value: any) => value.name !== "test-error");
assert.ok(testValues.length > 0, "No test results received from Excel add-in");
console.log(`User Agent: ${testValues[0].Value}`);
console.log(`User Agent: ${testValues[0].value}`);
assert.strictEqual(testValues.length, 7);
});
it("ADD function should return expected value", async function () {
assert.strictEqual(testJsonData.functions.ADD.result, testValues[1].Value);
assert.strictEqual(testJsonData.functions.ADD.result, testValues[1].value);
});
it("CLOCK function should return expected value", async function () {
// Check that captured values are different to ensure the function is streaming
assert.notStrictEqual(testValues[2].Value, testValues[3].Value);
assert.notStrictEqual(testValues[2].value, testValues[3].value);
// Check if the returned string contains 'AM', 'PM', or 'GMT', indicating it's a time-stamp
assert.strictEqual(
testValues[2].Value.includes(testJsonData.functions.CLOCK.result.amString) ||
testValues[2].Value.includes(testJsonData.functions.CLOCK.result.pmString) ||
testValues[2].Value.includes(testJsonData.functions.CLOCK.result.timeZoneString),
testValues[2].value.includes(testJsonData.functions.CLOCK.result.amString) ||
testValues[2].value.includes(testJsonData.functions.CLOCK.result.pmString) ||
testValues[2].value.includes(testJsonData.functions.CLOCK.result.timeZoneString),
true,
"Found timestamp indicator string in first value '" + testValues[2].Value + "'"
"Found timestamp indicator string in first value '" + testValues[2].value + "'"
);
assert.strictEqual(
testValues[3].Value.includes(testJsonData.functions.CLOCK.result.amString) ||
testValues[3].Value.includes(testJsonData.functions.CLOCK.result.pmString) ||
testValues[3].Value.includes(testJsonData.functions.CLOCK.result.timeZoneString),
testValues[3].value.includes(testJsonData.functions.CLOCK.result.amString) ||
testValues[3].value.includes(testJsonData.functions.CLOCK.result.pmString) ||
testValues[3].value.includes(testJsonData.functions.CLOCK.result.timeZoneString),
true,
"Found timestamp indicator string in second value '" + testValues[3].Value + "'"
"Found timestamp indicator string in second value '" + testValues[3].value + "'"
);
});
it("INCREMENT function should return expected value", async function () {
// Check that captured values are different to ensure the function is streaming
assert.notStrictEqual(testValues[3].Value, testValues[4].Value);
assert.notStrictEqual(testValues[3].value, testValues[4].value);
// Check to see that both captured streaming values are divisible by 4
assert.strictEqual(0, testValues[4].Value % testJsonData.functions.INCREMENT.result);
assert.strictEqual(0, testValues[5].Value % testJsonData.functions.INCREMENT.result);
assert.strictEqual(0, testValues[4].value % testJsonData.functions.INCREMENT.result);
assert.strictEqual(0, testValues[5].value % testJsonData.functions.INCREMENT.result);
});
it("LOG function should return expected value", async function () {
assert.strictEqual(testJsonData.functions.LOG.result, testValues[6].Value);
assert.strictEqual(testJsonData.functions.LOG.result, testValues[6].value);
});
});
after("Teardown test environment", async function () {
Expand Down