Update tests

This commit is contained in:
lowlighter
2021-04-29 13:44:17 +02:00
parent 33e9231d2d
commit 1c9cae0322
3 changed files with 136 additions and 117 deletions

View File

@@ -126,7 +126,9 @@ rules:
func-call-spacing: error func-call-spacing: error
arrow-spacing: error arrow-spacing: error
generator-star-spacing: error generator-star-spacing: error
object-curly-spacing: [error, never]
rest-spread-spacing: error rest-spread-spacing: error
key-spacing: [error, {afterColon: false}]
computed-property-spacing: error computed-property-spacing: error
array-bracket-spacing: [error, never] array-bracket-spacing: [error, never]
no-whitespace-before-property: error no-whitespace-before-property: error

View File

@@ -1,20 +1,22 @@
//Imports //Imports
const path = require("path") const path = require("path")
const git = require("simple-git")(path.join(__dirname, "..")) const git = require("simple-git")(path.join(__dirname, ".."))
//Edited files list //Edited files list
const diff = async () => (await git.diff("origin/master...", ["--name-status"])).split("\n").map(x => x.trim()).filter(x => /^M\s+/.test(x)).map(x => x.replace(/^M\s+/, "")) const diff = async () => (await git.diff("origin/master...", ["--name-status"])).split("\n").map(x => x.trim()).filter(x => /^M\s+/.test(x)).map(x => x.replace(/^M\s+/, ""))
//Files editions //Files editions
describe("Check files editions (checkout your files if needed)", () => { describe("Check files editions (checkout your files if needed)", () => {
describe("Auto-generated files were not modified", () => void test.each([ describe("Auto-generated files were not modified", () =>
void test.each([
"README.md", "README.md",
"source/plugins/README.md", "source/plugins/README.md",
"source/templates/README.md", "source/templates/README.md",
"action.yml", "action.yml",
"settings.example.json" "settings.example.json",
])("%s", async file => expect((await diff()).includes(file)).toBe(false))) ])("%s", async file => expect((await diff()).includes(file)).toBe(false)))
describe("Repository level files were not modified", () => void test.each([ describe("Repository level files were not modified", () =>
void test.each([
".github/config/*", ".github/config/*",
".github/ISSUE_TEMPLATE/*", ".github/ISSUE_TEMPLATE/*",
".github/PULL_REQUEST_TEMPLATE/*", ".github/PULL_REQUEST_TEMPLATE/*",
@@ -35,11 +37,12 @@
"tests/ci.test.js", "tests/ci.test.js",
"source/.eslintrc.yml", "source/.eslintrc.yml",
"source/app/mocks/.eslintrc.yml", "source/app/mocks/.eslintrc.yml",
"vercel.json" "vercel.json",
])("%s", async file => expect((await diff()).filter(edited => new RegExp(`^${file.replace(/[.]/g, "[.]").replace(/[*]/g, "[\\s\\S]*")}$`).test(edited)).length).toBe(0))) ])("%s", async file => expect((await diff()).filter(edited => new RegExp(`^${file.replace(/[.]/g, "[.]").replace(/[*]/g, "[\\s\\S]*")}$`).test(edited)).length).toBe(0)))
}) })
//Templates editions //Templates editions
describe("Check templates editions", () => { describe("Check templates editions", () => {
test("Use community templates instead (see https://github.com/lowlighter/metrics/tree/master/source/templates/community)", async () => void expect((await diff()).filter(edited => /^sources[/]templates[/]/.test(edited) && /^source[/]templates[/](?:classic|terminal|markdown|repository|community)[/][\s\S]*$/.test(edited)).length).toBe(0)) test("Use community templates instead (see https://github.com/lowlighter/metrics/tree/master/source/templates/community)", async () =>
}) void expect((await diff()).filter(edited => /^sources[/]templates[/]/.test(edited) && /^source[/]templates[/](?:classic|terminal|markdown|repository|community)[/][\s\S]*$/.test(edited)).length).toBe(0))
})

