Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit testing typescript SPFx web part (react) that uses pnpjs #1425

Closed
1 of 4 tasks
nbelyh opened this issue Oct 31, 2020 · 12 comments
Closed
1 of 4 tasks

Unit testing typescript SPFx web part (react) that uses pnpjs #1425

nbelyh opened this issue Oct 31, 2020 · 12 comments

Comments

@nbelyh
Copy link

nbelyh commented Oct 31, 2020

Category

  • Enhancement
  • Bug
  • Question
  • Documentation gap/issue

Version

Please specify what version of the library you are using: [2.0.11]

Please specify what version(s) of SharePoint you are targeting: [SharePoint Online]

Question

How do you unit test SPFx web part, written in typescript (react), that uses pnpjs to communicate with SharePoint?
Is there a stock configuration or framework?

I have already tried these tutorials they all don't seem to work with current version SPFx if you use both typescript and pnpjs:
https://www.eliostruyf.com/sharepoint-framework-unit-tests-with-jest/
https://blog.velingeorgiev.com/unit-test-your-sharepoint-framework-solution-with-jest/
https://www.c-sharpcorner.com/article/spfx-unit-test-with-jest-and-enzyme/
https://github.com/sebastianrogers/pnpjs-jest
https://github.com/estruyf/spfx-testing-jest

Related issue where you can find a typical example of the problems I'm currently facing:
#1058

    XXXX/node_modules/@pnp/sp/fields/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import "./web";

    > 2 | import { FieldTypes } from "@pnp/sp/fields";
        | ^
    SyntaxError: Unexpected string

The issue seems to be that: jest does not support modules natively (it supports them in the very last release, but that's for node 13, for which other things fail). So now transforms are used, and you should be able to overcome that with babel plugin, that can load the modules and remove all those "import" and "export" stuff. Now, babel does not play well with typescript so in jest there is another plugin ts-jest that does typescript, as of my current understanding. But installing that creates version incompatibilities and erros like cwd is not a function...

So, well, the whole thing looks like a swarm of snakes 😄

Could someone share a configuration that supports unit testing, for a SPFx web part 1.11 written in typescript, that uses pnpjs to communicate with SharePoint? I mean, I'm flexible and if JEST just does not want to work, screw it, I could use whatever 😄
Maybe I'm missing something simple? Or is nobody unit testing SPFx web parts?

Please note that if you don't use pnp (do not import it), the tutorials above work. So I believe this issue is related to PNP, and hopefully won't be closed like the referenced one... I'm really interested in an example where you do import pnp, and use typescript (react) to build your web part.

So far my best shot was this setup:

  • jest
  • ts-jest (because the project is in typescript)
  • babel-jest (because pnp uses modules inside compiled .js files in node_modules)
  • identity-obj-proxy (to overcome the issue with scss modules)

Still no luck though. Any recommendation is appreciated 😄

@nbelyh nbelyh changed the title Unit testing SPFx web part (react) that uses pnpjs Unit testing typescript SPFx web part (react) that uses pnpjs Oct 31, 2020
@nbelyh
Copy link
Author

nbelyh commented Nov 1, 2020

Found a somewhat related user voice topic... probably this should go to the same bucket:
https://sharepoint.uservoice.com/forums/329220-sharepoint-dev-platform/suggestions/34073197-web-parts-allow-them-to-be-unit-testable

@patrick-rodgers
Copy link
Member

@andrewconnell just released a new blog post about setting up jest that might help you out.

As discussed in the other thread, the issue is with node and jest's ability to use es modules, which is what we use to enable the selective imports. We do publish commonjs modules for use specifically in node environments. But that's not what you want in the browser. We tried to package it all together, but that caused a lot of issues for folks.

Beyond that we can't offer much support, perhaps someone from the community has additional ideas as well. I get you don't want this issue closed - but the issue isn't with PnPjs as much as it is with the module support.

@nbelyh
Copy link
Author

nbelyh commented Nov 3, 2020

Thank you @patrick-rodgers

With the blog post unfortunately it's the same problem, here is the reated issues:
Voitanos/jest-preset-spfx-react16#1
Voitanos/jest-preset-spfx-react16#7

Seems that I have moderate progress with babel though, just to share here maybe for others who may run into the same thing. Relevant configuration fragments are below.

  • babel-plugin-transform-es2015-modules-commonjs (to fix ES modules in compiled code). Also had to add pnp to "transformIgnorePatterns" so that babel does process it.
  • babel-plugin-transform-amd-to-commonjs (to fix en-us.js that is using AMD for babel for strings - what a mess)

project json:

    "babel-core": "^6.26.3",
    "babel-jest": "^25.0.0",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
    "babel-plugin-transform-amd-to-commonjs": "^1.4.0",
    "jest": "^25.0.0",
    "ts-jest": "^25.0.0",

jest config:

  "jest": {
    "transform": {
      "^.+\\.(ts|tsx)$": "ts-jest",
      "^.+\\.js$": "babel-jest"
    },
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "json"
    ],
    "moduleDirectories": [
      "node_modules",
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(@pnp)/)"
    ],

