Files
starface-outlook-sync-addin/node_modules/office-addin-usage-data/test/test.ts
T
Stefan Hacker 37ad745546 first commit
2026-04-03 09:38:48 +02:00

465 lines
20 KiB
TypeScript

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as appInsights from "applicationinsights";
import assert from "assert";
import fs from "fs";
import { beforeEach, describe, it } from "mocha";
import sinon from "sinon";
import os from "os";
import * as defaults from "../src/defaults";
import * as officeAddinUsageData from "../src/usageData";
import * as jsonData from "../src/usageDataSettings";
import * as log from "../src/log";
import { v4 as uuidv4 } from "uuid";
/* global console */
let addInUsageData: officeAddinUsageData.OfficeAddinUsageData;
const err = new Error(
`this error contains a file path:C:/${os.homedir()}/AppData/Roaming/npm/node_modules/alanced-match/index.js`
);
let usageData: string = "";
const mockDeviceID = uuidv4();
const usageDataObject: officeAddinUsageData.IUsageDataOptions = {
groupName: "office-addin-usage-data",
projectName: "office-addin-usage-data",
instrumentationKey: defaults.instrumentationKeyForOfficeAddinCLITools,
promptQuestion:
"-----------------------------------------\nDo you want to opt-in for usage data?[y/n]\n-----------------------------------------",
raisePrompt: false,
usageDataLevel: officeAddinUsageData.UsageDataLevel.on,
method: officeAddinUsageData.UsageDataReportingMethod.applicationInsights,
isForTesting: true,
deviceID: mockDeviceID,
};
describe("Test office-addin-usage data-package", function () {
this.beforeAll(function () {
try {
if (fs.existsSync(defaults.usageDataJsonFilePath)) {
const fileContent = fs.readFileSync(defaults.usageDataJsonFilePath, "utf8");
if (fileContent) {
usageData = JSON.parse(fileContent) || "";
}
}
} catch {
// do nothing
}
});
this.afterAll(function () {
if (fs.existsSync(defaults.usageDataJsonFilePath) && usageData !== undefined) {
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(usageData, null, 2));
} else if (fs.existsSync(defaults.usageDataJsonFilePath)) {
fs.unlinkSync(defaults.usageDataJsonFilePath);
}
});
beforeEach(function () {
if (fs.existsSync(defaults.usageDataJsonFilePath)) {
fs.unlinkSync(defaults.usageDataJsonFilePath);
}
addInUsageData = new officeAddinUsageData.OfficeAddinUsageData(usageDataObject);
addInUsageData.setUsageDataOn();
});
describe("Test constructor with minimal options", () => {
it("Should successfully construct an OfficeAddInUsageData instance", () => {
assert.doesNotThrow(() => {
new officeAddinUsageData.OfficeAddinUsageData({
isForTesting: true,
usageDataLevel: officeAddinUsageData.UsageDataLevel.off,
projectName: "office-addin-usage-data",
groupName: "TestGroupName",
instrumentationKey: defaults.instrumentationKeyForOfficeAddinCLITools,
});
});
});
});
describe("Test reportEvent method", () => {
it("should track event of object passed in with a project name", () => {
const testEvent = {
Test1: [true, 100],
ScriptType: ["JavaScript", 1],
};
addInUsageData.reportEvent("office-addin-usage-data", testEvent);
assert.equal(addInUsageData.getEventsSent(), 1);
});
});
describe("Test reportError method", () => {
it("should send usage data exception", () => {
addInUsageData.reportError("ReportErrorCheck", err);
assert.equal(addInUsageData.getExceptionsSent(), 1);
});
});
describe("Test promptForUsageData method", () => {
it("Should return 'true' because usageDataJsonFilePath doesn't exist", () => {
// delete officeAddinUsageData.json
if (fs.existsSync(defaults.usageDataJsonFilePath)) {
fs.unlinkSync(defaults.usageDataJsonFilePath);
}
assert.equal(jsonData.needToPromptForUsageData(usageDataObject.groupName as string), true);
});
});
describe("Test promptForUsageData method", () => {
it("Should return 'false' because usageDataJsonFilePath exists and groupName exists in file", () => {
jsonData.writeUsageDataJsonData(
usageDataObject.groupName as string,
usageDataObject.usageDataLevel as officeAddinUsageData.UsageDataLevel
);
assert.equal(jsonData.needToPromptForUsageData(usageDataObject.groupName as string), false);
});
});
describe("Test promptForUsageData method", () => {
it("Should return 'true' because usageDataJsonFilePath exists but groupName doesn't exist on file", () => {
jsonData.writeUsageDataJsonData(
usageDataObject.groupName as string,
usageDataObject.usageDataLevel as officeAddinUsageData.UsageDataLevel
);
assert.equal(jsonData.needToPromptForUsageData("test group name"), true);
});
});
describe("Test usageDataOptIn method", () => {
it("Should write out file with groupName set to true to usageDataJsonFilePath", () => {
addInUsageData.usageDataOptIn(usageDataObject.isForTesting, "y");
const jsonTelemtryData = jsonData.readUsageDataJsonData();
assert.equal(
jsonTelemtryData.usageDataInstances[usageDataObject.groupName as string].usageDataLevel,
usageDataObject.usageDataLevel
);
});
});
describe("Test setUsageDataOff method", () => {
it("should change samplingPercentage to 100, turns usage data on", () => {
addInUsageData.setUsageDataOn();
addInUsageData.setUsageDataOff();
assert.equal(addInUsageData.isUsageDataOn(), false);
});
});
describe("Test setUsageDataOn method", () => {
it("should change samplingPercentage to 100, turns usage data on", () => {
addInUsageData.setUsageDataOff();
addInUsageData.setUsageDataOn();
assert.equal(appInsights.defaultClient.config.samplingPercentage, 100);
});
});
describe("Test isUsageDataOn method", () => {
it("should return true if samplingPercentage is on(100)", () => {
appInsights.defaultClient.config.samplingPercentage = 100;
assert.equal(addInUsageData.isUsageDataOn(), true);
});
it("should return false if samplingPercentage is off(0)", () => {
appInsights.defaultClient.config.samplingPercentage = 0;
assert.equal(addInUsageData.isUsageDataOn(), false);
});
});
describe("Test getUsageDataKey method", () => {
it("should return usage data key", () => {
assert.equal(addInUsageData.getUsageDataKey(), "de0d9e7c-1f46-4552-bc21-4e43e489a015");
});
});
describe("Test getEventsSent method", () => {
it("should return amount of events successfully sent", () => {
addInUsageData.setUsageDataOff();
const testEvent = {
Test1: [true, 100],
ScriptType: ["Java", 1],
};
addInUsageData.reportEvent("office-addin-usage-data", testEvent);
assert.equal(addInUsageData.getEventsSent(), 1);
});
});
describe("Test getExceptionsSent method", () => {
it("should return amount of exceptions successfully sent ", () => {
addInUsageData.setUsageDataOff();
addInUsageData.reportError("TestData", err);
assert.equal(addInUsageData.getExceptionsSent(), 1);
});
});
describe("Test UsageDataLevel method", () => {
it("should return the usage data level of the object", () => {
assert.equal("on", addInUsageData.getUsageDataLevel());
});
});
describe("Test maskFilePaths method", () => {
it("should parse error file paths with slashs", () => {
addInUsageData.setUsageDataOff();
const error = new Error(
`this error contains a file path: C:/${os.homedir()}/AppData/Roaming/npm/node_modules/alanced-match/index.js`
);
const compareError = new Error();
compareError.name = "Error";
compareError.message = "this error contains a file path: <filepath>";
// may throw error if change any part of the top of the test file
compareError.stack = "this error contains a file path: <filepath>";
addInUsageData.maskFilePaths(error);
assert.strictEqual(compareError.name, error.name);
assert.strictEqual(compareError.message, error.message);
assert.strictEqual((error.stack ?? "").includes(compareError.stack), true);
});
it("should parse error file paths with backslashs", () => {
addInUsageData.setUsageDataOff();
const errWithBackslash = new Error(
`this error contains a file path: C:\\Users\\admin\\AppData\\Local\\Temp\\excel file .xlsx`
);
const compareErrorWithBackslash = new Error();
compareErrorWithBackslash.message = "this error contains a file path: <filepath>";
compareErrorWithBackslash.stack = "this error contains a file path: <filepath>";
addInUsageData.maskFilePaths(errWithBackslash);
assert.strictEqual(compareErrorWithBackslash.message, errWithBackslash.message);
assert.strictEqual((errWithBackslash.stack ?? "").includes(compareErrorWithBackslash.stack), true);
});
it("should parse error file paths with slashs and backslashs", () => {
addInUsageData.setUsageDataOff();
const error = new Error(
`this error contains a file path: C:\\Users/\\admin\\AppData\\Local//Temp\\excel_file .xlsx`
);
const compareError = new Error();
compareError.message = "this error contains a file path: <filepath>";
compareError.stack = "this error contains a file path: <filepath>";
addInUsageData.maskFilePaths(error);
assert.strictEqual(compareError.message, error.message);
assert.strictEqual((error.stack ?? "").includes(compareError.stack), true);
});
it("should handle relative paths", () => {
addInUsageData.setUsageDataOff();
const error = new Error(`file path: /this is a file path/path/manifestName.xml`);
const compareError = new Error();
compareError.message = "file path: <filepath>";
compareError.stack = "file path: <filepath>";
addInUsageData.maskFilePaths(error);
assert.strictEqual(compareError.message, error.message);
assert.strictEqual((error.stack ?? "").includes(compareError.stack), true);
});
});
describe("Test modifySetting method", () => {
it("should modify or create specific property to new value", () => {
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel }, deviceID: mockDeviceID },
};
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(jsonObject));
const usageDataJsonData = jsonData.readUsageDataJsonData();
const testPropertyName = "testProperty";
usageDataJsonData.usageDataInstances[usageDataObject.groupName as string][testPropertyName] = 0;
jsonData.modifyUsageDataJsonData(usageDataObject.groupName as string, testPropertyName, 0);
assert.equal(JSON.stringify(usageDataJsonData), JSON.stringify(jsonData.readUsageDataJsonData()));
});
});
describe("Test readUsageDataJsonData method", () => {
it("should read and return parsed object object from usage data", () => {
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel } },
deviceID: mockDeviceID,
};
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(jsonObject));
assert.equal(JSON.stringify(jsonObject), JSON.stringify(jsonData.readUsageDataJsonData()));
});
});
describe("Test readUsageDataLevel method", () => {
it("should read and return object's usage data level from file", () => {
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel } },
deviceID: mockDeviceID,
};
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(jsonObject));
assert.equal(
officeAddinUsageData.UsageDataLevel.on,
jsonData.readUsageDataLevel(usageDataObject.groupName as string)
);
});
});
describe("Test readUsageDataObjectProperty method", () => {
it("should read and return parsed object object from usage data", () => {
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel } },
deviceID: mockDeviceID,
};
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(jsonObject));
assert.equal(
officeAddinUsageData.UsageDataLevel.on,
jsonData.readUsageDataObjectProperty(usageDataObject.groupName as string, "usageDataLevel")
);
});
});
describe("Test writeUsageDataJsonData method", () => {
it("should write to already existing file", () => {
fs.writeFileSync(defaults.usageDataJsonFilePath, "");
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel }, deviceID: mockDeviceID },
};
jsonData.writeUsageDataJsonData(
usageDataObject.groupName as string,
usageDataObject.usageDataLevel as officeAddinUsageData.UsageDataLevel
);
assert.equal(
JSON.stringify(jsonObject["usageDataInstances"][usageDataObject.groupName as string], null, 2),
JSON.stringify(
JSON.parse(fs.readFileSync(defaults.usageDataJsonFilePath, "utf8"))["usageDataInstances"][
usageDataObject.groupName as string
],
null,
2
)
);
});
});
describe("Test writeUsageDataJsonData method", () => {
it("should create new existing file with correct format", () => {
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel }, deviceID: mockDeviceID },
};
jsonData.writeUsageDataJsonData(
usageDataObject.groupName as string,
usageDataObject.usageDataLevel as officeAddinUsageData.UsageDataLevel
);
assert.equal(
JSON.stringify(jsonObject["usageDataInstances"][usageDataObject.groupName as string], null, 2),
JSON.stringify(
JSON.parse(fs.readFileSync(defaults.usageDataJsonFilePath, "utf8"))["usageDataInstances"][
usageDataObject.groupName as string
],
null,
2
)
);
});
});
describe("Test groupNameExists method", () => {
it("should check if groupName exists", () => {
fs.writeFileSync(defaults.usageDataJsonFilePath, "test");
const usageDataLevel = usageDataObject.usageDataLevel;
let jsonObject = {};
jsonObject[usageDataObject.groupName as string] = usageDataObject.usageDataLevel;
jsonObject = { usageDataInstances: jsonData };
jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel }, deviceID: mockDeviceID },
};
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(jsonObject));
assert.equal(true, jsonData.groupNameExists("office-addin-usage-data"));
});
});
describe("Test readUsageDataSettings method", () => {
it("should read and return parsed usage data object group settings", () => {
const usageDataLevel = usageDataObject.usageDataLevel;
const jsonObject = {
usageDataInstances: { [usageDataObject.groupName as string]: { usageDataLevel } },
deviceID: mockDeviceID,
};
fs.writeFileSync(defaults.usageDataJsonFilePath, JSON.stringify(jsonObject));
assert.equal(
JSON.stringify(jsonObject.usageDataInstances[usageDataObject.groupName as string]),
JSON.stringify(jsonData.readUsageDataSettings(usageDataObject.groupName))
);
});
});
describe("Test reportSuccess", () => {
it("should send success events successfully", () => {
addInUsageData.reportSuccess("testMethod-reportSuccess", { TestVal: 42, OtherTestVal: "testing" });
assert.equal(addInUsageData.getEventsSent(), 1);
});
it("should send success events successfully, even when there's no additional data", () => {
addInUsageData.reportSuccess("testMethod-reportSuccess");
assert.equal(addInUsageData.getEventsSent(), 1);
});
});
describe("Test reportExpectedException", () => {
it("should send successful fail events successfully", () => {
addInUsageData.reportExpectedException("testMethod-reportExpectedException", new Error("Test"), {
TestVal: 42,
OtherTestVal: "testing",
});
assert.equal(addInUsageData.getEventsSent(), 1);
});
it("should send successful fail events successfully, even when there's no additional data", () => {
addInUsageData.reportExpectedException("testMethod-reportExpectedException", new Error("Test"));
assert.equal(addInUsageData.getEventsSent(), 1);
});
});
describe("Test sendUsageDataEvent", () => {
it("should send events successfully", () => {
addInUsageData.sendUsageDataEvent({ TestVal: 42, OtherTestVal: "testing" });
assert.equal(addInUsageData.getEventsSent(), 1);
});
it("should send events successfully, even when there's no data", () => {
addInUsageData.sendUsageDataEvent();
assert.equal(addInUsageData.getEventsSent(), 1);
});
});
describe("Test reportException", () => {
it("should send exceptions successfully", () => {
addInUsageData.reportException("testMethod-reportException", new Error("Test"), {
TestVal: 42,
OtherTestVal: "testing",
});
assert.equal(addInUsageData.getExceptionsSent(), 1);
});
it("should send exceptions successfully, even when there's no data", () => {
addInUsageData.reportException("testMethod-reportException", new Error("Test"));
assert.equal(addInUsageData.getExceptionsSent(), 1);
});
});
describe("log.ts", function () {
describe("logErrorMessage()", function () {
it("called with Error", function () {
const spyConsoleError = sinon.spy(console, "error");
const spyConsoleLog = sinon.spy(console, "log");
const message = "This is an error.";
const error = new Error(message);
log.logErrorMessage(error);
assert.ok(spyConsoleError.calledOnceWith(`Error: ${message}`));
assert.ok(spyConsoleLog.notCalled);
spyConsoleError.restore();
spyConsoleLog.restore();
});
it("called with string", function () {
const spyConsoleError = sinon.spy(console, "error");
const spyConsoleLog = sinon.spy(console, "log");
const message = "This is the error message.";
log.logErrorMessage(message);
assert.ok(spyConsoleError.calledOnceWith(`Error: ${message}`));
assert.ok(spyConsoleLog.notCalled);
spyConsoleError.restore();
spyConsoleLog.restore();
});
});
});
});