Git Product home page Git Product logo

jest-css-modules-transform's Introduction

Build Status

jest-css-modules-transform

Preprocessor css modules for Jest test framework

This preprocessor converts css files in modules like Webpack. If we have css files

.class1, .class2, .class3 {
    display: block;
}

Webpack will transfrom it to object.

{
    class1: 'class1', //value may be different. It depends of localIndentName property
    class2: 'class2',
    class3: 'class3',
}

In testing you need to mock all css modules to aviod exception. But use pure object {} for mocking is bad idea, because it makes wrong classNames in components. This preprocessor makes correct modules as if Webpack did.

Usage

In Jest config add option

"transform": {
  ".+\\.(css|styl|less|sass|scss)$": "jest-css-modules-transform"
},

or

"transform": {
  ".+\\.(css|styl|less|sass|scss)$": "<rootDir>/node_modules/jest-css-modules-transform"
},

It supports pure CSS, SCSS, SASS, STYLUS and LESS.

For PostCSS

For .css, .pcss, .postcss files used postcss.config.js from root folder(if file exist of course).
For tests you can rewrite your existed postcss.config.js. See options.

Options

You can save preproccessor options in file jest-css-modules-transform-config.js in root of your project(Where is the file package.json). You can pass options for your preprocessors.

example:
const path = require('path');  
const additionalResolvePath = path.resolve(__dirname, 'src', 'additional_modules');

module.exports = {
    sassConfig: {
        includePaths: [additionalResolvePath],
        precision: 5,
    },
    lessConfig: {
        paths: [additionalResolvePath],
    },
    stylusConfig: {
        paths: [additionalResolvePath],
    },
    postcssConfig: {
        plugins: [
            require('autoprefixer')({
                browsers: ['Chrome 68', 'Firefox 62', 'Safari 12']
            })
        ]
    },
};

For all preprocessor options see offical documentations for Sass, Less, Stylus.

cssLoaderConfig

exportLocalsStyle

Webpack's cssLoader has option exportLocalsStyle.

// file jest-css-modules-transform-config.js
module.exports = {
   cssLoaderConfig: {
        exportLocalsStyle: 'camelCase'
   }
};

then this css code

    .foo__bar{color: red;}
    .foo__bar2{color: red;}

converted to

    {
        foo__bar: 'foo__bar',
        fooBar: 'foo__bar',
        foo__bar2: 'foo__bar2',
        fooBar: 'foo__bar2',
    }

Available values camelCase, camelCaseOnly, dashes, dashesOnly, asIs(by default)

prepend

Type: string, Function, Array<string | Function>
Default: null

Pass urls for prepend(before file content) to transformed files.
Useful in a situation where the module uses variables or mixins without explicit import.

For example you have vars in file, but without implicit import. You can prepend file with sass variables before convert module.

injectIntoDOM

Type: boolean Default: false

Inject the generated CSS into the head of the document.

This option could be useful for visual regression testing, where the output dom has the styles applied to it.

sassModuleName

Type: string Default: null

The default nodejs module for sass/scss files is sass. If not found in node_modules, then node-sass. You can define any another module.

Example with array of paths
// file jest-css-modules-transform-config.js
module.exports = {
   prepend: [
       'some/url/vars.scss',
       'some/url/theme.scss',
   ],
};
Example with single string
// file jest-css-modules-transform-config.js
module.exports = {
   prepend: 'some/url/vars.scss',
};
Example with custom function
// file jest-css-modules-transform-config.js
module.exports = {
   prepend: (filepath) => {
       if (filepath.includes('components')) {
           return [
               'components/vars.scss',
               'components2/vars.scss',
           ];
       }

       return [
            'common/vars.scss',
            'common/vars2.scss',
       ];
   },
};

It works with any preprocessors(Sass, Less, Styles, PostCSS, pure CSS)

Custom config path

By default option plugin's config file is jest-css-modules-transform-config.js from root. For specify custom path just add env JEST_CSS_MODULES_TRANSFORM_CONFIG. For example:

JEST_CSS_MODULES_TRANSFORM_CONFIG=custom-config-path npm test

