OfficeDev / Office-Addin-Scripts

A set of scripts and packages that are consumed in Office add-ins projects.
MIT License
155 stars 98 forks source link

Unable to use OfficeMockObject in jsdom test environment #653

Open mspiess opened 2 years ago

mspiess commented 2 years ago

Prerequisites

Expected behavior

The jest test runner runs the tests with jsdom environment without error while making use of "office-addin-mock".

Current behavior

The test fails to run because "office-addin-mock" seems to expect a Node environment (see Failure Logs below).

Steps to Reproduce

Run the following test file:

/**
 * @jest-environment jsdom
 */

import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { OfficeMockObject } from "office-addin-mock";
import App from "./App";

/* global global, it, expect */

const officeMock = new OfficeMockObject({});
// @ts-ignore
global.Office = officeMock;

it("should render message while fetching contact(s)", () => {
  render(<App title={"Some Title"} isOfficeInitialized={true} />);

  expect(screen.getByRole("header")).toHaveTextContent("Whatever");
});

Context

Packages installed in addition to the office-addin-react starter:

jest.config.js:

const config = {
  preset: "ts-jest",
  testEnvironment: "node",
};
module.exports = config;

Test script: jest

Failure Logs

● Test suite failed to run

    The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string.
    Consider using the "node" test environment.

    TypeError: this._handle.unref is not a function

       6 | import { render, screen } from "@testing-library/react";
       7 | import "@testing-library/jest-dom";
    >  8 | import { OfficeMockObject } from "office-addin-mock";
         | ^
       9 | import App from "./App";
      10 |
      11 | /* global global, it, expect */

      at new OfficeAddinUsageData (node_modules/office-addin-usage-data/src/usageData.ts:126:13)
      at Object.<anonymous> (node_modules/office-addin-manifest/src/defaults.ts:7:64)
      at Object.<anonymous> (node_modules/office-addin-manifest/src/manifestOperations.ts:4:1)
      at Object.<anonymous> (node_modules/office-addin-manifest/src/main.ts:7:1)
      at Object.<anonymous> (node_modules/office-addin-mock/src/officeMockObject.ts:1:1)
      at Object.<anonymous> (node_modules/office-addin-mock/src/main.ts:4:1)
      at Object.<anonymous> (src/taskpane/components/minimal.test.tsx:8:1)
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:317:13)
      at runJest (node_modules/@jest/core/build/runJest.js:407:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:339:7)
      at runCLI (node_modules/@jest/core/build/cli/index.js:190:3)
igor-ribeiiro commented 2 years ago

I'm not sure if this is a problem with the office-addin-mock library itself or just some configuration you are missing. Searching online, I found Consider using the "jsdom" test environment, could you please try it?

mspiess commented 2 years ago

TL;DR: turning off usage-data collection with the following command circumvents this issue:

npx office-addin-usage-data off

Hi @igor-ribeiiro,

I don't think it is a configuration issue. Putting the comment

/**
 * @jest-environment jsdom
 */

at the top of a test file has the same effect, as configuring the testEnvironment in jest.config.js as suggested on the page you linked. Besides, the error message suggests to use the node environment, so I am quite confident that the test is actually executed in the jsdom test environment. I created a repository with a minimal example for reproducing this issue: https://github.com/mspiess/office-add-in-min-example I still think that the issue is the inability of the office-addin-mock library to run in a browser-like environment, as stated in the title of this issue.

I did some further research towards the cause of this error. I was able to get a more complete stacktrace by removing the superfluous error-wrapping in line 126 in usageData.ts:

throw new Error(err);

I replaced it with:

throw err;

This revealed two more lines in the stacktrace:

at AutoCollectPerformance.Object.<anonymous>.AutoCollectPerformance.enable (node_modules/applicationinsights/AutoCollection/Performance.ts:81:30)
at Function.start (node_modules/applicationinsights/applicationinsights.ts:118:22)

Looking at the code, this._handle.unref is indeed called there, and that function does not seem to exist in the jsdom test environment. Realizing that this code is related to the collection of usage data I tried to turn usage data collection off with:

npx office-addin-usage-data off

When running the test again afterwards, I received different errors which I was able to resolve by tuning the jest config. For anybody stumbling upon this in the future, you can see the necessary changes in the "fix" branch of my minimal-example repository.


I guess you can close this issue, but I propose following options to prevent people from running into this issue in the future:

igor-ribeiiro commented 2 years ago

TL;DR: turning off usage-data collection with the following command circumvents this issue:

npx office-addin-usage-data off

Hi @igor-ribeiiro,

I don't think it is a configuration issue. Putting the comment

/**
 * @jest-environment jsdom
 */

at the top of a test file has the same effect, as configuring the testEnvironment in jest.config.js as suggested on the page you linked. Besides, the error message suggests to use the node environment, so I am quite confident that the test is actually executed in the jsdom test environment. I created a repository with a minimal example for reproducing this issue: https://github.com/mspiess/office-add-in-min-example I still think that the issue is the inability of the office-addin-mock library to run in a browser-like environment, as stated in the title of this issue.

