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.
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- run: ./doSomething.sh | tee output.log
|
||||
- id: output-log
|
||||
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:
|
||||
input:
|
||||
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
|
||||
outputs:
|
||||
contents:
|
||||
description: "A version of 'input' where all ANSI codes have been replaced with HTML color codes."
|
||||
runs:
|
||||
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 Converter from "ansi-to-html";
|
||||
import fs from "fs";
|
||||
import { main } from "./action.js";
|
||||
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
main();
|
||||
|
||||
Generated
+17065
-1
File diff suppressed because it is too large
Load Diff
+103
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ansi-to-html-action",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "./index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": "git@github.com:justinm/ansi-to-html-action.git",
|
||||
@@ -12,7 +12,9 @@
|
||||
"url": "https://justinmccormick.com/ansi-to-html-action"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --ext js ."
|
||||
"lint": "eslint --ext js .",
|
||||
"release": "npx semantic-release",
|
||||
"test": "npx cross-env FORCE_COLOR=1 npx jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
@@ -20,12 +22,28 @@
|
||||
"ansi-to-html": "^0.7.2"
|
||||
},
|
||||
"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",
|
||||
"babel-jest": "^28.1.3",
|
||||
"chalk": "^4.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.22.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-jest": "^26.8.3",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^28.1.3",
|
||||
"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": {
|
||||
"root": true,
|
||||
@@ -44,9 +62,90 @@
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"test/**"
|
||||
],
|
||||
"plugins": [
|
||||
"jest"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:jest/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"jest/prefer-expect-assertions": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"prettierOptions": {
|
||||
"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