chore: testing
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
name: Push Runner
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test Action
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
version: [ 16 ]
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
env:
|
||||||
|
EXPECTED_CONTENT: "<span style=color:#0AA>Sample Text</span>"
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
cache: npm
|
||||||
|
node-version: '16'
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
- name: Lint
|
||||||
|
run: npm run lint
|
||||||
|
- name: Unit Tests
|
||||||
|
run: npm run test
|
||||||
|
- name: Generate String
|
||||||
|
run: echo -en "\e[36mSample Text\e[0m" | tee output.log
|
||||||
|
- name: Read test file from disk
|
||||||
|
id: raw
|
||||||
|
uses: juliangruber/read-file-action@v1
|
||||||
|
with:
|
||||||
|
path: ./output.log
|
||||||
|
- name: Run action on file path
|
||||||
|
id: parsed-path
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
path: ./output.log
|
||||||
|
- name: Run action on input
|
||||||
|
id: parsed-input
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
input: ${{ steps.raw.outputs.content }}
|
||||||
|
- name: "Path smoke test"
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
if [[ "${{ steps.parsed-path.outputs.contents }}" != "${{ env.EXPECTED_CONTENT }}" ]]; then
|
||||||
|
echo "'${{ steps.parsed-path.outputs.contents }}' != '${{ env.EXPECTED_CONTENT }}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- name: "Input smoke test"
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
if [[ "${{ steps.parsed-input.outputs.contents }}" != "${{ env.EXPECTED_CONTENT }}" ]]; then
|
||||||
|
echo "'${{ steps.parsed-input.outputs.contents }}' != '${{ env.EXPECTED_CONTENT }}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
release:
|
||||||
|
name: Release Action
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: startsWith(github.ref, 'refs/heads/master')
|
||||||
|
needs:
|
||||||
|
- test
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
cache: npm
|
||||||
|
node-version: '16'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -25,6 +25,12 @@ A Github Action that converts ANSI color sequences to HTML friendly HEX codes.
|
|||||||
Read a file from disk that contains ANSI color escape sequences, escape its contents and post its contents to an active pull request.
|
Read a file from disk that contains ANSI color escape sequences, escape its contents and post its contents to an active pull request.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
- run: ./doSomething.sh | tee output.log
|
- run: ./doSomething.sh | tee output.log
|
||||||
- id: output-log
|
- id: output-log
|
||||||
uses: justinm/ansi-to-html-action@v0
|
uses: justinm/ansi-to-html-action@v0
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import Converter from "ansi-to-html";
|
||||||
|
import * as core from "@actions/core";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
const converter = new Converter();
|
||||||
|
const input = core.getInput("input", { required: false });
|
||||||
|
const encoding = core.getInput("encoding", {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
const path = core.getInput("path", { required: false });
|
||||||
|
|
||||||
|
if (!input && !path) {
|
||||||
|
return core.setFailed("You must provide either an input or path.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input && path) {
|
||||||
|
return core.setFailed(
|
||||||
|
"You must provide either an input or path, not both."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input && input !== "") {
|
||||||
|
core.setOutput("contents", converter.toHtml(input));
|
||||||
|
} else if (path && path !== "") {
|
||||||
|
if (!fs.existsSync(path)) {
|
||||||
|
return core.setFailed(`Path ${path} does not exist.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawContents = fs.readFileSync(path).toString(encoding);
|
||||||
|
|
||||||
|
core.setOutput("contents", converter.toHtml(rawContents));
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-1
@@ -7,10 +7,17 @@ branding:
|
|||||||
inputs:
|
inputs:
|
||||||
input:
|
input:
|
||||||
description: "The raw input containing ANSI color codes"
|
description: "The raw input containing ANSI color codes"
|
||||||
|
required: false
|
||||||
|
path:
|
||||||
|
description: "The raw input containing ANSI color codes"
|
||||||
|
required: false
|
||||||
|
encoding:
|
||||||
|
description: "The encoding for the raw input. Defaults to utf8"
|
||||||
|
default: "utf8"
|
||||||
required: true
|
required: true
|
||||||
outputs:
|
outputs:
|
||||||
contents:
|
contents:
|
||||||
description: "A version of 'input' where all ANSI codes have been replaced with HTML color codes."
|
description: "A version of 'input' where all ANSI codes have been replaced with HTML color codes."
|
||||||
runs:
|
runs:
|
||||||
using: "node16"
|
using: "node16"
|
||||||
main: "index.js"
|
main: "./index.js"
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [["@babel/preset-env", { targets: { node: "current" } }]],
|
||||||
|
};
|
||||||
@@ -1,26 +1,3 @@
|
|||||||
import core from "@actions/core";
|
import { main } from "./action.js";
|
||||||
import Converter from "ansi-to-html";
|
|
||||||
import fs from "fs";
|
|
||||||
|
|
||||||
const converter = new Converter();
|
main();
|
||||||
const input = core.getInput("input", { required: false });
|
|
||||||
const encoding = core.getInput("encoding", {
|
|
||||||
required: true,
|
|
||||||
});
|
|
||||||
const path = core.getInput("path", { required: false });
|
|
||||||
|
|
||||||
if (!input && !path) {
|
|
||||||
core.setFailed("You must provide either an input or path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input && path) {
|
|
||||||
core.setFailed("You must provide either an input or path, not both.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input && input !== "") {
|
|
||||||
core.setOutput("contents", converter.toHtml(input));
|
|
||||||
} else if (path && path !== "") {
|
|
||||||
const rawContents = fs.readFileSync(path).toString(encoding);
|
|
||||||
|
|
||||||
core.setOutput("contents", converter.toHtml(rawContents));
|
|
||||||
}
|
|
||||||
|
|||||||
Generated
+17065
-1
File diff suppressed because it is too large
Load Diff
+102
-3
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ansi-to-html-action",
|
"name": "ansi-to-html-action",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"main": "index.js",
|
"main": "./index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "git@github.com:justinm/ansi-to-html-action.git",
|
"repository": "git@github.com:justinm/ansi-to-html-action.git",
|
||||||
@@ -12,7 +12,9 @@
|
|||||||
"url": "https://justinmccormick.com/ansi-to-html-action"
|
"url": "https://justinmccormick.com/ansi-to-html-action"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint --ext js ."
|
"lint": "eslint --ext js .",
|
||||||
|
"release": "npx semantic-release",
|
||||||
|
"test": "npx cross-env FORCE_COLOR=1 npx jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.9.1",
|
"@actions/core": "^1.9.1",
|
||||||
@@ -20,12 +22,28 @@
|
|||||||
"ansi-to-html": "^0.7.2"
|
"ansi-to-html": "^0.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.18.10",
|
||||||
|
"@babel/preset-env": "^7.18.10",
|
||||||
|
"@semantic-release/changelog": "^6.0.1",
|
||||||
|
"@semantic-release/commit-analyzer": "^9.0.2",
|
||||||
|
"@semantic-release/git": "^10.0.1",
|
||||||
|
"@semantic-release/github": "^8.0.5",
|
||||||
|
"@semantic-release/npm": "^9.0.1",
|
||||||
|
"@semantic-release/release-notes-generator": "^10.0.3",
|
||||||
|
"@types/jest": "^28.1.7",
|
||||||
"@types/node": "^18.7.3",
|
"@types/node": "^18.7.3",
|
||||||
|
"babel-jest": "^28.1.3",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.22.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"eslint-plugin-jest": "^26.8.3",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
"jest": "^28.1.3",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prettier-eslint": "^15.0.1"
|
"prettier-eslint": "^15.0.1",
|
||||||
|
"semantic-release": "^19.0.3",
|
||||||
|
"semantic-release-conventional-commits": "^3.0.0"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
@@ -44,9 +62,90 @@
|
|||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"prettier/prettier": "error"
|
"prettier/prettier": "error"
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"test/**"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"jest"
|
||||||
|
],
|
||||||
|
"extends": [
|
||||||
|
"plugin:jest/recommended"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"jest/prefer-expect-assertions": "off"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"prettierOptions": {
|
"prettierOptions": {
|
||||||
"bracketSpacing": true
|
"bracketSpacing": true
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"transform": {
|
||||||
|
"\\.[jt]sx?$": "babel-jest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"branches": [
|
||||||
|
"master"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"@semantic-release/commit-analyzer",
|
||||||
|
{
|
||||||
|
"preset": "conventionalcommits",
|
||||||
|
"parserOpts": {
|
||||||
|
"noteKeywords": [
|
||||||
|
"BREAKS",
|
||||||
|
"BREAKING CHANGE",
|
||||||
|
"BREAKING CHANGES",
|
||||||
|
"BACKWARDS COMPAT",
|
||||||
|
"BACKWARDS COMPATIBILITY"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@semantic-release/release-notes-generator",
|
||||||
|
[
|
||||||
|
"@semantic-release/changelog",
|
||||||
|
{
|
||||||
|
"changeLogFile": "CHANGELOG.md"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/npm",
|
||||||
|
{
|
||||||
|
"npmPublish": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/github",
|
||||||
|
{
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"path": "CHANGELOG.md",
|
||||||
|
"label": "Changelog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"label": "Readme"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "LICENSE.md",
|
||||||
|
"label": "License"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/git",
|
||||||
|
{
|
||||||
|
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import { main } from "../action.js";
|
||||||
|
import * as core from "@actions/core";
|
||||||
|
import chalk from "chalk";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
jest.mock("@actions/core");
|
||||||
|
|
||||||
|
describe("Action", () => {
|
||||||
|
describe("using inputs", () => {
|
||||||
|
it("returns an HTML safe string", () => {
|
||||||
|
const mockGetInput = jest.fn((key) => {
|
||||||
|
switch (key) {
|
||||||
|
case "input":
|
||||||
|
return chalk.red("test");
|
||||||
|
case "encoding":
|
||||||
|
return "utf8";
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
const mockSetOutput = jest.fn();
|
||||||
|
|
||||||
|
jest.spyOn(core, "getInput").mockImplementation(mockGetInput);
|
||||||
|
jest.spyOn(core, "setOutput").mockImplementation(mockSetOutput);
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
expect(mockGetInput.mock.calls).toHaveLength(3);
|
||||||
|
expect(mockSetOutput.mock.calls).toHaveLength(1);
|
||||||
|
expect(mockSetOutput.mock.calls[0]).toHaveLength(2);
|
||||||
|
expect(mockSetOutput.mock.calls[0][0]).toMatch("contents");
|
||||||
|
expect(mockSetOutput.mock.calls[0][1]).toMatch(
|
||||||
|
'<span style="color:#A00">test<span style="color:#FFF"></span></span>'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("using paths", () => {
|
||||||
|
it("returns an HTML safe string", () => {
|
||||||
|
const mockGetInput = jest.fn((key) => {
|
||||||
|
switch (key) {
|
||||||
|
case "encoding":
|
||||||
|
return "utf8";
|
||||||
|
case "path":
|
||||||
|
return "./test.log";
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
const mockSetOutput = jest.fn();
|
||||||
|
const mockExistsSync = jest.fn(() => true);
|
||||||
|
const mockReadFileSync = jest.fn(() => chalk.red("test"));
|
||||||
|
|
||||||
|
jest.spyOn(core, "getInput").mockImplementation(mockGetInput);
|
||||||
|
jest.spyOn(core, "setOutput").mockImplementation(mockSetOutput);
|
||||||
|
jest.spyOn(fs, "existsSync").mockImplementation(mockExistsSync);
|
||||||
|
jest.spyOn(fs, "readFileSync").mockImplementation(mockReadFileSync);
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
expect(mockGetInput.mock.calls).toHaveLength(3);
|
||||||
|
expect(mockSetOutput.mock.calls).toHaveLength(1);
|
||||||
|
expect(mockSetOutput.mock.calls[0]).toHaveLength(2);
|
||||||
|
expect(mockSetOutput.mock.calls[0][0]).toMatch("contents");
|
||||||
|
expect(mockSetOutput.mock.calls[0][1]).toMatch(
|
||||||
|
'<span style="color:#A00">test<span style="color:#FFF"></span></span>'
|
||||||
|
);
|
||||||
|
expect(mockExistsSync.mock.calls).toHaveLength(1);
|
||||||
|
expect(mockReadFileSync.mock.calls).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns an error when the path does not exists", () => {
|
||||||
|
const mockGetInput = jest.fn((key) => {
|
||||||
|
switch (key) {
|
||||||
|
case "encoding":
|
||||||
|
return "utf8";
|
||||||
|
case "path":
|
||||||
|
return "./test.log";
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
const mockSetOutput = jest.fn();
|
||||||
|
const mockSetFailed = jest.fn();
|
||||||
|
const mockExistsSync = jest.fn(() => false);
|
||||||
|
const mockReadFileSync = jest.fn(() => chalk.red("test"));
|
||||||
|
|
||||||
|
jest.spyOn(core, "getInput").mockImplementation(mockGetInput);
|
||||||
|
jest.spyOn(core, "setOutput").mockImplementation(mockSetOutput);
|
||||||
|
jest.spyOn(core, "setFailed").mockImplementation(mockSetFailed);
|
||||||
|
jest.spyOn(fs, "existsSync").mockImplementation(mockExistsSync);
|
||||||
|
jest.spyOn(fs, "readFileSync").mockImplementation(mockReadFileSync);
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
expect(mockGetInput.mock.calls).toHaveLength(3);
|
||||||
|
expect(mockSetOutput.mock.calls).toHaveLength(0);
|
||||||
|
expect(mockExistsSync.mock.calls).toHaveLength(1);
|
||||||
|
expect(mockReadFileSync.mock.calls).toHaveLength(0);
|
||||||
|
expect(mockSetFailed.mock.calls).toHaveLength(1);
|
||||||
|
expect(mockSetFailed.mock.calls[0]).toHaveLength(1);
|
||||||
|
expect(mockSetFailed.mock.calls[0][0]).toMatch(
|
||||||
|
`Path ./test.log does not exist.`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "dist",
|
|
||||||
"allowJs": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"strict": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"noEmit": false,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"target": "ES6",
|
|
||||||
"lib": [
|
|
||||||
"dom",
|
|
||||||
"dom.iterable",
|
|
||||||
"esnext"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user