const TapReporter = require("testem/lib/reporters/tap_reporter"); const { shouldLoadPluginTestJs } = require("discourse-plugins"); const fs = require("fs"); class Reporter { failReports = []; deprecationCounts = new Map(); constructor() { this._tapReporter = new TapReporter(...arguments); } reportMetadata(tag, metadata) { if (tag === "increment-deprecation") { const id = metadata.id; const currentCount = this.deprecationCounts.get(id) || 0; this.deprecationCounts.set(id, currentCount + 1); } else if (tag === "summary-line") { process.stdout.write(`\n${metadata.message}\n`); } else { this._tapReporter.reportMetadata(...arguments); } } report(prefix, data) { if (data.failed) { this.failReports.push([prefix, data, this._tapReporter.id]); } this._tapReporter.report(prefix, data); } generateDeprecationTable() { const maxIdLength = Math.max( ...Array.from(this.deprecationCounts.keys()).map((k) => k.length) ); let msg = `| ${"id".padEnd(maxIdLength)} | count |\n`; msg += `| ${"".padEnd(maxIdLength, "-")} | ----- |\n`; for (const [id, count] of this.deprecationCounts.entries()) { const countString = count.toString(); msg += `| ${id.padEnd(maxIdLength)} | ${countString.padStart(5)} |\n`; } return msg; } reportDeprecations() { let deprecationMessage = "[Deprecation Counter] "; if (this.deprecationCounts.size > 0) { const table = this.generateDeprecationTable(); deprecationMessage += `Test run completed with deprecations:\n\n${table}`; if (process.env.GITHUB_ACTIONS && process.env.GITHUB_STEP_SUMMARY) { let jobSummary = `### ⚠️ JS Deprecations\n\nTest run completed with deprecations:\n\n`; jobSummary += table; jobSummary += `\n\n`; fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, jobSummary); } } else { deprecationMessage += "No deprecations logged"; } process.stdout.write(`\n${deprecationMessage}\n\n`); } finish() { this._tapReporter.finish(); this.reportDeprecations(); if (this.failReports.length > 0) { process.stdout.write("\nFailures:\n\n"); this.failReports.forEach(([prefix, data, id]) => { if (process.env.GITHUB_ACTIONS) { process.stdout.write(`::error ::QUnit Test Failure: ${data.name}\n`); } this._tapReporter.id = id; this._tapReporter.report(prefix, data); }); } } } module.exports = { test_page: "tests/index.html?hidepassed", disable_watching: true, launch_in_ci: ["Chrome"], // launch_in_dev: ["Chrome"] // Ember-CLI always launches testem in 'CI' mode tap_failed_tests_only: false, parallel: -1, browser_start_timeout: 120, browser_args: { Chrome: [ // --no-sandbox is needed when running Chrome inside a container process.env.CI ? "--no-sandbox" : null, "--headless", "--disable-dev-shm-usage", "--disable-software-rasterizer", "--mute-audio", "--remote-debugging-port=4201", "--window-size=1440,900", "--enable-precise-memory-info", "--js-flags=--max_old_space_size=4096", ].filter(Boolean), Firefox: ["-headless", "--width=1440", "--height=900"], }, reporter: Reporter, }; if (process.env.TESTEM_FIREFOX_PATH) { module.exports.browser_paths ||= {}; module.exports.browser_paths["Firefox"] = process.env.TESTEM_FIREFOX_PATH; } const target = `http://127.0.0.1:${process.env.UNICORN_PORT || "3000"}`; if (process.argv.includes("-t")) { // Running testem without ember cli. Probably for theme-qunit const testPage = process.argv[process.argv.indexOf("-t") + 1]; module.exports.proxies = {}; module.exports.proxies[`/*/theme-qunit`] = { target: `${target}${testPage}`, ignorePath: true, xfwd: true, }; module.exports.proxies["/*/*"] = { target, xfwd: true }; module.exports.middleware = [ function (app) { // Make the testem.js file available under /assets // so it's within the app's CSP app.get("/assets/testem.js", function (req, res, next) { req.url = "/testem.js"; next(); }); }, ]; } else if (shouldLoadPluginTestJs()) { // Running with ember cli, but we want to pass through plugin request to Rails module.exports.proxies = { "/assets/plugins/*_extra.js": { target, }, "/plugins/": { target, }, "/bootstrap/plugin-css-for-tests.css": { target, }, "/stylesheets/": { target, }, }; }