I did some further research towards the cause of this error. I was able to get a more complete stacktrace by removing the superfluous error-wrapping in line 126 in usageData.ts:

throw new Error(err);

I replaced it with:

throw err;

This revealed two more lines in the stacktrace:

at AutoCollectPerformance.Object.<anonymous>.AutoCollectPerformance.enable (node_modules/applicationinsights/AutoCollection/Performance.ts:81:30)
at Function.start (node_modules/applicationinsights/applicationinsights.ts:118:22)

Looking at the code, this._handle.unref is indeed called there, and that function does not seem to exist in the jsdom test environment. Realizing that this code is related to the collection of usage data I tried to turn usage data collection off with:

npx office-addin-usage-data off

When running the test again afterwards, I received different errors which I was able to resolve by tuning the jest config. For anybody stumbling upon this in the future, you can see the necessary changes in the "fix" branch of my minimal-example repository.

I guess you can close this issue, but I propose following options to prevent people from running into this issue in the future:

  • disable data collection in the mock (btw ...seriously?) by default
  • somehow make it work in the js-dom test environment

We will keep the issue open until this is fixed. Thanks for providing a workaround for now, hopefully, it will work for others until fixed.

carlhauck commented 1 year ago

Any updates on a fix for this?

Unfortunately, @mspiess' workaround didn't work for me.

I'm able to use office-addin-mock with jest v27, but not with v28 or v29 (and those newer versions of jest are necessary for other upgrades we'd like to make).

millerds commented 1 year ago

@carlhauck it sounds like your problem is different. Can you enter a new issue with the errors you get when using v28 or v29?

rosergeev commented 12 months ago

I have upgraded yesterday from jest 27 to 29 with similar results:

` Details:

C:\Projects\ima-office\src\ImaOffice365.Common.Web\node_modules\.pnpm\uuid@8.3.2\node_modules\uuid\dist\esm-browser\index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
                                                                                  ^^^^^^

SyntaxError: Unexpected token 'export'

   9 | import { RoutePaths } from "../../../routing";
  10 | import * as ReactRouterDom from "react-router-dom";
> 11 | import { OfficeMockObject } from "office-addin-mock";
     | ^
  12 | import "@testing-library/jest-dom";
  13 |
  14 | jest.mock("../../../services/CoordinatorService");

  at Runtime.createScriptFromCode (node_modules/.pnpm/jest-runtime@29.6.4/node_modules/jest-runtime/build/index.js:1505:14)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-usage-data@1.6.7/node_modules/office-addin-usage-data/src/usageDataSettings.ts:7:1)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-usage-data@1.6.7/node_modules/office-addin-usage-data/src/usageData.ts:6:1)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-usage-data@1.6.7/node_modules/office-addin-usage-data/src/main.ts:6:1)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-manifest@1.12.7/node_modules/office-addin-manifest/src/addInTypes.ts:4:1)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-manifest@1.12.7/node_modules/office-addin-manifest/src/main.ts:4:1)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-mock@2.3.14/node_modules/office-addin-mock/src/officeMockObject.ts:1:1)
  at Object.<anonymous> (node_modules/.pnpm/office-addin-mock@2.3.14/node_modules/office-addin-mock/src/main.ts:4:1)
  at Object.<anonymous> (src/tests/components/imaDocument/documentTypeSelection.test.tsx:11:1)`

And I found out that latest version of Jest avtivates ESM mode by looking type property at the package.json file (Jest docs ESM ) Here it is a hint for this at stackoverflow (stackoverflow) As I understand neither uuid v8.3.2 nor v9.0.0 has this property (type: "module")

jieyuy commented 6 months ago

We also encountered the similar issue as above. V29 is not compatible. And npx office-addin-usage-data off doesn't work unfortunately.

GrumpyAL commented 3 months ago

I was also able to reproduce this issue with jest v29. I was able to get a fix working (Thanks @mspiess).

I'm running a JS project and not typescript so I modified the Jest config changes a little bit and only seemed to need:

    "transformIgnorePatterns": [
      "/node_modules/(?!(uuid)/)"
    ]
  }

To get it working.

KristianLonergan commented 2 months ago

Any updates on this ? I have tried the workarounds suggested in the comments however I still hit this issue of:

C:\Users\k.l\Documents\repositories\lwb360-drafting\word\add-in\node_modules\office-addin-usage-data\node_modules\uuid\dist\esm-browser\index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
                                                                                      ^^^^^^

    SyntaxError: Unexpected token 'export'

    > 1 | import { OfficeMockObject } from 'office-addin-mock';
        | ^
      2 | import { ObjectData } from 'office-addin-mock/lib/objectData';

I am using jest v29 and "office-addin-mock": "^2.4.3",