AleksandrRogov / DynamicsWebApi

DynamicsWebApi is a Microsoft Dataverse Web API helper library for JavaScript & TypeScript
MIT License
268 stars 58 forks source link

Tests failures ts-jest / export {} issue. #161

Closed omnisip closed 10 months ago

omnisip commented 11 months ago

DynamicsWebApi version 2.1.1

We have tried every thing we know how with ts-jest and tsconfig.json including esModuleInterop, among others, and dynamics-web-api is the only import that has the issue. Issue reproduces even in an empty test files and all it does is instantiate the DynamicsWebApi class.

FAIL PriceListItemGeneration/Components/Pricing/PricingPanel.spec.tsx ● Test suite failed to run

Jest encountered an unexpected token

Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

By default "node_modules" folder is ignored by transformers.

Here's what you can do:
 • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
 • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
 • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
 • If you need a custom transformation specify a "transform" option in your config.
 • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation

Details:

/home/dan/Git/BBWS.BearFlight.Monorepo/BBWS.FieldService.PCF/src/PriceListItemGeneration/node_modules/dynamics-web-api/dist/browser/esm/dynamics-web-api.js:2527
export {
^^^^^^

SyntaxError: Unexpected token 'export'

   8 | import { Stack } from '@fluentui/react/lib/Stack';
   9 | import { Label } from '@fluentui/react/lib/Label';
> 10 | import { DynamicsWebApi } from 'dynamics-web-api';
     | ^
  11 | import { IDynamicsWebApi } from '../../Repository/Interfaces/IDynamicsWebApi';
  12 | import { CreateFromPriceListModal } from '../CreateFromPriceList/CreateFromPriceListModal';
  13 | import { DumpsterGlobalsModal } from '../DumpsterGlobals/DumpsterGlobalsModal';

  at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1496:14)
  at Object.require (PriceListItemGeneration/Components/Pricing/PricingPanel.tsx:10:1)
  at Object.<anonymous> (PriceListItemGeneration/Components/Pricing/PricingPanel.spec.tsx:4:1)
AleksandrRogov commented 11 months ago

hi @omnisip , Are you testing in a browser or node? Are you testing a compiled bundle or a source code directly?

omnisip commented 10 months ago

Node. source code directly. -- whatever we get from npm install.

omnisip commented 10 months ago

We are using JSDom. But it's in our test suite.

AleksandrRogov commented 10 months ago

hi @omnisip , If you are testing in Node, then it is loading a wrong DynamicsWebApi bundle, that's what it says in the error details that you mentioned:

/home/dan/Git/BBWS.BearFlight.Monorepo/BBWS.FieldService.PCF/src/PriceListItemGeneration/node_modules/dynamics-web-api/dist/browser/esm/dynamics-web-api.js:2527

Note here, that it is loading browser/esm, instead of just esm. browser/esm will only work in a browser, not Node.

omnisip commented 10 months ago

How do I fix that? It happens whenever I use jsdom. Also -- what's the difference between the bundles?

AleksandrRogov commented 10 months ago

The main difference between the bundles is that the one is built for Node.js and uses all Node.js features that are not available in a browser, such as http and https modules. In browser/esm, those modules are replaced with XmlHttpRequest, because http and https exist strictly in Node. There are other differences, but this is the main one.