or

JEST_CSS_MODULES_TRANSFORM_CONFIG=custom-config-path yarn test

Install

npm i jest-css-modules-transform

jest-css-modules-transform's People

Contributors

ashubham avatar connormiha avatar cyco130 avatar dependabot[bot] avatar gish avatar kalmi avatar m0ngr31 avatar mbelsky avatar voskresla avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

jest-css-modules-transform's Issues

Dependency Update

Update the postcss from 8.4.5 to 8.4.6
Because the nanoid used in [email protected] is vulnerable to Information Disclosure. Due to a weakness in the fillPool() function in index.js, a local attacker can leverage the JavaScript valueOf() function to reproduce the last ID generated. Depending on how the application uses these unique IDs, the attacker could use this information to access other sensitive data.

Config options passed like jest describes are not used

If you set options like jest actually documents, and is cleaner for the setup I have, they aren't used.

  transform: {
    '\\.(scss|css)$': [
      require.resolve('jest-css-modules-transform'),
      {
        injectIntoDOM: true,
        sassModuleName: require.resolve('sass'),
        postcssConfig: sharedPostcssConfig(null, { mode: 'none' }),
      },
    ],
  },

It would be great if this is used. I am using a mono-repo, and the config options now available make it hard to set it due to the mono-repo setup. It actually makes it quite impossible for a mono-repo without any hacking.

jest-css-modules-transform-config.js not read

I have created the jest-css-modules-transform-config.js in the root of my package, however it does not seem to be honored.

Contents of the config file:

module.exports = {
    injectIntoDOM: true,
    prepend: [
        './src/scss/vue-ui.scss',
    ],
};

Example Test:

import { shallowMount, mount } from '@vue/test-utils'
import Select from '@/components/Forms/Select.vue'
import colors from '@/scss/_base_js.scss';

describe('Select.vue', () => {

  const wrapper = mount(Select, {
    propsData: {
      options: ['Option A', 'Option B'],
      value: 'Option A'
    }
  });

  it('has the brand brand color', () => {
    console.log(getComputedStyle(wrapper.element));
    //expect(wrapper.element).toHaveStyle({background: colors.brandColor});
  });
})

The computed styles are empty and the css does not seem to be injected into the DOM. Am I doing something wrong here? I also tried to manually set the path via the JEST_CSS_MODULES_TRANSFORM_CONFIG env variable but it seems to have no effect either.

Cannot find module 'node-sass'

Hi, i use jest-css-modules-transform in .test.tsx files and i have this error on run tests:

Cannot find module 'node-sass'

    Require stack:
      src/common/components/test-component/index.tsx
      src/common/components/test-component/__test__/index.test.tsx

      at getSassContent (node_modules/jest-css-modules-transform/dist/index.js:62:20)
      at Object.process (node_modules/jest-css-modules-transform/dist/index.js:108:27)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:463:35)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:568:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:606:25)

How can i resolve this problem?
At the moment in my project a do not have node-sass dependency in package.json.
Should i just add node-sass?

Usage with @jest-runner/electron

Hi, I'm trying to use this in electron, but the sass module can't be found. I get an "Illigal invocation" error, and I'm not proficient enough with electron to know what is going on, and how to update configuration to get this package working with the @jest-runner/electron one. I need an actual browser and rendering because I want to test the eventual colours of elements. So any help is very appreciated.

This is my config:

jest-config.js

  //...
  displayName: 'Real browser',
  runner: require.resolve('@jest-runner/electron'),
  testEnvironment: require.resolve('@jest-runner/electron/environment'),
  testMatch: ['**/*.spec.{???,??}'],
  transform: {
    '\\.(scss|css)$': require.resolve('jest-css-modules-transform'),
  },
  //...

jest-css-modules-transform-config.js

const sharedPostcssConfig = require('@company/tools-config-postcss');

module.exports = {
  injectIntoDOM: true,
  sassModuleName: require.resolve('sass'),
  postcssConfig: sharedPostcssConfig(null, { mode: 'none' }),
};

:export blocks should get camelCase versions of their outputs

a css module file in my codebase has an :export block, e.g.

// foo.css
:export {
    page-margin: 16px;
}

// foo.js
import {pageMargin} from "./foo.css";

However, this transform only seems to give us "page-margin" to use, i.e. we'd have to change foo.js to import styles from "./foo.css"; const pageMargin = styles["page-margin"];. I expected the camel casing to be implemented for us, as it seems to be implemented by postcss-modules and so our build system already supports the syntax (entirely by accident).

:not selector work wrong

I made example, just run npm i && npx jest master...voskresla:bug-with-not-selector

With css:

.class2, .class3 {
    display: block;
    color: #fff;
}
.class3:not(.class1) {
    color: black
}

we expected Object like:

{
  "class1": "class1",
  "class2": "class2",
  "class3": "class3",
}

but received object is:

Snapshot name: `Style with :not selector should import default 1`

    - Snapshot  - 1
    + Received  + 1

      Object {
    -   "class1": "class1",
    +   "class1)": "class1)",
        "class2": "class2",
        "class3": "class3",
      }

      7 | });

css classes are not injected when using scss with css modules

Hi,

I have a project with the following stack: React/Redux/Typescript/SCSS/CSSModules

We are using jest with react-testing-library to test our components that are developed in storybook and then published to a private repository.

This is my jest.config.js file

module.exports = {
  "roots": [
    "<rootDir>/src"
  ],
  "transform": {
    "^.+\\.tsx?$": "ts-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx",
    "json",
    "node"
  ],
  testPathIgnorePatterns: ["/node_modules/"],
  "moduleNameMapper": {
    ".+\\.(css|styl|less|sass|scss|svg)$": "<rootDir>/node_modules/jest-css-modules-transform",
  },
  "transformIgnorePatterns" : [
    "^.d.ts?$"
  ],
}

Component I'm testing ChipStatus.tsx

import * as React from "react"

import * as s from "./ChipStatus.scss"
import { IChipStatusProps } from "."

const ChipStatus: React.FunctionComponent<IChipStatusProps> = props => {
  return <div className={s.active}>{props.placeholder}</div>
}

export default ChipStatus

And this is my test ChipStatus.test.tsx

import * as React from "react"
import { render } from "react-testing-library"
import "jest-dom/extend-expect"

import ChipStatus from "./ChipStatus"
import { EChipStatus } from "./index"

test("ChipStatus inactive", async () => {
  const { container, debug } = render(
    <ChipStatus status={EChipStatus.ACTIVE} placeholder={"texte active"} />
  )
  expect(container.firstChild).toHaveClass("active");
  expect(container.firstChild).toHaveTextContent("texte active")
})

This test should pass, however it fails because there's no class injected in my component

This is the debug() of my component

<div
                      class=""
                    >
                      <p
                        class="MuiTypography-root-136 MuiTypography-body1-145"
                      >
                        Active
                      </p>
                    </div>

As you can see, I'm missing the class active. What troubles me is that in a component from Material-ui we have the class that is injected, but I guess that when the test runs, the scss file is not being compiled into css and the class is not injected.

Am I missing something in my set up?

Does not work with jest 28

Received following error from jest 28.0.0 when importing css

Invalid return value:
      Code transformer's `process` method must return an object containing `code` key
      with processed string. If `processAsync` method is implemented it must return
      a Promise resolving to an object containing `code` key with processed string.
      Code Transformation Documentation:
      https://jestjs.io/docs/code-transformation

Version

jest: 28.0.0
jest-css-modules-transform: 4.3.0

Error on import from within prepended file

If I prepend (using prepend option in jest-css-modules-transform-config.js) a .scss file into which I import some variables from different folder (using relative path), my test ends up with an error:

 FAIL tests/js/Footer/Footer.test.jsx
  ● Test suite failed to run
    File to import not found or unreadable: ../../styles/colors.
      at Object.module.exports.renderSync (node_modules/node-sass/lib/index.js:441:16)
      at getSassContent (node_modules/jest-css-modules-transform/dist/index.js:69:24)
      at Object.process (node_modules/jest-css-modules-transform/dist/index.js:108:27)

The prepended file (colors.scss) is really simple (as is my config file). Its content is:

/* This theme currently imports dev styles. */
@import '../../styles/colors';

And my jest-css-modules-transform-config.js's content is:

module.exports = {
  prepend: ["./assets/themes/orange/colors.scss"]
};

Paths are correct since they work well with sass-resources-loader in my webpack, only the secondary import fails. This still could be my fault as I might be missing some sass configuration in the config file, but I am not sure at this point.

SyntaxError: Octal escape sequences are not allowed in template strings

Hi, I am using a third-party library with css like below: (I guess for cross browser compatibility)

.main {
  content: '\20';
}

when I run test with this css, jest will throw this error:

styles.css:3
      content: '\20';
                 ^

    SyntaxError: Octal escape sequences are not allowed in template strings.

      2 | import * as React from 'react'
      3 |
    > 4 | import classes from './styles.css'

But it still run in browser, can you advice what can I do to parse this syntax? thank you!

Returns empty object on class

Hey! I'm having difficulties adding this to my jest tests.

To reproduce:

  1. git clone https://github.com/evenstensberg/css-test.git
  2. cd react
  3. npm install && npm run test

Here's the direct link:

https://github.com/evenstensberg/css-test/tree/master/react

Here's the link to package.json

https://github.com/evenstensberg/css-test/blob/master/react/package.json#L64-L68

Here's the link to the test

https://github.com/evenstensberg/css-test/blob/master/react/src/style-tests/main.test.js

Screen Shot 2021-05-13 at 18 39 21

Add support for media queries

Classes defined within @media are skipped. Some classes are only defined within media queries and they are omitted entirely.

Example with responsive utility classes:

.display-block {
    display: block;
}

@media (max-width: 600px) {
   .display-block\@sm {
        display: block;
   }
}

display-block is present in the result, but display-block@sm is not.

Support for cssNext nesting

Hey, I am CSS next in my css modules in a react project, and specifically within that i am using the nesting feature.

example

.MyAccount {
    position: relative;

    & .sidebar {
        float: left;
    }
}

This preprocessor doesn't seem to be able to handle that as when i debug in enzyme it processes the .MyAccount class ok but returns undefined for sidebar

<div className="MyAccount">
          <div className={[undefined]}>
               Content
          </div>
</div>

Thanks

Transformer breaks on `jest@>=27`

Issue

The process(src, path, config) {} signature of jest@>=27 actually nests the config object inside another, higher level config object used strictly for the jest runner.

To be more specific, your moduleTransform.process function tries to read the higher level config instead of the actual jest.config.json file. This results in the config fields needed for your code being null, crashing the transformer.

Example

const moduleTransform: Omit<Transformer, 'getCacheKey'> = {
  process(src, path, config) {
    console.log(config);
  }
}

reveals the config object as something akin to:

{
    "isInternalModule": false,
    "supportsDynamicImport": false,
    "supportsExportNamespaceFrom": false,
    "supportsStaticESM": false,
    "supportsTopLevelAwait": false,
    "collectCoverage": true,
    "collectCoverageFrom": [],
    "coverageProvider": "babel",
    "instrument": true,
    "cacheFS": {},
    "config": {
        // fields set in jest.config.json, including those that your transformer cares about
        "automock": false,
        "cache": false,
        "clearMocks": false,
        "coveragePathIgnorePatterns": [ "/path/to/my-app/.git", "/path/to/my-app/config", "/path/to/my-app/dist" ],
        "cwd": "/path/to/my-app",
        "rootDir": "/path/to/my-app",
        "transform": [ // Note: even though jest.config.json uses an object for "transform," it's converted to an array in `process()`
            [ 
                "\\.[tj]sx?$", 
                "/path/to/my-app/node_modules/jest-config/node_modules/babel-jest/build/index.js",
                {
                    "configFile": "/path/to/my-app/config/babel.config.json"
                }
            ], 
            [
                "\\.s?css$", 
                "/path/to/my-app/node_modules/jest-css-modules-transform/dist/index.js", 
                {
                    "customConfigKeyForYourTransformer": "customVal",
                    "For example": "instead of a separate file using module.exports",
                    "sassConfig": {
                        "includePaths": [ "additionalResolvePath" ],
                        "precision": 5,
                    },
                    "lessConfig": {
                        "paths": [ "additionalResolvePath" ],
                    },
                    "stylusConfig": {
                        "paths": [ "additionalResolvePath" ],
                    },
                    "postcssConfig": {
                        "plugins": [ "..." ]
                    },
                }
            ]
        ],
        "transformIgnorePatterns": [ "/node_modules/" ]
    },
    "transformerConfig": {
        // same fields as above /\.s?css$/ regex field, but directly accessible rather than iterating through an array
        "customConfigKeyForYourTransformer": "customVal",
        // ... rest of config fields your transformer uses
    }
}

Proposed Solution

Support both jest versions

You could easily support both jest@<27 and jest@>=27 by attempting reading v27's config structure first, then defaulting to v26's structure.

const moduleTransform: Omit<Transformer, 'getCacheKey'> = {
  process(src, path, config) {
    config = config.config || config; // config.config == jest@27  -  config == jest@26
    // ... all the rest of the logic stays the same
  }
  // or better yet:
  process(src, path, options) {
    const config = options.config || options;
    // ...
  }
}

Add much-needed flexibility with preprocessor options

Likewise, using jest's built-in config object structure would also allow passing in the preprocessor options inline (as jest recommends) rather than forcing the user to create a separate file. This would be particularly helpful if users only have one or two configs to pass in, but it's also just generally better form to follow the API as the creators instruct rather than your own custom API.

const moduleTransform: Omit<Transformer, 'getCacheKey'> = {
  process(src, path, options) {
    const config = options.config || options;
    configPath = configPath || resolve(config.rootDir, CONFIG_PATH);
    preProcessorsConfig = options.transformerConfig || preProcessorsConfig || getPreProcessorsConfig(configPath);
    // ... all the rest of the logic stays the same
  }
}

Note: This would also solve issue #37.

adding transform option causes: SyntaxError: Cannot use import statement outside a module

with this config, when I add transform it fails compiling
same if I remove "\.(css|less|scss|sass)$": "identity-obj-proxy",

"jest": {
"verbose": true,
"moduleNameMapper": {
"\.(jpg|jpeg|png|svg|ttf|woff)$": "./src/config/fileMock.jAAAs",
"\.(css|less|scss|sass)$": "identity-obj-proxy",
"typeface-roboto": "identity-obj-proxy"
},
"transform": {
".+\.(css|styl|less|sass|scss)$": "jest-css-modules-transform"
}
},

When I change to below config, it will says " PostCSS plugin postcss-nested requires PostCSS 8."

"transform": {
"\.(js|jsx)$": "babel-jest",
"\.scss$": "jest-css-modules-transform"
}

jest --env --verbose --passWithNoTests --rootDir src/

FAIL src/components/helpers/format-form-data.test.js
● Test suite failed to run

Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here's what you can do:
 • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
 • 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/en/configuration.html

Details:

src\components\helpers\format-form-data.test.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { formatFormData } from 'components/helpers/format-form-data';
                                                                                         ^^^^^^

SyntaxError: Cannot use import statement outside a module

  at Runtime.createScriptFromCode (../node_modules/jest-runtime/build/index.js:1350:14)

FAIL src/components/testutil/component-accessors.test.js
● Test suite failed to run

Jest encountered an unexpected token

This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

Using latest 4.3.0 in my create react setup and adding transform option for jest with
"transform": {
".+\.(css|styl|less|sass|scss)$": "jest-css-modules-transform"
}

Will make my tests fail to compile:

By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

Here's what you can do:
 • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
 • 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/en/configuration.html

Details:

