From 2b639a6fc10e736cefaeacd3f9af88987f8676cb Mon Sep 17 00:00:00 2001 From: CharlieM312 Date: Thu, 7 May 2026 17:40:30 +0100 Subject: [PATCH] Converted to ESM and actions fixes --- .github/workflows/main.yml | 4 ++-- package-lock.json | 37 ++++++++++--------------------------- package.json | 5 +++-- src/dashboard.ts | 4 ++-- src/index.ts | 5 +++-- src/test_parser.ts | 23 ++++++++++++++++++----- test/dashboard.ts | 6 ++++-- test/file.ts | 12 +++++++----- test/junit.ts | 8 +++++--- test/tap.ts | 8 +++++--- test/trx.ts | 8 +++++--- 11 files changed, 64 insertions(+), 56 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4ce578c..858e1cb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,7 +27,7 @@ jobs: npm run build npm run test - name: Create test summary - uses: ./bin + uses: ./dist with: paths: test/results/*.xml output: test/results/results.html @@ -61,7 +61,7 @@ jobs: run: | npm ci npm run build - npm run pack + npm run package cp action.yml dist/ cp README.md dist/ diff --git a/package-lock.json b/package-lock.json index 084ae86..4128448 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,15 +70,6 @@ "undici": "^6.23.0" } }, - "node_modules/@actions/http-client/node_modules/undici": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", - "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, "node_modules/@actions/io": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz", @@ -116,7 +107,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1624,7 +1614,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2342,7 +2331,6 @@ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.19.0" } @@ -2433,7 +2421,6 @@ "integrity": "sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.59.2", "@typescript-eslint/types": "8.59.2", @@ -2963,7 +2950,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3446,7 +3432,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -3575,7 +3560,6 @@ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -4202,7 +4186,6 @@ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4263,7 +4246,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -6086,7 +6068,6 @@ "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.3.0", "@jest/types": "30.3.0", @@ -7167,7 +7148,6 @@ "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", @@ -7835,7 +7815,6 @@ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8082,7 +8061,6 @@ "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -8791,7 +8769,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -8825,7 +8802,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -8915,8 +8891,7 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tunnel": { "version": "0.0.6", @@ -9024,7 +8999,6 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9076,6 +9050,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", + "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "7.19.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", diff --git a/package.json b/package.json index af97fee..3a426a8 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "test-summary", "version": "0.0.1", "private": true, + "type": "module", "description": "Display test results in a GitHub Actions workflow", "main": "dist/index.js", "exports": { @@ -12,9 +13,9 @@ "format": "prettier --write **/*.ts", "lint": "eslint src/**/*.ts", "package": "npx rimraf ./dist && npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript", - "test": "mocha -r ts-node/register --reporter mocha-multi-reporters --reporter-options configFile=test/config.json test/**/*.ts", + "test": "node --loader ts-node/esm ./node_modules/mocha/bin/mocha --reporter mocha-multi-reporters --reporter-options configFile=test/config.json test/**/*.ts", "clean": "rm -rf dist", - "all": "npm run build && npm run lint && npm run pack && npm test" + "all": "npm run build && npm run lint && npm run package && npm test" }, "repository": { "type": "git", diff --git a/src/dashboard.ts b/src/dashboard.ts index c949a40..3a0efc5 100644 --- a/src/dashboard.ts +++ b/src/dashboard.ts @@ -1,5 +1,5 @@ -import escapeHTML from "./escape_html" -import { TestResult, TestStatus } from "./test_parser" +import escapeHTML from "./escape_html.js" +import { TestResult, TestStatus } from "./test_parser.js" const dashboardUrl = "https://svg.test-summary.com/dashboard.svg" const passIconUrl = "https://svg.test-summary.com/icon/pass.svg?s=12" diff --git a/src/index.ts b/src/index.ts index 0ca7e7a..c68419b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,8 +3,9 @@ import * as util from "util" import * as core from "@actions/core" import * as glob from "glob" -import { TestResult, TestStatus, parseFile } from "./test_parser" -import { dashboardResults, dashboardSummary } from "./dashboard" +import { TestStatus, parseFile } from "./test_parser.js" +import type { TestResult } from "./test_parser.js" +import { dashboardResults, dashboardSummary } from "./dashboard.js" async function run(): Promise { try { diff --git a/src/test_parser.ts b/src/test_parser.ts index 0425c38..fb3ee48 100644 --- a/src/test_parser.ts +++ b/src/test_parser.ts @@ -40,6 +40,18 @@ export interface TestCase { duration?: string } +function normalizeNewlines(value: unknown): string | undefined { + if (value === null || value === undefined) return undefined + if (typeof value === "string") return value.replace(/\r\n/g, "\n") + if (typeof value === "object") { + const v = value as any + if ("_" in v && typeof v._ === "string") { + return v._.replace(/\r\n/g, "\n") + } + } + return String(value).replace(/\r\n/g, "\n") +} + export async function parseTap(data: string): Promise { const lines = data.trim().split(/\r?\n/) // let version = 12 @@ -257,9 +269,9 @@ async function parseJunitXml(xml: any): Promise { message = element.$ ? element.$.message : undefined if (typeof element === "string") { - details = element + details = normalizeNewlines(element) } else { - details = element._ + details = normalizeNewlines(element._) } counts.failed++ @@ -335,7 +347,7 @@ export async function parseTrx(xml: any): Promise { let details: string = "" const output = item?.Output?.[0] - details = "StdOut:" + output?.StdOut?.[0] + details = `StdOut:${normalizeNewlines(output?.StdOut?.[0]) ?? ""}` if (outcome == "Passed") { counts.passed++ @@ -343,8 +355,9 @@ export async function parseTrx(xml: any): Promise { status = TestStatus.Fail counts.failed++ - message = output?.ErrorInfo?.[0]?.Message - details = "StackTrace:" + output?.ErrorInfo?.[0]?.StackTrace + '\n' + details + message = normalizeNewlines(output?.ErrorInfo?.[0]?.Message) ?? undefined + details = normalizeNewlines(`StackTrace:${output?.ErrorInfo?.[0]?.StackTrace ?? ""}\n${details}`) ?? details + } else { status = TestStatus.Pass counts.skipped++ diff --git a/test/dashboard.ts b/test/dashboard.ts index 802bf71..891bc02 100644 --- a/test/dashboard.ts +++ b/test/dashboard.ts @@ -1,7 +1,9 @@ +/// import { expect } from "chai" -import { TestStatus, TestResult } from "../src/test_parser" -import { dashboardResults } from "../src/dashboard" +import { TestStatus } from "../src/test_parser.js" +import type { TestResult } from "../src/test_parser.js" +import { dashboardResults } from "../src/dashboard.js" describe("dashboard", async () => { it("escapes HTML entities", async () => { diff --git a/test/file.ts b/test/file.ts index e63212a..ed6010a 100644 --- a/test/file.ts +++ b/test/file.ts @@ -1,14 +1,16 @@ import * as chai from "chai" import chaiAsPromised from 'chai-as-promised' import { expect } from "chai" - -import { TestStatus, parseFile } from "../src/test_parser" +import {dirname, join} from "path" +import { parseFile } from "../src/test_parser.js" +import { fileURLToPath } from "node:url" chai.use(chaiAsPromised) -const tapResourcePath = `${__dirname}/resources/tap` -const junitResourcePath = `${__dirname}/resources/junit` -const trxResourcePath = `${__dirname}/resources/trx` +const currentDir = dirname(fileURLToPath(import.meta.url)) +const tapResourcePath = join(currentDir, "resources/tap") +const junitResourcePath = join(currentDir, "resources/junit") +const trxResourcePath = join(currentDir, "resources/trx") describe("file", async () => { it("identifies common tap", async () => { diff --git a/test/junit.ts b/test/junit.ts index df1e5aa..29cbec4 100644 --- a/test/junit.ts +++ b/test/junit.ts @@ -1,9 +1,11 @@ -import * as chai from "chai" import { expect } from "chai" -import { TestStatus, parseJunitFile } from "../src/test_parser" +import { TestStatus, parseJunitFile } from "../src/test_parser.js" +import {dirname, join} from "path" +import { fileURLToPath } from "node:url" -const resourcePath = `${__dirname}/resources/junit` +const currentDir = dirname(fileURLToPath(import.meta.url)) +const resourcePath = join(currentDir, "resources/junit") describe("junit", async () => { it("parses common", async () => { diff --git a/test/tap.ts b/test/tap.ts index 2dfb3aa..e23d1af 100644 --- a/test/tap.ts +++ b/test/tap.ts @@ -1,12 +1,14 @@ import * as chai from "chai" import chaiAsPromised from 'chai-as-promised' import { expect } from "chai" - -import { TestStatus, parseTapFile } from "../src/test_parser" +import { TestStatus, parseTapFile } from "../src/test_parser.js" +import { dirname, join } from "path" +import { fileURLToPath } from "url" chai.use(chaiAsPromised) -const resourcePath = `${__dirname}/resources/tap` +const currentDir = dirname(fileURLToPath(import.meta.url)) +const resourcePath = join(currentDir, "resources/tap") describe("tap", async () => { it("parses common", async () => { diff --git a/test/trx.ts b/test/trx.ts index dfe75cd..007977d 100644 --- a/test/trx.ts +++ b/test/trx.ts @@ -1,14 +1,16 @@ -import * as chai from "chai" import { expect } from "chai" import * as fs from "fs" import * as util from "util" import xml2js from "xml2js" +import {dirname, join} from "path" +import { fileURLToPath } from "url" -import { TestStatus, parseTrx } from "../src/test_parser" +import { TestStatus, parseTrx } from "../src/test_parser.js" -const resourcePath = `${__dirname}/resources/trx` +const currentDir = dirname(fileURLToPath(import.meta.url)) +const resourcePath = join(currentDir, "resources/trx") async function parseTrxFile(filename: string) { const readfile = util.promisify(fs.readFile)