Is your app a CommonJs module or ES module? If you could share the package.json and tsconfig.json (if it's in TypeScript), it will help a lot.

SerhiiYatsenko commented 10 months ago

Hi, @AleksandrRogov the package.json and tsconfig.json: package.json tsconfig.json

AleksandrRogov commented 10 months ago

@omnisip , @SerhiiYatsenko can you give me your node version please?

The only difference I see between your tsconfig and mine in the PCF controls is that I set "module" to ES6 and "moduleResolution" to "node". Which makes sense because I dropped support for ES5 in v2. I just feel like jest does not understand that DynamicsWebApi is ES6 module and export keyword does not exist in ES5. I do also exclude "node_modules" specifically, don't remember why, but it should not be a cause of an issue.

{
    "extends": "./node_modules/pcf-scripts/tsconfig_base.json",
    "compilerOptions": {
        "typeRoots": ["node_modules/@types", "./types/**/*"],
        "module": "ES6",
        "moduleResolution": "node"
    },
    "exclude": ["node_modules"]
}

Can you try including "module" and "moduleResolution" in your tsconfig?

And I haven't used JSDom before, but it looks like that it brings support for browser features to Node, so including browser/esm should be ok, otherwise it would throw an error somewhere else. The main issue is that jest does not recognize "export" keyword.

SerhiiYatsenko commented 10 months ago

Node version is v18.16.1 Screenshot_169

omnisip commented 10 months ago

Any luck? We're still stuck on this.

This is the only dependency with these issues.

AleksandrRogov commented 10 months ago

@omnisip as I mentioned before, the issue happens because jest does not "understand" export keyword. The library is ES6 module but jest is most likely expecting ES5 or even CommonJS module.

Did some research on jest and it looks like it does not really have a good support for ESM. Can you try one of the suggestions I found for another library that had the same problem with jest? Basically, just add a module resolution to your jest.config.js, like so:

# jest.config.js
module.exports {
  moduleNameMapper: {
    // Workaround for Jest having bad ESM support
    'dynamics-web-api': require.resolve('dynamics-web-api'),

You can find more info here (that's where I found this suggestion): https://github.com/uuidjs/uuid/issues/451#issuecomment-1112328417

AleksandrRogov commented 10 months ago

Here are even more details: https://github.com/uuidjs/uuid/pull/616#issue-1130750840 And here: https://github.com/microsoft/accessibility-insights-web/pull/5421#issuecomment-1109168149

omnisip commented 10 months ago

I think that worked, but created a new issue:

console.error
  Error: Xrm Context is not available. In most cases, it can be resolved by adding a reference to a ClientGlobalContext.js.aspx. Please refer to MSDN documentation for more details.
      at Function.getXrmContext (C:\Users\DanWeber\WebstormProjects\BBWS.BearFlight.Monorepo\BBWS.FieldService.PCF\src\PriceListItemGeneration\node_modules\dynamics-web-api\dist\cjs\dynamics-web-api.js:187:15)
      at Function.getClientUrl (C:\Users\DanWeber\WebstormProjects\BBWS.BearFlight.Monorepo\BBWS.FieldService.PCF\src\PriceListItemGeneration\node_modules\dynamics-web-api\dist\cjs\dynamics-web-api.js:195:34)
      at getApiUrl (C:\Users\DanWeber\WebstormProjects\BBWS.BearFlight.Monorepo\BBWS.FieldService.PCF\src\PriceListItemGeneration\node_modules\dynamics-web-api\dist\cjs\dynamics-web-api.js:848:27)
      at mergeApiConfigs (C:\Users\DanWeber\WebstormProjects\BBWS.BearFlight.Monorepo\BBWS.FieldService.PCF\src\PriceListItemGeneration\node_modules\dynamics-web-api\dist\cjs\dynamics-web-api.js:862:27)
      at Function.merge (C:\Users\DanWeber\WebstormProjects\BBWS.BearFlight.Monorepo\BBWS.FieldService.PCF\src\PriceListItemGeneration\node_modules\dynamics-web-api\dist\cjs\dynamics-web-api.js:870:5)
      at new DynamicsWebApi (C:\Users\DanWeber\WebstormProjects\BBWS.BearFlight.Monorepo\BBWS.FieldService.PCF\src\PriceListItemGeneration\node_modules\dynamics-web-api\dist\cjs\dynamics-web-api.js:2532:26)
AleksandrRogov commented 10 months ago

@omnisip you will need to mock Xrm Context that Dynamics provides. The library tries to access it so it can get the organization's server url.

It will be similar to what I do here: https://github.com/AleksandrRogov/DynamicsWebApi/blob/5c0ec4c590bb456650ba35567c7db2214e3edb10/tests/stubs.js#L6C8-L6C8

AleksandrRogov commented 10 months ago

@omnisip Just to clarify: only that getClientUrl needs to be mocked. No need to mock the whole Xrm object.

AleksandrRogov commented 10 months ago

Closing this, as I assume it is resolved. If you have any more questions feel free to post in the same issue. Thanks!