nx: Don't use `identity-obj-proxy` by default in the jest resolver

Description

Allow the ability to handle .css, .scss,.sass,.less, .styl extensions rather than early exit in the default @nrwl/jest/plugins/resolver with identity-obj-proxy.

Motivation

Using @vanilla-extract requires a jest-transform of the css files but it’ not possible to handle/transform them because the default nx resolver catches all css files.

Suggested Implementation

The resolver logic already checks the resolver options which could be used to opt out of identify-obj-proxy

Alternate Implementations

Don’t default to identity-obj-proxy and instead provide that as boilerplate config which would be easier to discover/change

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 32 (6 by maintainers)

Most upvoted comments

Thanks @bart88 that’s a good suggestion, so I tried.

The above works with no issues.

So I also extended it to:

//dummy.css.ts image

//dummy.tsx image Here I also try to read my injected vars using Context.

//dummy.spec.tsx image Here I also wrap my Provider (forget about the store, that’s just an additional dependency), so I can read my vars in the above component log.

This all passes, but check the logs: image

  • themeVars is an empty object, so no tokens in it (remember, this comes from the lib I created in nx)
  • vars, which is a local theme contract pulled from dummy.css.ts is a string
  • all styles are strings

The fun part? All of this is exactly the same with and WITHOUT the custom-resolver+jest-transformer

Finally, if I change the style imports to have css.ts import { dummyStyle, themeClass, vars } from “./dummy.css.ts”;

I get: image

And if I simplify to only using style(), I also get: image

Tx for your patience btw.

the resolver can be set at the project or global level. depends on if you want it to applied to all projects or not.

if you want to apply it to all projects, then you can pass it in the jest.preset.js (which get’s applied to all project)

so in this case

const nxPreset = require('@nrwl/jest/preset').default

module.exports = {
  ...nxPreset,
  resolver: 'path/to/your/custom-resolver.js'
}

in custom-resolver.js

module.exports = function(path, options) {
  // run your resolver logic first to prevent nrwl resolver handling css files
  if(isCssFile(path)) {
    return resolveCssFile(path, options); // this is probably just going to be options.defaultResolver(path, options) but idk 🤷 
  }

  return nrwlResolver(path, options); // pass to the nrwl resolver to handle the rest of the stuff
}

then you also need to set up a transformer to handle your css files. so in your project level jest.config.ts

/* eslint-disable */
export default {
  displayName: "impaqt-plus-ui",
  preset: "../../jest.preset.js",
  transform: {
    // "^(?!.*\\.(js|jsx|ts|tsx|json)$)": "@nrwl/react/plugins/jest", //disabled this
    "^.+\\.[tj]sx?$": ["babel-jest", { presets: ["@nrwl/react/babel"] }],
    "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/cssTransformer.js",
  },
  moduleFileExtensions: ["ts", "tsx", "js", "jsx"],
  coverageDirectory: "../../coverage/apps/impaqt-plus-ui",
  setupFiles: ["./src/app/setupMocks.ts"],
  setupFilesAfterEnv: ["./src/app/setupTests.ts"],
};

now you’ll need to setup the cssTransformer.js file.

const nrwlReactTransformer = require("@nrwl/react/plugins/jest");
const path = require("path");
const transformer = require("@vanilla-extract/jest-transform");

module.exports = {
  process(sourceText, sourcePath, options) {
    // if this is a vanilla-extract css.ts file then pass it to the vanilla-extract transformer
    if (sourcePath.endsWith(".css.ts")) {
      return transformer.default.process(sourceText, sourcePath, {
        config: options,
      });
    }

    // send to the nrwl transformer
    return nrwlReactTransformer(path, options);
  },
};

I think this will work. might have typo’d something. but the gist is there.

there are two places to setup the resolver (in the root jest.preset.js or project level jest.config.ts).

then setup the css transformer in the project level jest.config.ts so that your css files are transformed correctly.

You’re mixing a jest resolver and jest transformer.

The error you’re seeing is that the return nrwlResolver(path,options); returns a file path which is not a transformer object. So jest isn’t happy with that.

You’ll need to set up the custom jest resolver to not use identify-obj-proxy by returning the resolved path yourself first (probably just needs to use the default resolver from jest (options.defaultResolver) or at least that is the issues preventing from using vanilla-extract according to @craigbilner. I’m unfamiliar with the package.

and then you’ll need to apply whatever transformer logic to transform the css files for your project. which looks to be just the transformer from @vanilla-extract/jest-transform