From 34b9d1b91d3de6c87a7d27f7cd02a13836bc2cc5 Mon Sep 17 00:00:00 2001 From: MariaAga Date: Tue, 9 Jul 2024 19:39:18 +0100 Subject: [PATCH] Fixes #37637 - Test plugins from foreman core --- .eslintrc | 6 +- .github/workflows/plugins_react_tests.yml | 30 +++- babel.config.js | 4 + package-exclude.json | 1 + package.json | 23 ++- script/npm_test_plugin.js | 139 ++++++++++++++++++ script/plugin_webpack_directories.js | 18 +++ .../TemplateGeneratorActions.test.js | 12 +- webpack/{test_setup.js => core_test_setup.js} | 7 + webpack/global_test_setup.js | 19 +++ webpack/jest.config.js | 80 ++++++++++ webpack/resolveNodeModule.js | 61 ++++++++ webpack/theforeman-test.js | 36 +++++ webpack/theforeman_test_dependencies.js | 36 +++++ 14 files changed, 458 insertions(+), 14 deletions(-) create mode 100644 babel.config.js create mode 100755 script/npm_test_plugin.js rename webpack/{test_setup.js => core_test_setup.js} (73%) create mode 100644 webpack/global_test_setup.js create mode 100644 webpack/jest.config.js create mode 100644 webpack/resolveNodeModule.js create mode 100644 webpack/theforeman-test.js create mode 100644 webpack/theforeman_test_dependencies.js diff --git a/.eslintrc b/.eslintrc index 0de7f9bd00b..fd4ccd83cf5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -24,6 +24,7 @@ "auditable", "Autocompletion", "autogenerated", + "axios", "bool", "bootable", "Borderless", @@ -107,6 +108,7 @@ "noopener", "noreferrer", "nowrap", + "npx", "num", "numpad", "operatingsystem", @@ -159,6 +161,7 @@ "textarea", "textfield", "tfm", + "theforeman", "timepicker", "timerdelay", "timeseries", @@ -192,6 +195,7 @@ "minLength": 3 } ], - "@theforeman/rules/require-ouiaid": ["error"] + "@theforeman/rules/require-ouiaid": ["error"], + "import/no-extraneous-dependencies": "off", } } diff --git a/.github/workflows/plugins_react_tests.yml b/.github/workflows/plugins_react_tests.yml index 7d0f7184b7c..551b3e9c710 100644 --- a/.github/workflows/plugins_react_tests.yml +++ b/.github/workflows/plugins_react_tests.yml @@ -16,6 +16,9 @@ concurrency: group: ${{ github.ref_name }}-${{ github.workflow }} cancel-in-progress: true +env: + BUNDLE_WITHOUT: "console:development:journald:libvirt" + jobs: setup_matrix: name: Setup matrix @@ -45,11 +48,11 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - # We could update the postinstall action for foreman to look for an environment variable for plugin webpack dirs - # before kicking off the ruby script to find them, this would eliminate the ruby dep and running `npm install` in plugins. - - uses: ruby/setup-ruby@v1 + - name: "Set up Ruby ${{ matrix.ruby }}" + uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} + bundler-cache: true - name: Checkout Foreman uses: actions/checkout@v4 with: @@ -65,12 +68,29 @@ jobs: with: repository: ${{ matrix.plugin }} path: ${{ github.workspace }}/projects/plugin + - name: store plugin name + run: echo "PLUGIN_NAME=$(echo ${{ matrix.plugin }} | awk -F'/' '{print $NF}')" >> "${GITHUB_ENV}" + - name: Set up plugin in Foreman + run: | + echo "gemspec name: '$PLUGIN_NAME', path: '${{ github.workspace }}/projects/plugin'" > "bundler.d/$PLUGIN_NAME.local.rb" + if [ -d $PLUGIN_NAME/gemfile.d ] ; then + cat $PLUGIN_NAME/gemfile.d/*.rb >> bundler.d/$PLUGIN_NAME.local.rb + fi + working-directory: ${{ github.workspace }}/projects/foreman - name: Generate ${{ matrix.plugin }} npm dependencies package-lock run: npm install --package-lock-only --no-audit --legacy-peer-deps working-directory: ${{ github.workspace }}/projects/plugin - name: Install ${{ matrix.plugin }} npm dependencies run: npm ci --no-audit --legacy-peer-deps working-directory: ${{ github.workspace }}/projects/plugin + - run: sudo apt-get update + - run: sudo apt-get -qq -y install build-essential libcurl4-openssl-dev zlib1g-dev libpq-dev libvirt-dev + - name: Install gems + run: bundle install + working-directory: ${{ github.workspace }}/projects/foreman + - name: Run plugin webpack dir to test + run: ./script/plugin_webpack_directories.rb + working-directory: ${{ github.workspace }}/projects/foreman - name: Run ${{ matrix.plugin }} tests - run: npm test - working-directory: ${{ github.workspace }}/projects/plugin + run: npm run test:plugins $(echo ${{ matrix.plugin }} | awk -F'/' '{print $NF}') + working-directory: ${{ github.workspace }}/projects/foreman diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000000..e55bdc5f95a --- /dev/null +++ b/babel.config.js @@ -0,0 +1,4 @@ +module.exports = { + presets: [require.resolve('@theforeman/builder/babel')], + plugins: [require.resolve('babel-plugin-dynamic-import-node')], +}; diff --git a/package-exclude.json b/package-exclude.json index 3b9dabad042..747d37d055f 100644 --- a/package-exclude.json +++ b/package-exclude.json @@ -1,5 +1,6 @@ { "EXCLUDE_NPM_PACKAGES": [ + "@apollo/react-testing", "@sheerun/mutationobserver-shim", "@theforeman/env", "@theforeman/eslint-plugin-foreman", diff --git a/package.json b/package.json index 98a59097288..283d1082472 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,10 @@ "lint:custom": "eslint ./webpack", "foreman-js:link": "./script/npm_link_foreman_js.sh", "postlint": "./script/npm_lint_plugins.js", - "test": "tfm-test", + "test": "npx jest --setupFilesAfterEnv ./global_test_setup.js ./core_test_setup.js --testPathIgnorePatterns '/node_modules/' '/.+fixtures.+' --config ./webpack/jest.config.js", "test:watch": "tfm-test --watchAll", "test:current": "tfm-test --watch", + "test:plugins": "./script/npm_test_plugin.js", "publish-coverage": "tfm-publish-coverage", "postinstall": "./script/npm_install_plugins.js", "analyze": "./script/webpack-analyze" @@ -29,28 +30,45 @@ "react-intl": "^2.8.0" }, "devDependencies": { + "@apollo/react-testing": "^4.0.0", "@babel/core": "^7.7.0", + "@testing-library/jest-dom": "^5.3.0", + "@testing-library/react": "^10.0.2", + "@testing-library/react-hooks": "^3.4.2", "@theforeman/builder": "^13.1.0", "@theforeman/eslint-plugin-foreman": "^13.1.0", "@theforeman/eslint-plugin-rules": "^13.1.0", - "@theforeman/test": "^13.1.0", + "@theforeman/vendor-core": "^13.1.0", "@theforeman/vendor-dev": "^13.1.0", "@types/jest": "<27.0.0", "argv-parse": "^1.0.1", + "axios-mock-adapter": "^1.1.7", "babel-eslint": "^10.0.0", + "babel-jest": "^26.3.0", "babel-loader": "^8.0.0", "buffer": "^5.7.1", + "cheerio": "1.0.0-rc.10", "compression-webpack-plugin": "^10.0.0", "cross-env": "^5.2.0", "css-loader": "^6.8.1", "dotenv": "^5.0.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-to-json": "^3.4.3", "eslint": "^6.7.2", "eslint-plugin-spellcheck": "0.0.17", "graphql": "^15.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^26.4.0", + "jest-prop-type-error": "^1.1.0", + "jest-svg-transformer": "^1.0.0", + "jest-transform-graphql": "^2.1.0", "path-browserify": "^1.0.1", "prettier": "^1.19.1", "pretty-format": "26.6.2", "react-dnd-test-backend": "^9.4.0", + "react-redux-test-utils": "^0.2.0", + "react-test-renderer": "^17.0.1", "redux-mock-store": "^1.2.2", "sass": "~1.60.0", "sass-loader": "^13.3.2", @@ -59,6 +77,7 @@ "stylelint-config-standard": "^18.0.0", "tabbable": "~5.2.0", "victory-core": "~36.8.6", + "victory-legend": "~36.8.6", "victory-pie": "~36.8.6", "webpack": "^5.75.0", "webpack-bundle-analyzer": "^4.5.0", diff --git a/script/npm_test_plugin.js b/script/npm_test_plugin.js new file mode 100755 index 00000000000..cd8e8b54230 --- /dev/null +++ b/script/npm_test_plugin.js @@ -0,0 +1,139 @@ +#!/usr/bin/env node +/* eslint-disable import/no-dynamic-require */ +/* eslint-disable no-console */ +/* eslint-disable no-var */ + +/* This script is used to run tests for all plugins that have a `lint` script defined in their package.json + To run tests for an individual plugin, pass the plugin name as the first argument to the script + For example, to run tests for the `foreman-tasks` plugin, run: `npm run test-plugin foreman-tasks` + To pass arguments to jest, pass them after the plugin name like so: `npm run test-plugin foreman-tasks -- --debug` +*/ + +var fs = require('fs'); +var path = require('path'); +var lodash = require('lodash'); +var childProcess = require('child_process'); +var { packageJsonDirsObject } = require('./plugin_webpack_directories'); + +const passedArgs = process.argv.slice(2); +const coreConfigPath = path.resolve(__dirname, '../webpack/jest.config.js'); +const coreConfig = require(coreConfigPath); + +function runChildProcess(args, pluginPath) { + return new Promise((resolve, reject) => { + const child = childProcess.spawn('npx', args, { + shell: true, + }); + // this is needed to make sure the output is not cut + let stdoutBuffer = ''; + child.stdout.on('data', data => { + stdoutBuffer += data.toString(); + const lines = stdoutBuffer.split('\n'); + stdoutBuffer = lines.pop(); + }); + + let stderrBuffer = `${pluginPath}: \n`; + child.stderr.on('data', data => { + stderrBuffer += data.toString(); + const lines = stderrBuffer.split('\n'); + stderrBuffer = lines.pop(); + lines.forEach(line => console.error(line)); + }); + child.on('close', code => { + if (stdoutBuffer) console.log(stdoutBuffer); + if (stderrBuffer) console.error(stderrBuffer); + if (code === 0) { + resolve(); + } else { + reject(new Error(`Child process exited with code ${code}`)); + } + }); + }); +} +const runTests = async () => { + var dirs = packageJsonDirsObject(); + var dirsKeys = Object.keys(dirs); + function pluginDefinesLint(pluginPath) { + var packageHasNodeModules = fs.existsSync(`${pluginPath}/node_modules`); // skip gems + var packageData = JSON.parse(fs.readFileSync(`${pluginPath}/package.json`)); + + return ( + packageHasNodeModules && packageData.scripts && packageData.scripts.lint + ); + } + if (passedArgs[0] && passedArgs[0][0] !== '-') { + dirsKeys = dirsKeys.filter(dir => dir.endsWith(passedArgs[0])); + passedArgs.shift(); + } + function customizer(objValue, srcValue) { + if (lodash.isArray(objValue)) { + return lodash.uniq(objValue.concat(srcValue)); + } + return undefined; + } + // eslint-disable-next-line no-unused-vars + for (const dirsKey of dirsKeys) { + const pluginPath = dirs[dirsKey]; + if (pluginDefinesLint(pluginPath)) { + const testSetupFiles = [ + path.resolve(__dirname, '../webpack/global_test_setup.js'), + ]; + const testSetupPath = path.join(pluginPath, 'webpack', 'test_setup.js'); + if (fs.existsSync(testSetupPath)) { + testSetupFiles.unshift(testSetupPath); + } + const pluginConfigPath = path.join(pluginPath, 'jest.config.js'); + const combinedConfigPath = path.join( + pluginPath, + 'combined.jest.config.js' + ); + + if (fs.existsSync(pluginConfigPath)) { + // eslint-disable-next-line global-require + const pluginConfig = require(pluginConfigPath); + + const combinedConfig = lodash.mergeWith( + pluginConfig, + { + ...coreConfig, + setupFilesAfterEnv: [ + path.resolve(__dirname, '../webpack/global_test_setup.js'), + ], + }, + customizer + ); + combinedConfig.snapshotSerializers = coreConfig.snapshotSerializers; + fs.writeFileSync( + combinedConfigPath, + `module.exports = ${JSON.stringify(combinedConfig, null, 2)};`, + 'utf8' + ); + } + const pluginConfigOverride = fs.existsSync(pluginConfigPath); + const configPath = pluginConfigOverride + ? combinedConfigPath + : coreConfigPath; + const corePath = path.resolve(__dirname, '../'); + const args = [ + 'jest', + '--roots', + pluginPath, + corePath, + `--config=${configPath}`, + pluginConfigOverride + ? '' + : `--setupFilesAfterEnv ${testSetupFiles.join(' ')}`, + '--color', + ...passedArgs, + ]; + + // eslint-disable-next-line no-await-in-loop + await runChildProcess(args, pluginPath); // Run every plugin test in a separate process + if (fs.existsSync(combinedConfigPath)) { + fs.unlinkSync(combinedConfigPath); + } + } + } +}; + +runTests(); diff --git a/script/plugin_webpack_directories.js b/script/plugin_webpack_directories.js index 08d006e9c10..4436029d267 100644 --- a/script/plugin_webpack_directories.js +++ b/script/plugin_webpack_directories.js @@ -15,6 +15,19 @@ var sanitizeWebpackDirs = pluginDirs => { return splitDirs.length > 2 ? splitDirs[1] : pluginDirs; }; +var pluginPathObject = file => pluginsObj => { + var paths = {}; + Object.keys(pluginsObj.plugins).forEach(entryKey => { + if (!entryKey.includes(':')) { + const pluginPath = pluginsObj.plugins[entryKey].root; + if (fs.existsSync(path.join(pluginPath, file))) { + paths[entryKey] = pluginPath; + } + } + }); + return paths; +}; + // Get paths that have a specific file or folder var pluginPath = file => pluginsObj => { var paths = []; @@ -53,11 +66,16 @@ var getPluginDirs = stderr => var packageJsonDirs = stderr => pluginPath('package.json')(getPluginDirs(stderr)).map(path.dirname); +// Get plugin paths with the plugin name, dont assume the plugin path will have the pluin name +var packageJsonDirsObject = stderr => + pluginPathObject('package.json')(getPluginDirs(stderr)); + module.exports = { getPluginDirs, pluginNodeModules: pluginPath('node_modules'), aliasPlugins, packageJsonDirs, + packageJsonDirsObject, sanitizeWebpackDirs, pluginPath, }; diff --git a/webpack/assets/javascripts/react_app/components/TemplateGenerator/__tests__/TemplateGeneratorActions.test.js b/webpack/assets/javascripts/react_app/components/TemplateGenerator/__tests__/TemplateGeneratorActions.test.js index a3554f42fdb..05e8fba8f40 100644 --- a/webpack/assets/javascripts/react_app/components/TemplateGenerator/__tests__/TemplateGeneratorActions.test.js +++ b/webpack/assets/javascripts/react_app/components/TemplateGenerator/__tests__/TemplateGeneratorActions.test.js @@ -21,15 +21,16 @@ import * as actions from '../TemplateGeneratorActions'; jest.mock('file-saver'); jest.mock('../../../redux/API'); -beforeEach(() => { - API.post.mockImplementation(async () => scheduleResponse); - API.get.mockImplementation(async () => noContentResponse); -}); - describe('TemplateGeneratorActions', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); beforeEach(() => { API.post.mockClear(); API.get.mockClear(); + + API.post.mockImplementation(async () => scheduleResponse); + API.get.mockImplementation(async () => noContentResponse); }); describe('generateTemplate', () => { @@ -55,7 +56,6 @@ describe('TemplateGeneratorActions', () => { API.get .mockImplementationOnce(async () => noContentResponse) .mockImplementationOnce(async () => generatedReportResponse); - runActionInDepth(() => actions.generateTemplate(), 3).then(callTree => { const successAction = callTree[1][1][1]; expect(successAction).toHaveProperty('type', TEMPLATE_GENERATE_SUCCESS); diff --git a/webpack/test_setup.js b/webpack/core_test_setup.js similarity index 73% rename from webpack/test_setup.js rename to webpack/core_test_setup.js index c7158276891..d22b70ab381 100644 --- a/webpack/test_setup.js +++ b/webpack/core_test_setup.js @@ -6,13 +6,20 @@ ace.config.set('themePath', ''); jest.mock('jed'); jest.mock('./assets/javascripts/react_app/Root/Context/ForemanContext', () => ({ + getForemanContext: () => ({ + context: { metadata: { version: 'mocked_version' } }, + }), + useForemanContext: () => ({ metadata: { version: 'mocked_version' } }), + useForemanSetContext: () => {}, useForemanVersion: () => 'mocked_version', useForemanSettings: () => ({ perPage: 5 }), useForemanDocUrl: () => '/url', useForemanLocation: () => ({ title: 'location' }), useForemanOrganization: () => ({ title: 'organization' }), + useForemanUser: () => ({ login: 'user' }), getHostsPageUrl: displayNewHostsPage => displayNewHostsPage ? '/new/hosts' : '/hosts', + useForemanHostsPageUrl: () => '/hosts', })); jest.mock('./assets/javascripts/react_app/common/I18n'); jest.mock('./assets/javascripts/foreman_tools', () => ({ diff --git a/webpack/global_test_setup.js b/webpack/global_test_setup.js new file mode 100644 index 00000000000..de6724309e2 --- /dev/null +++ b/webpack/global_test_setup.js @@ -0,0 +1,19 @@ +// eslint-disable-next-line import/no-unresolved, import/extensions +import 'core-js/shim'; +// eslint-disable-next-line import/no-extraneous-dependencies +import 'regenerator-runtime/runtime'; + +const { configure } = require('enzyme'); +const Adapter = require('enzyme-adapter-react-16'); + +configure({ adapter: new Adapter() }); + +// https://github.com/facebook/jest/issues/6121 +// eslint-disable-next-line no-console +const { error } = console; +// eslint-disable-next-line no-console +console.error = (message, ...args) => { + error.apply(console, args); // keep default behaviour + const err = message instanceof Error ? message : new Error(message); + throw err; +}; diff --git a/webpack/jest.config.js b/webpack/jest.config.js new file mode 100644 index 00000000000..ee719d101cf --- /dev/null +++ b/webpack/jest.config.js @@ -0,0 +1,80 @@ +/* eslint-disable spellcheck/spell-checker */ +const fs = require('fs'); +const path = require('path'); +// const { modules: foremanJsModules } = require('@theforeman/vendor-core'); + +const nodeModules = path.resolve(__dirname, '..', 'node_modules'); +const packageJsonPath = path.resolve(__dirname, '..', 'package.json'); +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); +const vendorCorePackageJsonPath = path.resolve( + nodeModules, + '@theforeman/vendor-core', + 'package.json' +); +const vendorCorePackageJson = JSON.parse( + fs.readFileSync(vendorCorePackageJsonPath, 'utf8') +); + +const dependencies = { + ...packageJson.dependencies, + ...packageJson.devDependencies, + ...vendorCorePackageJson.dependencies, + '@apollo/client/testing': '@apollo/client/testing', +}; // Use shared dependencies from foreman node_modules and not plugin node_modules to avoid jest errors due to multiple instances of same package + +const moduleNameMapper = {}; +Object.keys(dependencies).forEach(dep => { + moduleNameMapper[`^${dep}$`] = path.resolve(nodeModules, dep); +}); + +const foremanReactFull = path.resolve( + __dirname, + 'assets/javascripts/react_app' +); +const foremanTest = path.resolve(__dirname, 'theforeman_test_dependencies.js'); + +module.exports = { + verbose: true, + logHeapUsage: true, + maxWorkers: 2, + collectCoverage: true, + coverageReporters: ['lcov'], + coverageDirectory: `../coverage`, + setupFiles: [require.resolve('jest-prop-type-error')], + testRegex: '.*\\.test\\.js$', + testPathIgnorePatterns: [ + '/node_modules/', + '/foreman/', + '/.+fixtures.+', + 'foreman/webpack', // dont test foreman core in plugins + ], + moduleDirectories: [ + `node_modules`, + `/node_modules/@theforeman/vendor-core/node_modules`, + `node_modules/@theforeman/vendor-core/node_modules`, + '/node_modules', + ], + transform: { + '^.+\\.js?$': 'babel-jest', + '\\.(gql|graphql)$': require.resolve('jest-transform-graphql'), // for graphql-tag + }, + snapshotSerializers: [require.resolve('enzyme-to-json/serializer')], + moduleNameMapper: { + '^.+\\.(png|gif|css|scss)$': 'identity-obj-proxy', + ...moduleNameMapper, + '^dnd-core$': `${nodeModules}/dnd-core/dist/cjs`, + '^react-dnd$': `${nodeModules}/react-dnd/dist/cjs`, + '^react-dnd-html5-backend$': `${nodeModules}/react-dnd-html5-backend/dist/cjs`, + '^react-dnd-touch-backend$': `${nodeModules}/react-dnd-touch-backend/dist/cjs`, + '^react-dnd-test-backend$': `${nodeModules}/react-dnd-test-backend/dist/cjs`, + '^react-dnd-test-utils$': `${nodeModules}/react-dnd-test-utils/dist/cjs`, + '^foremanReact(.*)$': `${foremanReactFull}/$1`, + '^@theforeman/test$': foremanTest, + '^victory(.*)$': `${nodeModules}/victory$1`, + }, + globals: { + __testing__: true, + URL_PREFIX: '', + }, + resolver: require.resolve('./resolveNodeModule'), +}; diff --git a/webpack/resolveNodeModule.js b/webpack/resolveNodeModule.js new file mode 100644 index 00000000000..8acba3b6474 --- /dev/null +++ b/webpack/resolveNodeModule.js @@ -0,0 +1,61 @@ +const { modules } = require('@theforeman/vendor-core'); + +const isRequestedByVendorCore = currentFileDirectory => + (currentFileDirectory.includes('foreman-js/packages/vendor-core') || + currentFileDirectory.includes('@theforeman/vendor-core')) && + !currentFileDirectory.includes( + 'foreman-js/packages/vendor-core/node_modules' + ) && + !currentFileDirectory.includes('@theforeman/vendor-core/node_modules'); + +const getModuleToResolve = ({ sourcePath, currentFileDirectory }) => { + // map the custom foreman js module to the correct path + const requestPath = sourcePath === '.' ? './index' : sourcePath; + const sourcePathSplit = sourcePath.split('/'); + const name = sourcePathSplit[sourcePathSplit.length - 1]; + const vendorModule = modules.find(m => m.name === name); + const requestedByVendorCore = isRequestedByVendorCore(currentFileDirectory); + + const shouldResolveCustomVendorModule = modules.find( + m => m.name === name && m.hasCustomPath && !requestedByVendorCore + ); + + return shouldResolveCustomVendorModule ? vendorModule.path : requestPath; +}; + +/** + * resolve a import/require of a node module + * this method should be calld by the jest-resolver + * to resolve every require statement + * This cannot be done with changing the paths with moduleNameMapper + */ + +const resolveNodeModule = (sourcePath, currentFile) => { + const { basedir, rootDir } = currentFile; + const moduleToResolve = getModuleToResolve({ + sourcePath, + currentFileDirectory: basedir, + }); + if (sourcePath.includes('theforeman_test_dependencies')) { + console.warn( + 'import from @theforeman/test is deprecated, please remove the package and import from enzyme, axios-mock-adapter, foremanReact/testHelpers, foremanReact/common/IntegrationTestHelper directly instead.' + ); + } + let results; + try { + results = require.resolve(moduleToResolve, { + paths: [basedir], + }); + } catch (error) { + results = currentFile.defaultResolver(moduleToResolve, currentFile); + } + + return rootDir + ? results.replace( + /.*\/foreman-js\/packages/, + `${rootDir}/node_modules/@theforeman` + ) + : results; +}; + +module.exports = resolveNodeModule; diff --git a/webpack/theforeman-test.js b/webpack/theforeman-test.js new file mode 100644 index 00000000000..eb747effd53 --- /dev/null +++ b/webpack/theforeman-test.js @@ -0,0 +1,36 @@ +// replaces @theforeman/test.js +import { shallow, mount, render, configure } from 'enzyme'; +import MockAdapter from 'axios-mock-adapter'; + +import { + mockWindowLocation, + classFunctionUnitTest, + shallowRenderComponentWithFixtures, + testComponentSnapshotsWithFixtures, + runActionInDepth, + testActionSnapshot, + testActionSnapshotWithFixtures, + testReducerSnapshotWithFixtures, + testSelectorsSnapshotWithFixtures, + initMockStore, +} from './assets/javascripts/react_app/common/testHelpers'; +import IntegrationTestHelper from './assets/javascripts/react_app/common/IntegrationTestHelper'; + +export { + mockWindowLocation, + classFunctionUnitTest, + shallowRenderComponentWithFixtures, + testComponentSnapshotsWithFixtures, + runActionInDepth, + testActionSnapshot, + testActionSnapshotWithFixtures, + testReducerSnapshotWithFixtures, + testSelectorsSnapshotWithFixtures, + initMockStore, + IntegrationTestHelper, + shallow, + mount, + render, + configure, + MockAdapter, +}; diff --git a/webpack/theforeman_test_dependencies.js b/webpack/theforeman_test_dependencies.js new file mode 100644 index 00000000000..eb747effd53 --- /dev/null +++ b/webpack/theforeman_test_dependencies.js @@ -0,0 +1,36 @@ +// replaces @theforeman/test.js +import { shallow, mount, render, configure } from 'enzyme'; +import MockAdapter from 'axios-mock-adapter'; + +import { + mockWindowLocation, + classFunctionUnitTest, + shallowRenderComponentWithFixtures, + testComponentSnapshotsWithFixtures, + runActionInDepth, + testActionSnapshot, + testActionSnapshotWithFixtures, + testReducerSnapshotWithFixtures, + testSelectorsSnapshotWithFixtures, + initMockStore, +} from './assets/javascripts/react_app/common/testHelpers'; +import IntegrationTestHelper from './assets/javascripts/react_app/common/IntegrationTestHelper'; + +export { + mockWindowLocation, + classFunctionUnitTest, + shallowRenderComponentWithFixtures, + testComponentSnapshotsWithFixtures, + runActionInDepth, + testActionSnapshot, + testActionSnapshotWithFixtures, + testReducerSnapshotWithFixtures, + testSelectorsSnapshotWithFixtures, + initMockStore, + IntegrationTestHelper, + shallow, + mount, + render, + configure, + MockAdapter, +};