babel config:

{
  "presets": [[ "@babel/preset-env", { "modules": false, "targets": { "node": "current" }}]],
  "plugins": ["transform-es2015-modules-commonjs", "transform-amd-to-commonjs"]
}

tsconfig:

   "module": "commonjs",
   "types": [
      .......
      "jest"
   ],

@patrick-rodgers
Copy link
Member

There are some more ideas in this thread. One of the big issue in play is that SPFx is never intended to run in node.

I will say as you work on this if there is something we can do within the library to assist (that makes sense) we are open to it.

@nbelyh
Copy link
Author

nbelyh commented Nov 3, 2020

babel + transform-amd-to-commonjs plugin seems to solve the issue with the strings quite nicely. Will go through that thread.
I will check if I can post this config with this babel thing as a separate repository.

@andrewconnell
Copy link

@patrick-rodgers said:

One of the big issue in play is that SPFx is never intended to run in node.

Yup... that's the crux of the problem. Microsoft made it incredibly hard to test SPFx projects because all the SPFx libraries expect to run within a SharePoint context & with the SPFx runtime present. It's why I recommend you never include the SPFx components in your tests, rather use them as the glue between your app & SharePoint, then you only focus on testing your app.

I do have it on my backlog to update my Jest presets for the current version dependency matrix... no ETA ATM, but it's planned work in the near future.

@nbelyh
Copy link
Author

nbelyh commented Nov 3, 2020

@andrewconnell I don't actulaly include SPFx components in tests, but the thing is - as soon as you have in the main module (or dependent module, such as a service) import { something} from @sp/@pnp/@microsoft it can easily becomes an issue in unit tests (jest) - invalid keyword 'import', 'export', 'define', take your pick 😄 I.e. the test won't even compile - that the thing...

@andrewconnell
Copy link

Gotcha... yeah, lots of people have hit this as as the thread @patrick-rodgers & you mentioned above, there are a few different approaches to resolving it. Sadly, one size doesn't fit all... just not a fun thing to deal with :-/

@wizneeraj
Copy link

@nbelyh - Please let me know if you were able to make jest work with PnPJs, i am having a similar issue and need some guidance on this regard.

@nbelyh
Copy link
Author

nbelyh commented Nov 11, 2020

@wizneeraj @andrewconnell
Like described above, created a simple hello-world repository (that uses babel with the mentioned plugins for unit testing):
https://github.com/nbelyh/spfx-unit-testing-pnpjs

config:

  • SPFx 1.11.0 (latest),
  • react 16,
  • typescript 3.9
  • can test both services and components (jest 26 + enzyme)
  • does not blow up on import { sp } from @pnp/sp
    (thatnks to babel and transform-es2015-modules-commonjs)
  • does not break on AMD "define" in string resources, i.e. on import * as strings from 'HelloWorldWebPartStrings'
    (thatnks to babel and transform-amd-to-commonjs)
  • some controls from @pnp/spfx-controls-react are working (checked with Placeholder)

To run unit test:

npm install
npm test

The modifications to the original projects are mostly in the latest commit:
nbelyh/spfx-unit-testing-pnpjs@b32e2e2

Had to add somehow window.DEBUG = true, looks like there is some issue with PnPTelemetry that is looking for "DEBUG" instead of window.DEBUG, so had to add that as jest startup

@patrick-rodgers
Copy link
Member

Closing this issue as answered. If you have additional questions or we did not answer your question, please open a new issue, ref this issue, and provide any additional details available. Thank you!

Would also invite someone from this thread to add an explanation to the docs to make the information easier to find.

@github-actions
Copy link

This issue is locked for inactivity or age. If you have a related issue please open a new issue and reference this one. Closed issues are not tracked.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants