Testing components with Jest using css modules - javascript

I'm working on a project in React using CSS modules for stylings.
I would like to test a component using Jest and React Testing Library, but when I try to render it I get this error:
Test suite failed to run
cssModule has no keys
3 | export default (style: {[key: string]: string}):any => {
4 | block.setSettings({throwOnError: true, modifierDelimiter: '--'});
> 5 | return block(style);
| ^
6 | };
7 |
block is an override from a function exported by the library bem-css-modules which I use for keeping BEM nomenclature while implementing css-modules.
I have managed to log the exact style (imported by the .module.scss file) which is passed to this function, and I have found that it is actually empty when rendering the component with react-testing-library:
import React from 'react';
import MyIcon from 'shared/components/myIcon/myIcon.component';
import styles from './myButton.module.scss';
import block from 'utils/bemCssModulesConfig';
console.log('styles', styles) // this logs "styles, {}" so it's empty object
const bem = block(styles);
This is the moduleNameMapper I am currently using:
"moduleNameMapper": {
"^.+\\.(scss|sass|css|less)$": "identity-obj-proxy"
}
I have already tryed using custom proxies copied from the internet or using external libraries as moduleNameMappers.

Related

How can I force Webpack in a Next.JS app to resolve to a specific dependency from an external directory?

Given the following directory structure, is it possible to have ALL react imports resolve to react-b?
|__node_modules
| |__react-a
|
|__app-a
| |__component-a
|
|__next-app
| |__react-b
| |__component-b
// component-a
import { useEffect } from 'react' // I need this to resolve to next-app/node_modules/react
export function() {
useEffect(() => {} , [])
return <></>
}
// component-b
import ComponentA from "../app-a/component-a"
export function() {
return <ComponentA />
}
The issue I am having is that we are migrating to a Next.JS app (next-app) but we want to continue to import components from (app-a). app-a is stuck for now on react 17.x.x but Next.JS is using 18.x.x. So when next-app is built, I need all react imports to resolve to react 18.x.x. At the time of writing this post we are using the experimental.externalDir setting to allow for importing components from outside the root of the next.js app.
The crux of it is that when importing from app-a I still need react to resolve to next-app/node_modules/react.
Webpack aliases seem to be the recommended answer generally but they don't appear to apply correctly in this situation.
I have solved this specific problem by using the next config transpilePackages list. Some dependencies that are dependent on react are causing the react version mismatch by importing react from the root node_modules. By including these packages in the transpilePackages list in the next config, it seems that next is pre-compiling these libs using the correct react version.
Example:
// next.config.js
const nextConfig = {
...other_config,
transpilePackages: ["react-focus-lock"],
}
Unfortunately I haven't fully appreciated why this imports the correct react dependency while using webpack resolve aliases does not.

Typescript not compiling enum in symlinked folder