react-ui\src\components\testutil\component-accessors.test.js:1
({"Object.":function(module,exports,require,__dirname,__filename,global,jest){import { render, fireEvent } from '@testing-library/react';
^^^^^^

SyntaxError: Cannot use import statement outside a module

  at Runtime.createScriptFromCode (../node_modules/jest-runtime/build/index.js:1350:14)

Test Suites: 2 failed, 2 total

Regex matching issues

Hi and thanks for all the effort put into the library. I am having an issue running the transform against one of my imports. I believe this is because the regex does not cover this case. If this is the case, would it be possible to update it?

I'm tying import a css file with this path:

require('rc-tooltip/assets/bootstrap_white.css')

So essentially a nested file in a package. When I try to run my tests and import this file, I get the following error:

SyntaxError: Unexpected token '.'

implying a match could not be made. I've tried to play around with this and figure out what the correct regex is, but I keep getting this error no matter what I try.

Thanks!

[Feature Request] Generate scoped className

For now, if we want to test nested components, there can be some class name conflicts.

// Foo.jsx
import Bar from './Bar';
import styles from './foo.module.scss';

function Foo() {
  return (
    <div className={styles.show}>
      <Bar />
    </div>
  );
}

export default Foo;
// Bar.jsx
import styles from './bar.module.scss';

function Bar() {
  return <p className={styles.show}>bar content</p>;
}

export default Bar;
// foo.module.scss
.show {
  display: block;
}
// bar.module.scss
.show {
  display: flex;
}
// jest-css-modules-transform-config.js
const path = require('path');

module.exports = {
  sassConfig: {
    includePaths: [path.resolve(__dirname, 'src')],
  },
  injectIntoDOM: true,
};

The injected CSS are conflicting:

.show {display: flex;}
.show {display: block;}
    <body>
      <div>
        <div
          class="show"
        >
          <p
            class="show"
          >
            bar content
          </p>
        </div>
      </div>
    </body>

It would be a big improvement if this jest transformer would generate something like the webpack loaders (Foo__show_SomeHash, Bar__show_OtherHash)

Add possibility to setup `includePaths` for node-sass

Hi.
I have two paths configured in webpack for node-sass like this:

          {
            test: /\.(css|scss|sass)$/,
            loader: 'sass-loader',
            options: {
              includePaths: [SRC_DIR, resolvePath('node_modules')],
            },
          },

Is there any way I can do similar setup for jest using this transform?

Thanks for great tool

Issue on 2.2.0


    Use process(css).then(cb) to work with async plugins
      
      at LazyResult.sync (node_modules/postcss/lib/lazy-result.js:263:23)
      at LazyResult.stringify (node_modules/postcss/lib/lazy-result.js:285:14)
      at LazyResult.get (node_modules/postcss/lib/lazy-result.js:334:25)
      at Object.process (node_modules/jest-css-modules-transform/src/index.js:241:78)

First run of tests with TS fails

Hi, i use jest-css-modules-transform with typescript and typescript-plugin-css-modules and when

Here is example repo:
https://github.com/krutoo/jest-ts-css-modules

I run it on node js 14.15.5

When run:

npm run test -- --watchAll

First run fails with:

  ● Test suite failed to run

    src/components/second/index.tsx:2:20 - error TS2307: Cannot find module './second.scss' or its corresponding type declarations.

    2 import styles from './second.scss';
                         ~~~~~~~~~~~~~~~

important: restart by Enter key on keyboard removes error

Can you help me to understand: is this a bug in the jest-css-modules-transform package? Or it is typescript-plugin-css-modules issue?

Add support for camel case

When using a webpack css-loader, we can specifiy a camelCase option.

{
    loader: "css-loader",
    options: {
        modules: true,
        camelCase: true
    }
}

Which create a style object like:

{
    'button--icon-play': 'button--icon-play',
    buttonIconPlay: 'button--icon-play'
}

I tried using the jest-css-modules-transform but the camelCase style were missing.

I instead used a custom jest transform mock:

const postcss = require('postcss');
const postcssJs = require('postcss-js');
const camelCase = require('camelcase');

module.exports = {
    process(src, filename, config, options) {
        try {
            const cssRendered = sass.renderSync({
                data: src,
                includePaths: [
                    'components/common/styles'
                ]
            });

            const cssString = cssRendered.css.toString();
            const cssObj = postcssJs.objectify(postcss.parse(cssString));
            const mockStyles = {};
            for (var i in cssObj) {
                const classname = i.replace(/^[\.]/, '');
                mockStyles[classname] = classname;
                mockStyles[camelCase(classname)] = classname;
            }
            return 'module.exports = ' + JSON.stringify(mockStyles) + ';';

        } catch(err) {
            console.log('Error in sass-mock', err);
            throw err;
        }
    }
};

Is there an easier way to do this? (using the webpack css-loader for example)
Or should jest-css-modules-transform supports camelCase?

Value of CSS module is 'default'

The content of Hello.less is:

.hello{
  text-align: center;
  margin: 20px;
  font-size: 48px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.greeting{
  margin-left: 25px;
  margin-right: 25px;
  font-size: 40px;
  min-width: 50px;
}

This is my jest.config.js:

module.exports = {
	setupFiles: ['./jest.setup.js'],
	transform: {
		'^.+\\.(css|less)?$':
			'<rootDir>/node_modules/jest-css-modules-transform',
		'^.+\\.js?$': 'babel-jest',
		'^.+\\.ts[x]?$': 'ts-jest'
	},
	moduleFileExtensions: ['tsx', 'ts', 'less', 'js', 'json', 'jsx'],
	moduleNameMapper: {
		'^utils(.*)$': '<rootDir>/src/utils$1',
		'^three-examples(.*)$': '<rootDir>/node_modules/three/examples$1',
		'\\.(css|less)$': 'identity-obj-proxy'
	}
}

Hello.test.ts:

import * as React from 'react'
import * as enzyme from 'enzyme'
import Hello from './Hello'
import styles from './Hello.less'
// const styles = require('./Hello.less')

it('Test render', () => {
	const hello = enzyme.shallow(<Hello name="jad" />)
	console.log('running...')
	console.log(styles) //output: default
	expect(hello.find('.' + styles.greeting).text()).toEqual('Hello jad')
})

After exec npm test, I got this error:

 Method “text” is meant to be run on 1 node. 0 found instead.

       9 |      console.log('running....')
      10 |      console.log(styles)
    > 11 |      expect(hello.find('.' + styles.greeting).text()).toEqual('Hello jad')
         |                                               ^
      12 | })

It seems that the value of styles.greeting is undefined, so the component hello cannot find the className '.undefined'

How can I get the correct value of styles.greeting with pattern of 'modules&localIdentName=[path][name]--[local]--[hash:base64:5]' which is set in the webpack.config.js

Thx

Unexpected reserved word

jest-css-modules-transform/dist/utils.js:33
        for await (const chunk of stream) {
            ^^^^^
    SyntaxError: Unexpected reserved word

This causes tests to fail, when I remove the await locally it works, but then my CI is dependent on this module to work. Any help?

Node version: 8.17.0
Version: 4.0.2
Jest version: 23.6

Add support for css modules :export block

Please, add support for exports, it would be extremely usefull with sass/less other preprocessors

Example .less

@type: "global";
:export {
  red: #db2b21;
  type: @type;
}
.some-style {
display: block;
}

the resulting object would look like this:

{ "some-style": "some-style", "red": "#db2b21", "type": "global" }

CSS transform from node_modules

Hi,
I've got everything working so far with both local css and local sass, I can do:

import 'my-css.css';
import 'my-scss.scss';

Everything gets mocked correctly.

I now have to use both sass files and css files from a module in the node_modules folder:

import '@my-org/my-module/my-scss.scss';
import '@my-org/my-module/my-css.css';

For sass I had to add the includePaths in the sassConfig, all working well.
However I can't find a way to test the file that import the css file from the node_modules folder.

I would appreciate any clue, I tried a lot of things in jest between "transformIgnorePatterns", "moduleNameMapper" and so on.

My config:

const path = require('path');

module.exports = {
    sassConfig: {
        includePaths: [
            path.resolve(__dirname, '../../../node_modules/')
        ],
        precision: 5,
    },
    cssLoaderConfig: {
        exportLocalsStyle: 'camelCase'
    }
};

The error:

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • 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/en/configuration.html

    Details:
    SyntaxError: Unexpected token .

    >  7 | import '@my-org/my-module/my-css.css';

Jest won't recompile CSS modules when their dependencies change unless you wipe Jest's cache

Issue

Jest won't recompile CSS modules when their dependencies change unless you wipe Jest's cache.

Reproduction Link

https://github.com/nskazki/jest-wont-recompile-css-modules

How to Reproduce

I've defined a SCSS variable in the color.scss, re-exported that variable via the module.scss, re-exported it again via the color.js, so that I can finally inspect it in the color.spec.js.

  1. Run the color.spec.js using npm run test. It should fail because the variable is actually red while it's expected to be green.
  2. Fix the variable's value, echo '$color: green;' > src/color.scss.
  3. Run the same spec again using the same command. It shouldn't have failed but it will because the wrong value is stuck in cache!
  4. Ignore the cache using npm run test-no-cache. It should pass this time.

Why Dependencies?

If you define the variable right in the module.scss instead of importing it from the color.scss, the problem with cache won't bother you. So, the problem has to do with dependencies.

Global style sheet with only :root selector seems to be excluded

Hi,

Our project has a number of global stylesheets that contain only css variables. The variables appear not to be injected into the document when there is no actual css class in the css file.

For example, our test does:

// Beautiful.spec.js
import React from "react";
import './index.css';
import Beautiful from "./Beautiful";
// ... more test imports

it("should have no visual regressions", async () => {
  const { getByTestId } = render(<Beautiful />);
  fireEvent.click(getByTestId("beautiful-button"));

  // expect(await generateImage()).toMatchImageSnapshot();  <-- this is what would normally take the screenshot, but for now, console log below
  console.dir(document.head.innerHTML);
});

The index.css above is the global stylesheet. It contains:

/* index.css */
:root {
    --some-var: blue;
}

The component pulls this in via an import import './beautiful.css'; which in turn uses the variable:

/* beautiful.css */
.button {
  background: var(--some-var);
}

The output from the console log is:

<style>.button {
        background: var(--some-var);
      }</style>

So the button component import it's css fine, but index.css has gone missing.

If I update index.css to:

/* index.css */
:root {
    --some-var: blue;
}
.stub {}

Then the console log becomes:

/* index.css */
 <style>:root {
          --some-var: blue;
      }
      .stub {}</style><style>.button {
        background: var(--some-var);
      }</style>

Now the index.css values appear in the document head. I can even comment out the stub class:

/* index.css */
:root {
    --some-var: blue;
}
/* .stub {} */

And styles appear correctly in the document head:

<style>:root {
          --some-var: blue;
      }
      /* .stub {} */</style><style>.button {
        background: var(--some-var);
      }</style>

Am I including global styles correctly? Or is there something rejecting the css variables?

Thanks.

Support for postcss 8

Hello,
thank you for this module. Do you plan on supporting v8 version of postcss ? It depends on postcss7 right now I think.

Upgrading to postcss 8 AND autoprefixer 10 is breaking the use of autoprefixer, and crashes my tests:

Error: PostCSS plugin autoprefixer requires PostCSS 8

Command failed: node C:\xxx\node_modules\jest-css-modules-transform\dist\postcss.js C:\xxx\src\client\Components\Inputs\input.css C:\xxx\jest-css-modules-transform-config.js C:\xxx\SWAG\postcss.config.js 0

Hope it helps.

SassError: Can't find stylesheet to import.

Hi, i use jest-css-modules-transform with typescript files and in my .scss files i have something like this:

@use '~foo/bar/baz.scss';

// ....some scss here

And in mye tests i have error:

SassError: Can't find stylesheet to import.

Looks like in jest environment sass cannot resolve tilde

how can i solve this problem?

Support of sass instead node-sass

Hello. Can jest-css-modules-transform work with sass module instead node-sass

node-sass is depreacated now and it is now supports new features of Sass/SCSS.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.