Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{ targets: { node: 'current' }, modules: 'commonjs' },
],
['@babel/preset-react', { runtime: 'classic' }],
],
plugins: [
['@babel/plugin-transform-class-properties', { loose: true }],
['@babel/plugin-transform-object-rest-spread', { loose: true }],
],
};

20 changes: 20 additions & 0 deletions jest.a11y.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Hermetic Jest config for a11y tests only
module.exports = {
rootDir: __dirname,
displayName: 'a11y',
testEnvironment: 'jsdom',
testRunner: 'jest-circus/runner',
// Disable Babel transforms to avoid picking up legacy .babelrc
transform: {},
moduleFileExtensions: ['js', 'json', 'jsx'],
transformIgnorePatterns: ['<rootDir>/node_modules/'],
testEnvironmentOptions: { url: 'http://localhost' },
testMatch: [
'**/?(*.)+(a11y.test).js?(x)',
'**/?(*.)+(a11y.test).jsx',
],
collectCoverage: true,
coverageDirectory: 'coverage/a11y',
coverageProvider: 'v8',
coverageThreshold: {},
};
6 changes: 6 additions & 0 deletions jest.a11y.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Jest a11y setup: RTL matchers and jest-axe matcher
require('@testing-library/jest-dom');
const { toHaveNoViolations } = require('jest-axe');

expect.extend(toHaveNoViolations);

89 changes: 65 additions & 24 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,72 @@
// https://jestjs.io/docs/en/configuration.html
// Ensure Enzyme is configured even if setupFiles resolution fails in CI
const path = require('path');

// Define File/Blob early to satisfy undici/jsdom when the environment initializes
(() => {
try {
if (typeof globalThis.File === 'undefined') {
const { File } = require('fetch-blob/file.js');
globalThis.File = File;
}
if (typeof globalThis.Blob === 'undefined') {
const { Blob } = require('buffer');
globalThis.Blob = globalThis.Blob || Blob;
}
// Polyfill Web Streams API early (ReadableStream, etc.) before undici/jsdom loads
if (typeof globalThis.ReadableStream === 'undefined') {
try {
const streams = require('web-streams-polyfill/ponyfill/es2018');
const { ReadableStream, WritableStream, TransformStream } = streams;
globalThis.ReadableStream = ReadableStream;
if (typeof globalThis.WritableStream === 'undefined') {
globalThis.WritableStream = WritableStream;
}
if (typeof globalThis.TransformStream === 'undefined') {
globalThis.TransformStream = TransformStream;
}
} catch (e) {
// ignore if polyfill missing; Node >=18 typically provides these
}
}
} catch (e) {
// If fetch-blob isn't available, the custom env will attempt to define File later
}
})();

require(path.resolve(__dirname, 'enzyme.config.js'));

