Skip to content

Commit

Permalink
Add tests for CSS Modules with React
Browse files Browse the repository at this point in the history
  • Loading branch information
Kocal committed Sep 20, 2024
1 parent dbd5e5d commit 8f3aef2
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 5 deletions.
12 changes: 12 additions & 0 deletions fixtures/react-css-modules/components/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import './styles.css';
import './styles.less';
import './styles.scss';
import './styles.stylus';
import stylesCss from './styles.module.css?module';
import stylesLess from './styles.module.less?module';
import stylesScss from './styles.module.scss?module';
import stylesStylus from './styles.module.stylus?module';

export default function App() {
return <div className={`red large justified lowercase ${stylesCss.italic} ${stylesLess.underline} ${stylesScss.bold} ${stylesStylus.rtl}`}></div>
}
3 changes: 3 additions & 0 deletions fixtures/react-css-modules/components/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.red {
color: red;
}
3 changes: 3 additions & 0 deletions fixtures/react-css-modules/components/styles.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.justified {
text-align: justify;
}
3 changes: 3 additions & 0 deletions fixtures/react-css-modules/components/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.italic {
font-style: italic;
}
3 changes: 3 additions & 0 deletions fixtures/react-css-modules/components/styles.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.underline {
text-decoration: underline;
}
3 changes: 3 additions & 0 deletions fixtures/react-css-modules/components/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.bold {
font-weight: bold;
}
2 changes: 2 additions & 0 deletions fixtures/react-css-modules/components/styles.module.stylus
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.rtl
direction: rtl;
3 changes: 3 additions & 0 deletions fixtures/react-css-modules/components/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.large {
font-size: 50px;
}
2 changes: 2 additions & 0 deletions fixtures/react-css-modules/components/styles.stylus
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.lowercase
text-transform: lowercase
6 changes: 6 additions & 0 deletions fixtures/react-css-modules/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {createRoot} from 'react-dom/client';
import App from './components/App';

const root = createRoot(document.getElementById('app'));

root.render(<App />);
5 changes: 4 additions & 1 deletion lib/loaders/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ module.exports = {
if (webpackConfig.useReact) {
loaderFeatures.ensurePackagesExistAndAreCorrectVersion('react');

babelConfig.presets.push(require.resolve('@babel/preset-react'));
babelConfig.presets.push([require.resolve('@babel/preset-react'), {
// TODO: To remove when Babel 8, "automatic" will become the default value
runtime: 'automatic',
}]);
}

if (webpackConfig.usePreact) {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@babel/eslint-parser": "^7.17.0",
"@babel/plugin-transform-react-jsx": "^7.12.11",
"@babel/preset-env": "^7.16.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-react": "^7.9.0",
"@babel/preset-typescript": "^7.0.0",
"@hotwired/stimulus": "^3.0.0",
"@symfony/mock-module": "file:fixtures/stimulus/mock-module",
Expand Down Expand Up @@ -81,6 +81,8 @@
"preact": "^10.5.0",
"preact-compat": "^3.17.0",
"puppeteer": "^23.2.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"sass": "^1.17.0",
"sass-loader": "^16.0.1",
"sinon": "^14.0.0",
Expand Down
83 changes: 82 additions & 1 deletion test/functional.js
Original file line number Diff line number Diff line change
Expand Up @@ -1720,6 +1720,88 @@ module.exports = {
});
});

it('React supports CSS/Sass/Less/Stylus modules', (done) => {
const appDir = testSetup.createTestAppDir();
const config = testSetup.createWebpackConfig(appDir, 'www/build', 'dev');
config.enableSingleRuntimeChunk();
config.setPublicPath('/build');
config.addEntry('main', './react-css-modules/main.js');
config.enableReactPreset();
config.enableSassLoader();
config.enableLessLoader();
config.enableStylusLoader();
config.configureCssLoader(options => {
// Remove hashes from local ident names
// since they are not always the same.
if (options.modules) {
options.modules.localIdentName = '[local]_foo';
}
});

// Enable the PostCSS loader so we can use `lang="postcss"`
config.enablePostCssLoader();
fs.writeFileSync(
path.join(appDir, 'postcss.config.js'),
`
module.exports = {
plugins: [
require('autoprefixer')()
]
} `
);

testSetup.runWebpack(config, (webpackAssert) => {
expect(config.outputPath).to.be.a.directory().with.deep.files([
'main.js',
'main.css',
'manifest.json',
'entrypoints.json',
'runtime.js',
]);

const expectClassDeclaration = (className) => {
webpackAssert.assertOutputFileContains(
'main.css',
`.${className} {`
);
};

expectClassDeclaration('red'); // Standard CSS
expectClassDeclaration('large'); // Standard SCSS
expectClassDeclaration('justified'); // Standard Less
expectClassDeclaration('lowercase'); // Standard Stylus

expectClassDeclaration('italic_foo'); // CSS Module
expectClassDeclaration('bold_foo'); // SCSS Module
expectClassDeclaration('underline_foo'); // Less Module
expectClassDeclaration('rtl_foo'); // Stylus Module

testSetup.requestTestPage(
browser,
path.join(config.getContext(), 'www'),
[
'build/runtime.js',
'build/main.js'
],
async({ page }) => {
const divClassArray = await page.evaluate(() => Array.from(document.body.querySelector('#app > div').classList.values()));

expect(divClassArray.includes('red')).to.be.true; // Standard CSS
expect(divClassArray.includes('large')).to.be.true; // Standard SCSS
expect(divClassArray.includes('justified')).to.be.true; // Standard Less
expect(divClassArray.includes('lowercase')).to.be.true; // Standard Stylus

expect(divClassArray.includes('italic_foo')).to.be.true; // CSS module
expect(divClassArray.includes('bold_foo')).to.be.true; // SCSS module
expect(divClassArray.includes('underline_foo')).to.be.true; // Less module
expect(divClassArray.includes('rtl_foo')).to.be.true; // Stylus module

done();
}
);
});
});

it('Preact supports CSS/Sass/Less/Stylus modules', (done) => {
const appDir = testSetup.createTestAppDir();
const config = testSetup.createWebpackConfig(appDir, 'www/build', 'dev');
Expand Down Expand Up @@ -1802,7 +1884,6 @@ module.exports = {
});
});


it('Vue.js error when using non-activated loaders', (done) => {
const config = createWebpackConfig('www/build', 'dev');
config.setPublicPath('/build');
Expand Down
26 changes: 24 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@
"@babel/types" "^7.4.4"
esutils "^2.0.2"

"@babel/preset-react@^7.0.0":
"@babel/preset-react@^7.9.0":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.7.tgz#480aeb389b2a798880bf1f889199e3641cbb22dc"
integrity sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==
Expand Down Expand Up @@ -4851,7 +4851,7 @@ log-symbols@^4.1.0:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"

loose-envify@^1.0.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
Expand Down Expand Up @@ -5918,11 +5918,26 @@ raw-body@2.5.2:
iconv-lite "0.4.24"
unpipe "1.0.0"

react-dom@^18.0.0:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.2"

react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==

react@^18.0.0:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
dependencies:
loose-envify "^1.1.0"

readable-stream@^2.0.1:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
Expand Down Expand Up @@ -6183,6 +6198,13 @@ sax@~1.3.0:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0"
integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==

scheduler@^0.23.2:
version "0.23.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
dependencies:
loose-envify "^1.1.0"

schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
Expand Down

0 comments on commit 8f3aef2

Please sign in to comment.