Skip to content

Commit

Permalink
continue
Browse files Browse the repository at this point in the history
  • Loading branch information
lowlighter committed Oct 20, 2023
1 parent cbb720f commit 5e9fffd
Show file tree
Hide file tree
Showing 40 changed files with 617 additions and 272 deletions.
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ branding:
inputs:
docker_image:
description: Docker image to use
default: Dockerfile # TODO(@lowlighter): change to remote published image
default: ghcr.io/lowlighter/metrics:v4
required: true
config:
description: Configuration file
Expand Down
3 changes: 1 addition & 2 deletions deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@processors/": "./source/processors/"
},
"tasks": {
"qq": "rm -rf .coverage && deno test --coverage=.coverage --no-check --unstable --trace-ops --allow-all source/metrics/engine/metadata_test.ts && deno coverage .coverage --exclude='(secret|log|io|errors|testing|validation|format|version|config|requests|processor|plugin|internal|component).ts'",
"qq": "rm -rf .coverage && deno test --coverage=.coverage --no-check --unstable --trace-ops --allow-all source/metrics/engine/components/processor_test.ts && deno coverage .coverage --exclude='(secret|log|io|errors|testing|validation|format|version|config|processor|internal|requests|component).ts'",
"q": "rm -rf .coverage && deno test --coverage=.coverage --unstable --trace-ops --fail-fast --allow-all source/metrics && deno coverage .coverage",
"btr": "deno run --allow-env --allow-read --allow-write=.btr.json --allow-run=deno --no-lock tasks.ts $0"
},
Expand Down Expand Up @@ -96,7 +96,6 @@
"doc": true,
"traceOps": true,
//"parallel": true,
"shuffle": true,
"coverage": ".coverage",
"failFast": 1,
"lock": false,
Expand Down
3 changes: 3 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions source/metrics/engine/components/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ export abstract class Component extends Internal {

/** Icon */
get icon() {
return this.name.match(/(\p{Emoji_Presentation}+)/gu)?.[0] ?? "⏹️"
return this.name.match(/([\p{Emoji}\u200d]+)/gu)?.[0] ?? "⏹️"
}

/** Action */
protected abstract action(state: state): Promise<unknown>

/** Is supported ? */
protected abstract supported(): void
protected abstract supported(state: state): Promise<void> | void

/** Run component */
protected async run(state: state) {
Expand All @@ -65,7 +65,7 @@ export abstract class Component extends Internal {
try {
// Ensure component is supported for current context
try {
this.supported()
await this.supported(state)
} catch (error) {
recoverable = false
throw error
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { expect, test } from "@utils/testing.ts"
import { Plugin } from "@engine/components/plugin.ts"
import { Processor } from "@engine/components/processor.ts"
import { process } from "@engine/process.ts"
import { test } from "@utils/testing.ts"
import { deepMerge } from "std/collections/deep_merge.ts"
import { Browser } from "@utils/browser.ts"
import * as dir from "@engine/paths.ts"
import { Logger } from "@utils/log.ts"
import { Component } from "@engine/components/component.ts"

const config = {
/** Config */
export const config = {
presets: {
default: {
plugins: {
Expand All @@ -22,51 +20,10 @@ const config = {
},
},
},
}

// Plugins
for (const id of await Plugin.list()) {
const plugin = await Plugin.load({ id })
const tests = await plugin.tests()
const templates = await plugin.templates()
const name = `${plugin.icon} plugins/${plugin.id}`
if (!tests.length) {
Deno.test.ignore(name, () => void null)
continue
}
for (const test of tests) {
Deno.test(`${name} | ${test.name}`, await getPermissions(test), async (t) => {
const { teardown } = setup()
for (const template of templates) {
await t.step(template, async () => {
await expect(process(deepMerge({ presets: { default: { plugins: { template } } } }, deepMerge(config, test, { arrays: "replace" })))).to.be.fulfilled.and.eventually.be.ok
})
}
teardown()
})
}
}

// Processors
for (const id of await Processor.list()) {
const processor = await Processor.load({ id })
const tests = await processor.tests()
const name = `${processor.icon} processors/${processor.id}`
if (!tests.length) {
Deno.test.ignore(name, () => void null)
continue
}
for (const test of tests) {
Deno.test(`${name} | ${test.name}`, await getPermissions(test), async () => {
const { teardown } = setup()
await expect(process(deepMerge(config, test, { arrays: "replace" }))).to.be.fulfilled.and.eventually.be.ok
teardown()
})
}
}
} as const

/** Setup for components tests */
function setup() {
export function setup() {
const { raw } = Logger
const { shareable } = Browser
Logger.raw = false
Expand All @@ -79,7 +36,7 @@ function setup() {
}

/** Compute required permissions */
async function getPermissions(test: Awaited<ReturnType<typeof Component["prototype"]["tests"]>>[0]) {
export async function getPermissions(test: Awaited<ReturnType<typeof Component["prototype"]["tests"]>>[0]) {
// Aggregate permissions from all plugins and processors
const requested = new Set<string>()
const components = new Set<string>()
Expand Down
14 changes: 14 additions & 0 deletions source/metrics/engine/components/internal_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Internal } from "@engine/components/internal.ts"
import { expect, test } from "@utils/testing.ts"

class InternalTest extends Internal {
protected static readonly meta = import.meta
constructor() {
super(null as test)
}
}

Deno.test("Internal()", { permissions: "none" }, () => {
const internal = new InternalTest()
expect(internal.id).to.equal("metrics/engine/components/internal_test.ts")
})
9 changes: 2 additions & 7 deletions source/metrics/engine/components/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ export abstract class Plugin extends Component {
return this.requests.fetch(...args)
}

/** Ratelimit */
protected ratelimit() {
return this.requests.ratelimit()
}

/** Render an EJS template */
protected async render({ state }: { state: state }) {
const name = this.context.template
Expand All @@ -72,8 +67,8 @@ export abstract class Plugin extends Component {

/** Is supported ? */
protected supported() {
if (!this.supports.includes(this.context.entity)) {
throws(`Not supported for ${this.context.entity}`)
if ((this.supports.length) && (!this.supports.includes(this.context.entity))) {
throws(`${this.id} not supported for ${this.context.entity}`)
}
}

Expand Down
72 changes: 72 additions & 0 deletions source/metrics/engine/components/plugin_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { expect, MetricsError, test } from "@utils/testing.ts"
import { is, Plugin } from "@engine/components/plugin.ts"
import { config as schema } from "@engine/config.ts"
import { config, getPermissions, setup } from "@engine/components/component_test.ts"
import { deepMerge } from "std/collections/deep_merge.ts"
import { process } from "@engine/process.ts"
//import * as dir from "@engine/paths.ts"

// TODO(@lowlighter): change to `[dir.source]` after https://github.com/denoland/deno_std/pull/3692
Deno.test("Plugin()", { permissions: { read: true } }, async (t) => {
const { plugins: [context] } = schema.parse({ plugins: [{ id: "test", logs: "none", fatal: true, template: null, retries: { delay: 0 } }] }) as test
class TestPlugin extends Plugin {
static readonly meta = { url: "test" } as test
readonly name = "⚗️ Test plugin"
readonly category = "testing"
readonly supports = ["user"]
readonly description = "Test plugin"
readonly inputs = is.object({})
readonly outputs = is.object({})
protected async action() {}
async run() {
const state = await Plugin.state.parseAsync({ results: [], errors: [] })
return super.run(state)
}
constructor(context: Plugin["context"]) {
super(context)
}
}

await t.step("tests() returns a list of tests", async () => {
const plugin = new TestPlugin(context)
await expect(plugin.tests()).to.eventually.be.an("array")
})

await t.step("templates() returns a list of templates", async () => {
const plugin = new TestPlugin(context)
await expect(plugin.templates()).to.eventually.be.an("array")
})

await t.step("supported()", async (t) => {
await t.step("is a noop when entity is supported", async () => {
const plugin = new TestPlugin({ ...context, entity: "user" })
await expect(plugin.run()).to.be.eventually.be.ok
})
await t.step("throws if not supported", async () => {
const plugin = new TestPlugin({ ...context, entity: "organization" })
await expect(plugin.run()).to.be.rejectedWith(MetricsError, /not supported for organization/i)
})
})
})

for (const id of await Plugin.list()) {
const plugin = await Plugin.load({ id })
const tests = await plugin.tests()
const templates = await plugin.templates()
const name = `${plugin.icon} plugins/${plugin.id}`
if (!tests.length) {
Deno.test.ignore(name, () => void null)
continue
}
for (const test of tests) {
Deno.test(`${name} | ${test.name}`, await getPermissions(test), async (t) => {
const { teardown } = setup()
for (const template of templates) {
await t.step(template, async () => {
await expect(process(deepMerge({ presets: { default: { plugins: { template } } } }, deepMerge(config, test, { arrays: "replace" })))).to.be.fulfilled.and.eventually.be.ok
})
}
teardown()
})
}
}
8 changes: 6 additions & 2 deletions source/metrics/engine/components/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { processor as schema } from "@engine/config.ts"
import { list } from "@utils/io.ts"
import type { Plugin } from "@engine/components/plugin.ts"
import { Requests } from "@engine/components/requests.ts"
import { throws } from "@utils/errors.ts"

/** Processor */
export abstract class Processor extends Component {
Expand All @@ -29,8 +30,11 @@ export abstract class Processor extends Component {
readonly outputs = is.object({})

/** Is supported ? */
protected supported() {
//TODO(@lowlighter): Implement
protected async supported(state: state) {
const { mime } = await this.piped(state)
if ((this.supports.length) && (!this.supports.includes(mime))) {
throws(`${this.id} not supported for ${mime}`)
}
}

/** Retrieve piped result */
Expand Down
60 changes: 60 additions & 0 deletions source/metrics/engine/components/processor_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { expect, MetricsError, test } from "@utils/testing.ts"
import { Processor } from "@engine/components/processor.ts"
import { config as schema } from "@engine/config.ts"
import { config, getPermissions, setup } from "@engine/components/component_test.ts"
import { deepMerge } from "std/collections/deep_merge.ts"
import { process } from "@engine/process.ts"
//import * as dir from "@engine/paths.ts"

// TODO(@lowlighter): change to `[dir.source]` after https://github.com/denoland/deno_std/pull/3692
Deno.test("Processor()", { permissions: { read: true } }, async (t) => {
const { plugins: [{ processors: [context] }] } = schema.parse({ plugins: [{ processors: [{ id: "test", logs: "none", fatal: true, retries: { delay: 0 } }] }] }) as test
class TestProcessor extends Processor {
static readonly meta = { url: "test" } as test
readonly name = "⚗️ Test processor"
readonly category = "testing"
readonly supports = ["image/svg+xml"]
readonly description = "Test processor"
protected async action() {}
async run({ mime }: test) {
const state = await Processor.state.parseAsync({ result: { content: "", mime, base64: false, result: {} }, results: [], errors: [] })
return super.run(state)
}
constructor(context: Processor["context"]) {
super(context)
}
}

await t.step("tests() returns a list of tests", async () => {
const plugin = new TestProcessor(context)
await expect(plugin.tests()).to.eventually.be.an("array")
})

await t.step("supported()", async (t) => {
await t.step("is a noop when entity is supported", async () => {
const plugin = new TestProcessor(context)
await expect(plugin.run({ mime: "image/svg+xml" })).to.be.eventually.be.ok
})
await t.step("throws if not supported", async () => {
const plugin = new TestProcessor(context)
await expect(plugin.run({ mime: "text/plain" })).to.be.rejectedWith(MetricsError, /not supported for text\/plain/i)
})
})
})

for (const id of await Processor.list()) {
const processor = await Processor.load({ id })
const tests = await processor.tests()
const name = `${processor.icon} processors/${processor.id}`
if (!tests.length) {
Deno.test.ignore(name, () => void null)
continue
}
for (const test of tests) {
Deno.test(`${name} | ${test.name}`, await getPermissions(test), async () => {
const { teardown } = setup()
await expect(process(deepMerge(config, test, { arrays: "replace" }))).to.be.fulfilled.and.eventually.be.ok
teardown()
})
}
}
2 changes: 1 addition & 1 deletion source/metrics/engine/components/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class Requests extends Internal {

/** Ratelimit */
async ratelimit() {
const { data: { resources: { core, search, graphql = { remaining: 0, limit: 0 }, ...others } } } = await this.octokit.rest.rateLimit.get()
const { data: { resources: { core, search, graphql = { remaining: 0, limit: 0 }, ...others } } } = await this.rest(this.api.rateLimit.get)
const { code_search: code } = others as { code_search: { remaining: number; limit: number } }
this.log.io({
core: `${core.remaining}/${core.limit}`,
Expand Down
Loading

0 comments on commit 5e9fffd

Please sign in to comment.