View File

@@ -1,21 +1,22 @@
//Imports //Imports
const processes = require("child_process") const processes = require("child_process")
const yaml = require("js-yaml") const yaml = require("js-yaml")
const fs = require("fs") const fs = require("fs")
const path = require("path") const path = require("path")
const url = require("url") const url = require("url")
const axios = require("axios") const axios = require("axios")
const faker = require("faker") const faker = require("faker")
const ejs = require("ejs") const ejs = require("ejs")
//Github action //Github action
const action = yaml.load(fs.readFileSync(path.join(__dirname, "../action.yml"), "utf8")) const action = yaml.load(fs.readFileSync(path.join(__dirname, "../action.yml"), "utf8"))
action.defaults = Object.fromEntries(Object.entries(action.inputs).map(([key, {default:value}]) => [key, value])) action.defaults = Object.fromEntries(Object.entries(action.inputs).map(([key, { default: value }]) => [key, value]))
action.input = vars => Object.fromEntries([...Object.entries(action.defaults), ...Object.entries(vars)].map(([key, value]) => [`INPUT_${key.toLocaleUpperCase()}`, value])) action.input = vars => Object.fromEntries([...Object.entries(action.defaults), ...Object.entries(vars)].map(([key, value]) => [`INPUT_${key.toLocaleUpperCase()}`, value]))
action.run = async (vars) => await new Promise((solve, reject) => { action.run = async vars =>
await new Promise((solve, reject) => {
let [stdout, stderr] = ["", ""] let [stdout, stderr] = ["", ""]
const env = {...process.env, ...action.input(vars), GITHUB_REPOSITORY:"lowlighter/metrics"} const env = { ...process.env, ...action.input(vars), GITHUB_REPOSITORY: "lowlighter/metrics" }
const child = processes.spawn("node", ["source/app/action/index.mjs"], {env}) const child = processes.spawn("node", ["source/app/action/index.mjs"], { env })
child.stdout.on("data", data => stdout += data) child.stdout.on("data", data => stdout += data)
child.stderr.on("data", data => stderr += data) child.stderr.on("data", data => stderr += data)
child.on("close", code => { child.on("close", code => {
@@ -27,111 +28,124 @@
}) })
//Web instance //Web instance
const web = {} const web = {}
web.run = async (vars) => (await axios(`http://localhost:3000/lowlighter?${new url.URLSearchParams(Object.fromEntries(Object.entries(vars).map(([key, value]) => [key.replace(/^plugin_/, "").replace(/_/g, "."), value])))}`)).status === 200 web.run = async vars => (await axios(`http://localhost:3000/lowlighter?${new url.URLSearchParams(Object.fromEntries(Object.entries(vars).map(([key, value]) => [key.replace(/^plugin_/, "").replace(/_/g, "."), value])))}`)).status === 200
web.start = async () => new Promise(solve => { web.start = async () =>
new Promise(solve => {
let stdout = "" let stdout = ""
web.instance = processes.spawn("node", ["source/app/web/index.mjs"], {env:{...process.env, USE_MOCKED_DATA:true, NO_SETTINGS:true}}) web.instance = processes.spawn("node", ["source/app/web/index.mjs"], { env: { ...process.env, USE_MOCKED_DATA: true, NO_SETTINGS: true } })
web.instance.stdout.on("data", data => (stdout += data, /Server ready !/.test(stdout) ? solve() : null)) web.instance.stdout.on("data", data => (stdout += data, /Server ready !/.test(stdout) ? solve() : null))
web.instance.stderr.on("data", data => console.error(`${data}`)) web.instance.stderr.on("data", data => console.error(`${data}`))
}) })
web.stop = async () => await web.instance.kill("SIGKILL") web.stop = async () => await web.instance.kill("SIGKILL")
//Web instance placeholder //Web instance placeholder
require("./../source/app/web/statics/app.placeholder.js") require("./../source/app/web/statics/app.placeholder.js")
const placeholder = globalThis.placeholder const placeholder = globalThis.placeholder
delete globalThis.placeholder delete globalThis.placeholder
placeholder.init({faker, ejs, axios:{async get(url) { return axios(`http://localhost:3000${url}`) }}}) placeholder.init({
placeholder.run = async (vars) => { faker,
const options = Object.fromEntries(Object.entries(vars).map(([key, value]) => [key.replace(/^plugin_/, "").replace(/_/g, "."), value])) ejs,
const enabled = Object.fromEntries(Object.entries(vars).filter(([key]) => /^plugin_[a-z]+$/.test(key))) axios: {
const config = Object.fromEntries(Object.entries(options).filter(([key]) => /^config[.]/.test(key))) async get(url) {
const base = Object.fromEntries(Object.entries(options).filter(([key]) => /^base[.]/.test(key))) return axios(`http://localhost:3000${url}`)
return typeof await placeholder({ },
templates:{selected:vars.template}, },
plugins:{enabled:{...enabled, base}, options}, })
config, placeholder.run = async vars => {
version:"TEST", const options = Object.fromEntries(Object.entries(vars).map(([key, value]) => [key.replace(/^plugin_/, "").replace(/_/g, "."), value]))
user:"lowlighter", const enabled = Object.fromEntries(Object.entries(vars).filter(([key]) => /^plugin_[a-z]+$/.test(key)))
avatar:"https://github.com/lowlighter.png", const config = Object.fromEntries(Object.entries(options).filter(([key]) => /^config[.]/.test(key)))
}) === "string" const base = Object.fromEntries(Object.entries(options).filter(([key]) => /^base[.]/.test(key)))
} return typeof await placeholder({
templates: { selected: vars.template },
plugins: { enabled: { ...enabled, base }, options },
config,
version: "TEST",
user: "lowlighter",
avatar: "https://github.com/lowlighter.png",
}) === "string"
}
//Setup //Setup
beforeAll(async done => { beforeAll(async done => {
//Clean community template //Clean community template
await fs.promises.rmdir(path.join(__dirname, "../source/templates/@classic"), {recursive:true}) await fs.promises.rmdir(path.join(__dirname, "../source/templates/@classic"), { recursive: true })
//Start web instance //Start web instance
await web.start() await web.start()
done() done()
}) })
//Teardown //Teardown
afterAll(async done => { afterAll(async done => {
//Stop web instance //Stop web instance
await web.stop() await web.stop()
//Clean community template //Clean community template
await fs.promises.rmdir(path.join(__dirname, "../source/templates/@classic"), {recursive:true}) await fs.promises.rmdir(path.join(__dirname, "../source/templates/@classic"), { recursive: true })
done() done()
}) })
//Load metadata (as jest doesn't support ESM modules, we use this dirty hack) //Load metadata (as jest doesn't support ESM modules, we use this dirty hack)
const metadata = JSON.parse(`${processes.spawnSync("node", [ const metadata = JSON.parse(`${
"--input-type", "module", processes.spawnSync("node", [
"--eval", 'import metadata from "./source/app/metrics/metadata.mjs";console.log(JSON.stringify(await metadata({log:false})))' "--input-type",
]).stdout}`) "module",
"--eval",
'import metadata from "./source/app/metrics/metadata.mjs";console.log(JSON.stringify(await metadata({log:false})))',
]).stdout
}`)
//Build tests index //Build tests index
const tests = [] const tests = []
for (const name in metadata.plugins) { for (const name in metadata.plugins) {
const cases = yaml const cases = yaml
.load(fs.readFileSync(path.join(__dirname, "../source/plugins", name, "tests.yml"), "utf8")) .load(fs.readFileSync(path.join(__dirname, "../source/plugins", name, "tests.yml"), "utf8"))
.map(({name:test, with:inputs, modes = [], timeout}) => { .map(({ name: test, with: inputs, modes = [], timeout }) => {
const skip = new Set(Object.entries(metadata.templates).filter(([_, {readme:{compatibility}}]) => !compatibility[name]).map(([template]) => template)) const skip = new Set(Object.entries(metadata.templates).filter(([_, { readme: { compatibility } }]) => !compatibility[name]).map(([template]) => template))
if (!(metadata.plugins[name].supports.includes("repository"))) if (!(metadata.plugins[name].supports.includes("repository")))
skip.add("repository") skip.add("repository")
return [test, inputs, {skip:[...skip], modes, timeout}] return [test, inputs, { skip: [...skip], modes, timeout }]
}) })
tests.push(...cases) tests.push(...cases)
} }
//Tests run //Tests run
describe("GitHub Action", () => describe("GitHub Action", () =>
describe.each([ describe.each([
["classic", {}], ["classic", {}],
["terminal", {}], ["terminal", {}],
["repository", {repo:"metrics"}], ["repository", { repo: "metrics" }],
])("Template : %s", (template, query) => { ])("Template : %s", (template, query) => {
for (const [name, input, {skip = [], modes = [], timeout} = {}] of tests) for (const [name, input, { skip = [], modes = [], timeout } = {}] of tests) {
if ((skip.includes(template))||((modes.length)&&(!modes.includes("action")))) if ((skip.includes(template)) || ((modes.length) && (!modes.includes("action"))))
test.skip(name, () => null) test.skip(name, () => null)
else else
test(name, async () => expect(await action.run({template, base:"", query:JSON.stringify(query), plugins_errors_fatal:true, dryrun:true, use_mocked_data:true, verify:true, ...input})).toBe(true), timeout) test(name, async () => expect(await action.run({ template, base: "", query: JSON.stringify(query), plugins_errors_fatal: true, dryrun: true, use_mocked_data: true, verify: true, ...input })).toBe(true), timeout)
}) }
) }))
describe("Web instance", () => describe("Web instance", () =>
describe.each([ describe.each([
["classic", {}], ["classic", {}],
["terminal", {}], ["terminal", {}],
["repository", {repo:"metrics"}], ["repository", { repo: "metrics" }],
])("Template : %s", (template, query) => { ])("Template : %s", (template, query) => {
for (const [name, input, {skip = [], modes = [], timeout} = {}] of tests) for (const [name, input, { skip = [], modes = [], timeout } = {}] of tests) {
if ((skip.includes(template))||((modes.length)&&(!modes.includes("web")))) if ((skip.includes(template)) || ((modes.length) && (!modes.includes("web"))))
test.skip(name, () => null) test.skip(name, () => null)
else else
test(name, async () => expect(await web.run({template, base:0, ...query, plugins_errors_fatal:true, verify:true, ...input})).toBe(true), timeout) test(name, async () => expect(await web.run({ template, base: 0, ...query, plugins_errors_fatal: true, verify: true, ...input })).toBe(true), timeout)
}) }
) }))
describe("Web instance (placeholder)", () => describe("Web instance (placeholder)", () =>
describe.each([ describe.each([
["classic", {}], ["classic", {}],
["terminal", {}], ["terminal", {}],
])("Template : %s", (template, query) => { ])("Template : %s", (template, query) => {
for (const [name, input, {skip = [], modes = [], timeout} = {}] of tests) for (const [name, input, { skip = [], modes = [], timeout } = {}] of tests) {
if ((skip.includes(template))||((modes.length)&&(!modes.includes("placeholder")))) if ((skip.includes(template)) || ((modes.length) && (!modes.includes("placeholder"))))
test.skip(name, () => null) test.skip(name, () => null)
else else
test(name, async () => expect(await placeholder.run({template, base:0, ...query, ...input})).toBe(true), timeout) test(name, async () => expect(await placeholder.run({ template, base: 0, ...query, ...input })).toBe(true), timeout)
}) }
) }))