module.exports = {
// Automatically clear mock calls and instances between every test
clearMocks: true,
collectCoverage: true,
collectCoverageFrom: ['react/**/*.{js,jsx,mjs}', '!js/components/Consonant/Testing/**'],
collectCoverageFrom: [
'react/src/js/**/*.{js,jsx,mjs}',
'!react/src/js/**/__tests__/**',
'!react/src/js/**/__test__/**',
'!react/src/js/components/Consonant/Testing/**',
'!react/src/js/components/Consonant/Helpers/TestingConstants/**',
'!react/src/js/components/Consonant/Modal/**',
'!react/src/js/components/Consonant/types/**',
// Temporarily exclude Container until we add fuller state coverage
'!react/src/js/components/Consonant/Container/Container.jsx',
'!react/src/js/**/polyfills.js',
'!react/src/js/**/watch.js',
'!react/src/js/**/ConsonantPageDOM.jsx',
'!react/src/js/**/app.jsx',
'!react/src/js/index.js',
],

coveragePathIgnorePatterns: [
'Modal',
'js/components/Consonant/Testing/',
'app.jsx',
'ConsonantPageDOM.jsx',
'polyfills.js',
'watch.js',
'react/src/js/components/Consonant/Testing/',
'js/components/Consonant/Helpers/TestingConstants',
'react/src/js/components/Consonant/Helpers/TestingConstants',
'app\\.jsx$',
'ConsonantPageDOM\\.jsx$',
'polyfills\\.js$',
'watch\\.js$',
],

// The directory where Jest should output its coverage files
Expand All @@ -34,14 +84,20 @@ module.exports = {

coverageProvider: 'babel',

// Pre-test setup files (polyfills)
setupFiles: [
'whatwg-fetch',
'<rootDir>/jest.setup.js',
],

// An array of file extensions your modules use
moduleFileExtensions: ['js', 'json', 'jsx'],

// Setup again inside test environment for safety across runners
setupFilesAfterEnv: [path.resolve(__dirname, 'enzyme.config.js')],

// The test environment that will be used for testing
testEnvironment: 'jsdom',
testEnvironment: '<rootDir>/jest.env.jsdom.file.js',

// Use Babel 7 just for Jest, ignoring project .babelrc (Babel 6)
transform: {
Expand All @@ -62,24 +118,6 @@ module.exports = {
plugins: [
['@babel/plugin-transform-class-properties', { loose: true }],
['@babel/plugin-transform-object-rest-spread', { loose: true }],
[
'istanbul',
{
exclude: [
'**/Modal/**',
'**/js/components/Consonant/Testing/**',
'**/app.jsx',
'**/ConsonantPageDOM.jsx',
'**/polyfills.js',
'**/watch.js',
'**/js/components/Consonant/Helpers/TestingConstants/**',
'**/__tests__/**',
'**/__test__/**',
'**/enzyme.config.js',
'**/*.config.js',
],
},
],
],
},
],
Expand All @@ -92,6 +130,9 @@ module.exports = {

testEnvironmentOptions: { url: 'http://localhost' },
transformIgnorePatterns: ['<rootDir>/node_modules/'],
moduleNameMapper: {
'^undici$': '<rootDir>/tests/setup/undici-shim.js',
},

// Indicates whether each individual test should be reported during the run
verbose: false,
Expand Down
56 changes: 56 additions & 0 deletions jest.env.jsdom.file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Custom Jest environment that ensures global File is defined before jsdom/undici loads
let JsdomEnvironment;

// Define critical Web APIs before requiring jest-environment-jsdom (which pulls in jsdom/undici)
(() => {
try {
// File polyfill
if (typeof globalThis.File === 'undefined') {
const { File } = require('fetch-blob/file.js');
globalThis.File = File;
}
} catch (e) {
// ignore
}

try {
// Blob fallback
if (typeof globalThis.Blob === 'undefined') {
const { Blob } = require('buffer');
if (Blob) globalThis.Blob = Blob;
}
} catch (e) {
// ignore
}

try {
// Web Streams: prefer Node's built-in implementation
if (typeof globalThis.ReadableStream === 'undefined') {
const ws = require('node:stream/web');
if (ws && ws.ReadableStream) {
globalThis.ReadableStream = ws.ReadableStream;
if (typeof globalThis.WritableStream === 'undefined' && ws.WritableStream) {
globalThis.WritableStream = ws.WritableStream;
}
if (typeof globalThis.TransformStream === 'undefined' && ws.TransformStream) {
globalThis.TransformStream = ws.TransformStream;
}
}
}
} catch (e) {
// ignore
}

// Defer requiring environment until after polyfills
// eslint-disable-next-line global-require
const EnvMod = require('jest-environment-jsdom');
JsdomEnvironment = EnvMod && (EnvMod.default || EnvMod.TestEnvironment || EnvMod);
})();

class JSDOMWithFileEnv extends JsdomEnvironment {
constructor(config, context) {
super(config, context);
}
}

module.exports = JSDOMWithFileEnv;
50 changes: 50 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Polyfills to stabilize test environment in Node 16 + jsdom

// Web Streams API polyfill for environments lacking ReadableStream, etc.
(() => {
if (typeof globalThis.ReadableStream === 'undefined') {
try {
const streams = require('web-streams-polyfill/ponyfill/es2018');
const { ReadableStream, WritableStream, TransformStream } = streams;
globalThis.ReadableStream = ReadableStream;
if (typeof globalThis.WritableStream === 'undefined') {
globalThis.WritableStream = WritableStream;
}
if (typeof globalThis.TransformStream === 'undefined') {
globalThis.TransformStream = TransformStream;
}
} catch (e) {
// If the polyfill isn't available, tests that rely on fetch/streams may fail in Node <18.
}
}
})();

// Ensure Fetch API globals (including File) are available for libraries using undici
(() => {
try {
const u = require('undici');
if (typeof globalThis.fetch === 'undefined' && typeof u.fetch === 'function') {
globalThis.fetch = u.fetch;
}
if (typeof globalThis.Headers === 'undefined' && typeof u.Headers !== 'undefined') {
globalThis.Headers = u.Headers;
}
if (typeof globalThis.Request === 'undefined' && typeof u.Request !== 'undefined') {
globalThis.Request = u.Request;
}
if (typeof globalThis.Response === 'undefined' && typeof u.Response !== 'undefined') {
globalThis.Response = u.Response;
}
if (typeof globalThis.FormData === 'undefined' && typeof u.FormData !== 'undefined') {
globalThis.FormData = u.FormData;
}
if (typeof globalThis.Blob === 'undefined' && typeof u.Blob !== 'undefined') {
globalThis.Blob = u.Blob;
}
if (typeof globalThis.File === 'undefined' && typeof u.File !== 'undefined') {
globalThis.File = u.File;
}
} catch (e) {
// undici not available; ignore
}
})();
Loading