forked from rosa/hakurei
Compare commits
19 Commits
d01cf2cb25
...
58b879f48f
| Author | SHA1 | Date | |
|---|---|---|---|
|
58b879f48f
|
|||
|
252e9a4efc
|
|||
|
7cba25eb40
|
|||
|
20cfb8201c
|
|||
|
4385922bb8
|
|||
|
82c73c36cf
|
|||
|
dc883c9c49
|
|||
|
6888033e8d
|
|||
|
7c39b32470
|
|||
|
52b9b7754a
|
|||
|
0d0c659649
|
|||
|
47962b1f55
|
|||
|
f160d1ab7f
|
|||
|
9fbd26217a
|
|||
|
79e0bacf76
|
|||
|
d552b98d42
|
|||
|
795f27205c
|
|||
|
19857a02dc
|
|||
|
6fffc4ccfc
|
@@ -1,4 +1,10 @@
|
||||
class PackageIndexEntry {
|
||||
function assertGetElementById(id: string): HTMLElement {
|
||||
let elem = document.getElementById(id)
|
||||
if(elem == null) throw new ReferenceError(`element with ID '${id}' missing from DOM`)
|
||||
return elem
|
||||
}
|
||||
|
||||
interface PackageIndexEntry {
|
||||
name: string
|
||||
size: number | null
|
||||
description: string | null
|
||||
@@ -34,7 +40,7 @@ function toByteSizeString(bytes: number): string {
|
||||
|
||||
const API_VERSION = 1
|
||||
const ENDPOINT = `/api/v${API_VERSION}`
|
||||
class InfoPayload {
|
||||
interface InfoPayload {
|
||||
count: number
|
||||
hakurei_version: string
|
||||
}
|
||||
@@ -42,9 +48,9 @@ class InfoPayload {
|
||||
async function infoRequest(): Promise<InfoPayload> {
|
||||
const res = await fetch(`${ENDPOINT}/info`)
|
||||
const payload = await res.json()
|
||||
return payload as InfoPayload
|
||||
return payload
|
||||
}
|
||||
class GetPayload {
|
||||
interface GetPayload {
|
||||
values: PackageIndexEntry[]
|
||||
}
|
||||
|
||||
@@ -57,7 +63,7 @@ enum SortOrders {
|
||||
async function getRequest(limit: number, index: number, sort: SortOrders): Promise<GetPayload> {
|
||||
const res = await fetch(`${ENDPOINT}/get?limit=${limit}&index=${index}&sort=${sort.valueOf()}`)
|
||||
const payload = await res.json()
|
||||
return payload as GetPayload
|
||||
return payload
|
||||
}
|
||||
class State {
|
||||
entriesPerPage: number = 10
|
||||
@@ -96,16 +102,16 @@ class State {
|
||||
}
|
||||
updatePage() {
|
||||
let page = Math.ceil(((this.getEntryIndex() + this.getEntriesPerPage()) - 1) / this.getEntriesPerPage())
|
||||
document.getElementById("page-number").innerText = String(page)
|
||||
assertGetElementById("page-number").innerText = String(page)
|
||||
}
|
||||
updateRange() {
|
||||
let max = Math.min(this.getEntryIndex() + this.getEntriesPerPage(), this.getMaxEntries())
|
||||
document.getElementById("entry-counter").innerText = `${this.getEntryIndex() + 1}-${max} of ${this.getMaxEntries()}`
|
||||
assertGetElementById("entry-counter").innerText = `${this.getEntryIndex() + 1}-${max} of ${this.getMaxEntries()}`
|
||||
}
|
||||
updateListings() {
|
||||
getRequest(this.getEntriesPerPage(), this.getEntryIndex(), this.getSortOrder())
|
||||
.then(res => {
|
||||
let table = document.getElementById("pkg-list")
|
||||
let table = assertGetElementById("pkg-list")
|
||||
table.innerHTML = ''
|
||||
res.values.forEach((row) => {
|
||||
table.appendChild(toHTML(row))
|
||||
@@ -141,15 +147,15 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
infoRequest()
|
||||
.then(res => {
|
||||
STATE.setMaxEntries(res.count)
|
||||
document.getElementById("hakurei-version").innerText = res.hakurei_version
|
||||
assertGetElementById("hakurei-version").innerText = res.hakurei_version
|
||||
STATE.updateRange()
|
||||
STATE.updateListings()
|
||||
})
|
||||
|
||||
document.getElementById("count").addEventListener("change", (event) => {
|
||||
assertGetElementById("count").addEventListener("change", (event) => {
|
||||
STATE.setEntriesPerPage(parseInt((event.target as HTMLSelectElement).value))
|
||||
})
|
||||
document.getElementById("sort").addEventListener("change", (event) => {
|
||||
assertGetElementById("sort").addEventListener("change", (event) => {
|
||||
STATE.setSortOrder(parseInt((event.target as HTMLSelectElement).value))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,8 +10,8 @@ import { StreamReporter, TESTS } from "./test.js";
|
||||
// TypeScript doesn't like process and Deno as their type definitions aren't
|
||||
// installed, but doesn't seem to complain if they're accessed through
|
||||
// globalThis.
|
||||
const process: any = globalThis.process;
|
||||
const Deno: any = globalThis.Deno;
|
||||
const process: any = (globalThis as any).process;
|
||||
const Deno: any = (globalThis as any).Deno;
|
||||
|
||||
function getArgs(): string[] {
|
||||
if (process) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
type TestTree = TestGroup | Test;
|
||||
type TestGroup = { name: string, children: TestTree[] };
|
||||
type Test = { name: string, test: (TestController) => void };
|
||||
type Test = { name: string, test: (t: TestController) => void };
|
||||
|
||||
export class TestRegistrar {
|
||||
#suites: TestGroup[];
|
||||
@@ -39,7 +39,7 @@ export function context(name: string, children: TestTree[]): TestTree {
|
||||
}
|
||||
export const group = context;
|
||||
|
||||
export function test(name: string, test: (TestController) => void): TestTree {
|
||||
export function test(name: string, test: (t: TestController) => void): TestTree {
|
||||
return { name, test };
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ function extractExceptionString(e: any): string {
|
||||
// String() instead of .toString() as null and undefined don't have
|
||||
// properties.
|
||||
const s = String(e);
|
||||
if (!(e instanceof Error && "stack" in e)) return s;
|
||||
if (!(e instanceof Error && e.stack)) return s;
|
||||
// v8 (Chromium, NodeJS) include the error message, while Firefox and WebKit
|
||||
// do not.
|
||||
if (e.stack.startsWith(s)) return e.stack;
|
||||
@@ -241,9 +241,10 @@ export class StreamReporter implements Reporter {
|
||||
// into { "a ❯ b": ["c", "d"] }.
|
||||
let pathMap = new Map<string, ({ name: string } & TestResult)[]>();
|
||||
for (const t of data) {
|
||||
if (t.path.length === 0) throw new RangeError("path is empty");
|
||||
const key = t.path.slice(0, -1).join(SEP);
|
||||
if (!pathMap.has(key)) pathMap.set(key, []);
|
||||
pathMap.get(key).push({ name: t.path.at(-1), ...t });
|
||||
pathMap.get(key)!.push({ name: t.path.at(-1)!, ...t });
|
||||
}
|
||||
|
||||
this.stream.writeln("");
|
||||
@@ -280,22 +281,31 @@ export class StreamReporter implements Reporter {
|
||||
}
|
||||
}
|
||||
|
||||
function throwNotInDOMError(id: string): never {
|
||||
throw new ReferenceError(`element with ID '${id}' missing from DOM`);
|
||||
}
|
||||
|
||||
export class DOMReporter implements Reporter {
|
||||
register(suites: TestGroup[]) {}
|
||||
|
||||
update(path: string[], result: TestResult) {
|
||||
if (path.length === 0) throw new RangeError("path is empty");
|
||||
if (result.state === "skip") {
|
||||
document.getElementById("skip-counter-text").classList.remove("hidden");
|
||||
const text = document.getElementById("skip-counter-text");
|
||||
if (!text) throwNotInDOMError("skip-counter-text");
|
||||
text.classList.remove("hidden");
|
||||
}
|
||||
const counter = document.getElementById(`${result.state}-counter`);
|
||||
if (!counter) throwNotInDOMError(`${result.state}-counter`);
|
||||
counter.innerText = (Number(counter.innerText) + 1).toString();
|
||||
|
||||
let parent = document.getElementById("root");
|
||||
if (!parent) throwNotInDOMError("root");
|
||||
for (const node of path) {
|
||||
let child: HTMLDetailsElement;
|
||||
let summary: HTMLElement;
|
||||
outer: for (const d of parent.children) {
|
||||
let child: HTMLDetailsElement | null = null;
|
||||
let summary: HTMLElement | null = null;
|
||||
let d: Element;
|
||||
outer: for (d of parent.children) {
|
||||
if (!(d instanceof HTMLDetailsElement)) continue;
|
||||
for (const s of d.children) {
|
||||
if (!(s instanceof HTMLElement)) continue;
|
||||
@@ -315,6 +325,7 @@ export class DOMReporter implements Reporter {
|
||||
child.appendChild(summary);
|
||||
parent.appendChild(child);
|
||||
}
|
||||
if (!summary) throw new Error("unreachable as assigned above");
|
||||
|
||||
switch (result.state) {
|
||||
case "failure":
|
||||
@@ -358,7 +369,7 @@ export class DOMReporter implements Reporter {
|
||||
|
||||
interface GoNode {
|
||||
name: string;
|
||||
subtests?: GoNode[];
|
||||
subtests: GoNode[] | null;
|
||||
}
|
||||
|
||||
// Used to display results via `go test`, via some glue code from the Go side.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "ES2024"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user