Frank Borden | 68876a3 | 2022-09-14 11:39:16 +0200 | [diff] [blame^] | 1 | /** |
| 2 | * @license |
| 3 | * Copyright 2020 Google LLC |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | const runUnderBazel = !!process.env["RUNFILES_DIR"]; |
| 8 | const path = require("path"); |
| 9 | |
| 10 | function getModulesDir() { |
| 11 | if (runUnderBazel) { |
| 12 | // Run under bazel |
| 13 | return [ |
| 14 | `external/plugins_npm/node_modules`, |
| 15 | `external/ui_npm/node_modules`, |
| 16 | `external/ui_dev_npm/node_modules`, |
| 17 | ]; |
| 18 | } |
| 19 | |
| 20 | // Run from intellij or npm run test:kdebug |
| 21 | return [ |
| 22 | path.join(__dirname, "app/node_modules"), |
| 23 | path.join(__dirname, "node_modules"), |
| 24 | ]; |
| 25 | } |
| 26 | |
| 27 | function getUiDevNpmFilePath(importPath) { |
| 28 | if (runUnderBazel) { |
| 29 | return `external/ui_dev_npm/node_modules/${importPath}`; |
| 30 | } else { |
| 31 | return `polygerrit-ui/node_modules/${importPath}`; |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | function runInIde() { |
| 36 | // A simple detection of IDE. |
| 37 | // Default browserNoActivityTimeout is 30 seconds. An IDE usually |
| 38 | // runs karma in background and send commands when a user wants to |
| 39 | // execute test. If interval between user executed tests is bigger than |
| 40 | // browserNoActivityTimeout, the IDE reports error and doesn't restart |
| 41 | // server. |
| 42 | // We want to increase browserNoActivityTimeout when tests run in IDE. |
| 43 | // Wd don't want to increase it in other cases, oterhise hanging tests |
| 44 | // can slow down CI. |
| 45 | return ( |
| 46 | !runUnderBazel && |
| 47 | process.argv.some((arg) => arg.toLowerCase().contains("intellij")) |
| 48 | ); |
| 49 | } |
| 50 | |
| 51 | module.exports = function (config) { |
| 52 | let root = config.root; |
| 53 | if (!root) { |
| 54 | console.warn(`--root argument not set. Falling back to __dirname.`); |
| 55 | root = path.resolve(__dirname) + "/"; |
| 56 | } |
| 57 | // Use --test-files to specify pattern for a test files. |
| 58 | // It can be just a file name, without a path: |
| 59 | // --test-files async-foreach-behavior_test.js |
| 60 | // If you specify --test-files without pattern, it gets true value |
| 61 | // In this case we will run all tests (usefull for package.json "debugtest" |
| 62 | // script) |
| 63 | // We will convert a .ts argument to .js and fill in .js if no extension is |
| 64 | // given. |
| 65 | let filePattern; |
| 66 | if (typeof config.testFiles === "string") { |
| 67 | if (config.testFiles.endsWith(".ts")) { |
| 68 | filePattern = |
| 69 | config.testFiles.substr(0, config.testFiles.lastIndexOf(".")) + ".js"; |
| 70 | } else if (config.testFiles.endsWith(".js")) { |
| 71 | filePattern = config.testFiles; |
| 72 | } else { |
| 73 | filePattern = config.testFiles + ".js"; |
| 74 | } |
| 75 | } else { |
| 76 | filePattern = "*_test.js"; |
| 77 | } |
| 78 | const testFilesPattern = root + "**/" + filePattern; |
| 79 | |
| 80 | console.info(`Karma test file pattern: ${testFilesPattern}`); |
| 81 | // Special patch for grep parameters (see details in the grep-patch-karam.js) |
| 82 | const additionalFiles = runUnderBazel |
| 83 | ? [] |
| 84 | : ["polygerrit-ui/grep-patch-karma.js"]; |
| 85 | config.set({ |
| 86 | browserNoActivityTimeout: runInIde ? 60 * 60 * 1000 : 30 * 1000, |
| 87 | // base path that will be used to resolve all patterns (eg. files, exclude) |
| 88 | basePath: "../", |
| 89 | plugins: [ |
| 90 | // Do not use karma-* to load all installed plugin |
| 91 | // This can lead to unexpected behavior under bazel |
| 92 | // if you forget to add a plugin in a bazel rule. |
| 93 | require.resolve("@open-wc/karma-esm"), |
| 94 | "karma-mocha", |
| 95 | "karma-chrome-launcher", |
| 96 | "karma-mocha-reporter", |
| 97 | ], |
| 98 | // frameworks to use |
| 99 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter |
| 100 | frameworks: ["mocha", "esm"], |
| 101 | |
| 102 | // list of files / patterns to load in the browser |
| 103 | files: [ |
| 104 | ...additionalFiles, |
| 105 | getUiDevNpmFilePath("source-map-support/browser-source-map-support.js"), |
| 106 | getUiDevNpmFilePath( |
| 107 | "accessibility-developer-tools/dist/js/axs_testing.js" |
| 108 | ), |
| 109 | { |
| 110 | pattern: getUiDevNpmFilePath("@open-wc/semantic-dom-diff/index.js"), |
| 111 | type: "module", |
| 112 | }, |
| 113 | { |
| 114 | pattern: getUiDevNpmFilePath("@open-wc/testing-helpers/index.js"), |
| 115 | type: "module", |
| 116 | }, |
| 117 | getUiDevNpmFilePath("sinon/pkg/sinon.js"), |
| 118 | { pattern: testFilesPattern, type: "module" }, |
| 119 | ], |
| 120 | esm: { |
| 121 | nodeResolve: { |
| 122 | // By default, it tries to use page.mjs file instead of page.js |
| 123 | // when importing 'page/page', so we shouldn't use .mjs extension |
| 124 | // in node resolve. |
| 125 | // The .ts extension is required to display source code in browser |
| 126 | // (otherwise esm plugin crashes) |
| 127 | extensions: [".js", ".ts"], |
| 128 | }, |
| 129 | moduleDirs: getModulesDir(), |
| 130 | // Bazel and yarn uses symlinks for files. |
| 131 | // preserveSymlinks is necessary for correct modules paths resolving |
| 132 | preserveSymlinks: true, |
| 133 | // By default, esm-dev-server uses 'auto' compatibility mode. |
| 134 | // In the 'auto' mode it incorrectly applies polyfills and |
| 135 | // breaks tests in some browser versions |
| 136 | // (for example, Chrome 69 on gerrit-ci). |
| 137 | compatibility: "none", |
| 138 | plugins: [ |
| 139 | { |
| 140 | resolveImport(importSpecifier) { |
| 141 | // esm-dev-server interprets .ts files as .js files and |
| 142 | // tries to replace all module imports with relative/absolute |
| 143 | // paths. In most cases this works correctly. However if |
| 144 | // a ts file imports type from .d.ts and there is no |
| 145 | // associated .js file then the esm-dev-server responds with |
| 146 | // 500 error. |
| 147 | // For example the following import .ts file causes problem |
| 148 | // import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces'; |
| 149 | // To avoid problems, we don't resolve imports in .ts files |
| 150 | // and instead always return original path |
| 151 | if (importSpecifier.context.originalUrl.endsWith(".ts")) { |
| 152 | return importSpecifier.source; |
| 153 | } |
| 154 | return undefined; |
| 155 | }, |
| 156 | }, |
| 157 | { |
| 158 | transform(context) { |
| 159 | if (context.path.endsWith("/node_modules/page/page.js")) { |
| 160 | const orignalBody = context.body; |
| 161 | // Can't import page.js directly, because this is undefined. |
| 162 | // Replace it with window |
| 163 | // The same replace exists in server.go |
| 164 | // Rollup makes this replacement automatically |
| 165 | const transformedBody = orignalBody.replace( |
| 166 | "}(this, (function () { 'use strict';", |
| 167 | "}(window, (function () { 'use strict';" |
| 168 | ); |
| 169 | if (orignalBody.length === transformedBody.length) { |
| 170 | console.error( |
| 171 | "The page.js was updated. Please update transform accordingly" |
| 172 | ); |
| 173 | process.exit(1); |
| 174 | } |
| 175 | return { body: transformedBody }; |
| 176 | } |
| 177 | }, |
| 178 | }, |
| 179 | ], |
| 180 | }, |
| 181 | // test results reporter to use |
| 182 | // possible values: 'dots', 'progress' |
| 183 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter |
| 184 | reporters: ["mocha"], |
| 185 | |
| 186 | mochaReporter: { |
| 187 | showDiff: true, |
| 188 | }, |
| 189 | |
| 190 | // Listen on localhost so it either listens to ipv4 |
| 191 | // or ipv6. Some OS's default to ipv6 for localhost |
| 192 | // and others ipv4. |
| 193 | // Nodejs 17 changed the behaviour from prefering ipv4 to |
| 194 | // using the OS settings. |
| 195 | // The default is 127.0.0.1 thus if localhost is on ipv6 only |
| 196 | // it'll fail to connect to the karma server. |
| 197 | // See https://github.com/karma-runner/karma/blob/e17698f950af83bf2b3edc540d2a3e1fb73cba59/lib/utils/dns-utils.js#L3 |
| 198 | listenAddress: "localhost", |
| 199 | |
| 200 | // web server port |
| 201 | port: 9876, |
| 202 | |
| 203 | // enable / disable colors in the output (reporters and logs) |
| 204 | colors: true, |
| 205 | |
| 206 | // level of logging |
| 207 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG |
| 208 | logLevel: config.LOG_INFO, |
| 209 | |
| 210 | // enable / disable watching file and executing tests whenever any file changes |
| 211 | autoWatch: false, |
| 212 | |
| 213 | // start these browsers |
| 214 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher |
| 215 | browsers: ["CustomChromeHeadless"], |
| 216 | browserForDebugging: "CustomChromeHeadlessWithDebugPort", |
| 217 | |
| 218 | // Continuous Integration mode |
| 219 | // if true, Karma captures browsers, runs the tests and exits |
| 220 | singleRun: true, |
| 221 | |
| 222 | // Concurrency level |
| 223 | // how many browser should be started simultaneous |
| 224 | concurrency: Infinity, |
| 225 | |
| 226 | client: { |
| 227 | mocha: { |
| 228 | ui: "tdd", |
| 229 | timeout: 5000, |
| 230 | }, |
| 231 | }, |
| 232 | |
| 233 | customLaunchers: { |
| 234 | // Based on https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai |
| 235 | CustomChromeHeadless: { |
| 236 | base: "ChromeHeadless", |
| 237 | flags: ["--disable-translate", "--disable-extensions"], |
| 238 | }, |
| 239 | ChromeDev: { |
| 240 | base: "Chrome", |
| 241 | flags: ["--disable-extensions", " --auto-open-devtools-for-tabs"], |
| 242 | }, |
| 243 | CustomChromeHeadlessWithDebugPort: { |
| 244 | base: "CustomChromeHeadless", |
| 245 | flags: ["--remote-debugging-port=9222"], |
| 246 | }, |
| 247 | }, |
| 248 | }); |
| 249 | }; |