EDIT: Unfortunately this seems like a known issue that cannot be solved without messing with create-react-app, although I could be wrong :( https://github.com/facebook/create-react-app/issues/3547#issuecomment-593764097
I am working on a react project using typescript and firebase functions, with my firebase functions project folder inside the project folder for the react app. As there are lots of enums and interfaces that I want to keep consistent between my frontend (the react app) and my backend (the firebase functions), I use a symlink to share a folder containing files common between these two projects. This works fine with interfaces, but causes errors when I try to use an enum exported from this symlinked folder:
ERROR in ./functions/src/shared-types/roles.ts 3:0
Module parse failed: The keyword 'enum' is reserved (3:0)
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/source-map-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
| __webpack_require__.$Refresh$.runtime = require('/Users/joel/my-project/node_modules/react-refresh/runtime.js');
|
> enum Roles {
| Admin = 'Admin',
| Access = 'Access',
Repro
Starting from a fresh create-react-app with typescript support, add a folder called shared-types at the same level as src and put a file in it called MyEnum.ts:
// shared-types/MyEnum.ts
enum MyEnum {
Foo = "foo",
Bar = "bar"
}
export default MyEnum;
Then, make a symlink between that folder and another one also called shared-types inside src:
$ ln -s /path/to/project/shared-types /path/to/project/src/shared-types
Then, import and use MyEnum in App.tsx:
// src/App.tsx
import React from 'react';
import './App.css';
import MyEnum from "./shared-types/MyEnum";
function App() {
return (
<div className="App">
<h1>{MyEnum.Bar}</h1>
</div>
);
}
export default App;
Finally, just run npm start:
ERROR in ./shared-types/MyEnum.ts 3:0
Module parse failed: The keyword 'enum' is reserved (3:0)
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/source-map-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
| __webpack_require__.$Refresh$.runtime = require('/Users/joel/repro/node_modules/react-refresh/runtime.js');
|
> enum MyEnum {
| Foo = 'foo',
| Bar = 'bar',
Things that aren't causing it
It's not that typescript is ignoring the shared-types folder, as everything compiles fine if you add an interface to that folder and use it in App.tsx. Plus, running tsc --listFilesOnly will return a list including /path/to/project/src/shared-types/MyEnum.tsc.
It's not that my version of typescript doesn't support enums or that enums are disabled, as everything works fine if you add an enum to App.tsx itself.
Thanks in advance for the help! And feel free to suggest better ways of sharing files between these two projects in the comments if there are any!
It turns out that create-react-app doesn't support symlinks under src at all! The fact that the interface stuff worked at all seems to be a fluke.
https://github.com/facebook/create-react-app/issues/3547
This seems to have been a known issue for four years, but there is no blessed solution to it yet. 🫤

Exporting from one library if web, another library if native in React Native

So I am trying to use Victory Charts (https://formidable.com/open-source/victory) and would prefer to not just use a webview, as they've got a native implementation.
However, I am trying to use the library with React Native Web, and it does not work at all, I get the following error:
/Users/myname/Desktop/Projects/myproject/Frontend/Expo/node_modules/victory-native/lib/components/victory-axis.js 10:22
Module parse failed: Unexpected token (10:22)
You may need an appropriate loader to handle this file type.
|
| export default class extends VictoryAxis {
> static defaultProps = Object.assign({}, VictoryAxis.defaultProps, {
| axisComponent: <LineSegment/>,
| axisLabelComponent: <VictoryLabel/>,
My guess is that I'll need to use two "wrapper" files, Victory.js and Victory.web.js for importing.
Here is my Victory.web.js file so far:
Victory = require('victory');
export default Victory;
This does not work.
I have also tried:
import { VictoryPie } from 'victory';
export VictoryPie;
Which gives me the error:
/Users/myname/Desktop/Projects/myproject/Frontend/Expo/src/components/utility/Victory.web.js
SyntaxError: /Users/myname/Desktop/Projects/myproject/Frontend/Expo/src/components/utility/Victory.web.js: Unexpected token (3:17)
1 | import { VictoryPie } from 'victory';
2 |
> 3 | export VictoryPie;
I just want to be able to use this library on both React Native and React Native Web without it throwing errors. Is there any way to do so?
Not sure if this is the best way to do it, but this way worked for me:
export const VictoryPie = require('victory').VictoryPie;

"The keyword 'interface' is reserved" when using LernaJS

Can not seem to run NextJs in development (next dev) when using Lerna. I can get other files to pull in just fine (e.g images) but it doens't seem to process TS on the fly using this method. Anybody have any thoughts on this?
ModuleParseError: Module parse failed: The keyword 'interface' is reserved (3:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import React from "react";
|
> interface Props {
| name: string;
| }
packages/shared/components/Example.tsx
import React from "react";
interface Props {
name: string;
}
export const Example = ({ name }: Props) => {
return <div>Name: {name}</div>;
};
packages/web/pages/index.tsx
import { Example } from "shared/components/Example";
This is something that is being worked on/considered and supposedly might actually work already in some cases, but I was not able to make baseUrl work for me.
In the mean time per Jacob Rask's suggestion you should use next-transpile-modules. I was struggling with this issue myself, and this finally worked!

How to setup Vue.JS to have JSX and TypeScript working together

JSX works perfectly in my Vue.JS project ... Unless I use typescript.
I create a Vue.JS project without typescript
vue create test
cd test
npm run serve
I replace HelloWorld.vue by
<script>
import Vue from 'vue';
export default Vue.extend({
name: 'HelloWorld',
render(){return (<p>JSX !</p>)},
});
</script>
And it's working perfectly
I make an other project, but with typescript, replace again HelloWorld.vue, I get an error
Module parse failed: Unexpected token (4:35)
You may need an appropriate loader to handle this file type.
| export default Vue.extend({
| name: 'HelloWorld',
> render: function (h) { return (<p>JSX !</p>); }
| });
|
I've tried every thin clue I've found on internet: I've tried writting HelloWorld.tsx instead, configuring babel or tsconfig, I've tried creating jsx.d.ts, installing more packages, ... Everytime I get exactly this error.
Could anybody give me the magic recipe for having a Vue.JS project with both JSX and typescript ?

Categories