forked from rosa/hakurei
Compare commits
6 Commits
pkgserver-
...
pkgserver-
| Author | SHA1 | Date | |
|---|---|---|---|
|
296904ed17
|
|||
|
fcba9e96ed
|
|||
|
346fd599a5
|
|||
|
f8f94b0cc8
|
|||
|
786def0c34
|
|||
|
8cdfc0a819
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -31,10 +31,7 @@ go.work.sum
|
|||||||
/cmd/pkgserver/ui/static/*.js
|
/cmd/pkgserver/ui/static/*.js
|
||||||
/cmd/pkgserver/ui/static/*.css*
|
/cmd/pkgserver/ui/static/*.css*
|
||||||
/cmd/pkgserver/ui/static/*.css.map
|
/cmd/pkgserver/ui/static/*.css.map
|
||||||
/cmd/pkgserver/ui_test/*.js
|
/cmd/pkgserver/ui_test/static
|
||||||
/cmd/pkgserver/ui_test/lib/*.js
|
|
||||||
/cmd/pkgserver/ui_test/lib/*.css*
|
|
||||||
/cmd/pkgserver/ui_test/lib/*.css.map
|
|
||||||
/internal/pkg/testdata/testtool
|
/internal/pkg/testdata/testtool
|
||||||
/internal/rosa/hakurei_current.tar.gz
|
/internal/rosa/hakurei_current.tar.gz
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
var mux http.ServeMux
|
var mux http.ServeMux
|
||||||
uiRoutes(&mux)
|
uiRoutes(&mux)
|
||||||
testUiRoutes(&mux)
|
testUIRoutes(&mux)
|
||||||
index.registerAPI(&mux)
|
index.registerAPI(&mux)
|
||||||
server := http.Server{
|
server := http.Server{
|
||||||
Addr: flagAddr,
|
Addr: flagAddr,
|
||||||
|
|||||||
@@ -4,94 +4,32 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate tsc -p ui_test
|
// Always remove ui_test/ui; if the previous tsc run failed, the rm never
|
||||||
//go:generate sass ui_test/lib/ui.scss ui_test/lib/ui.css
|
// executes.
|
||||||
//go:embed ui_test/*
|
|
||||||
var test_content embed.FS
|
|
||||||
|
|
||||||
func serveTestWebUI(w http.ResponseWriter, r *http.Request) {
|
//go:generate sh -c "rm -r ui_test/ui/ 2>/dev/null || true"
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
//go:generate mkdir ui_test/ui
|
||||||
w.Header().Set("X-XSS-Protection", "1")
|
//go:generate sh -c "cp ui/static/*.ts ui_test/ui/"
|
||||||
w.Header().Set("X-Frame-Options", "DENY")
|
//go:generate tsc --outDir ui_test/static -p ui_test
|
||||||
|
//go:generate rm -r ui_test/ui/
|
||||||
|
//go:generate sass ui_test/lib/ui.scss ui_test/static/style.css
|
||||||
|
//go:generate cp ui_test/lib/ui.html ui_test/static/index.html
|
||||||
|
//go:generate sh -c "cd ui_test/lib && cp *.svg ../static/"
|
||||||
|
//go:embed ui_test/static
|
||||||
|
var _staticTest embed.FS
|
||||||
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/ui.html")
|
var staticTest = func() fs.FS {
|
||||||
|
if f, err := fs.Sub(_staticTest, "ui_test/static"); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return f
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
func serveTestWebUIStaticContent(w http.ResponseWriter, r *http.Request) {
|
func testUIRoutes(mux *http.ServeMux) {
|
||||||
switch r.URL.Path {
|
mux.Handle("GET /test/", http.StripPrefix("/test", http.FileServer(http.FS(staticTest))))
|
||||||
case "/testui/style.css":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/ui.css")
|
|
||||||
case "/testui/skip-closed.svg":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/skip-closed.svg")
|
|
||||||
case "/testui/skip-open.svg":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/skip-open.svg")
|
|
||||||
case "/testui/success-closed.svg":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/success-closed.svg")
|
|
||||||
case "/testui/success-open.svg":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/success-open.svg")
|
|
||||||
case "/testui/failure-closed.svg":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/failure-closed.svg")
|
|
||||||
case "/testui/failure-open.svg":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/failure-open.svg")
|
|
||||||
default:
|
|
||||||
http.NotFound(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveTestLibrary(w http.ResponseWriter, r *http.Request) {
|
|
||||||
switch r.URL.Path {
|
|
||||||
case "/test/lib/test.js":
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/lib/test.js")
|
|
||||||
default:
|
|
||||||
http.NotFound(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveTests(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path == "/test/" {
|
|
||||||
http.Redirect(w, r, "/test.html", http.StatusMovedPermanently)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
testPath := strings.TrimPrefix(r.URL.Path, "/test/")
|
|
||||||
|
|
||||||
if path.Ext(testPath) != ".js" {
|
|
||||||
http.Error(w, "403 forbidden", http.StatusForbidden)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
|
||||||
w.Header().Set("Pragma", "no-cache")
|
|
||||||
w.Header().Set("Expires", "0")
|
|
||||||
|
|
||||||
http.ServeFileFS(w, r, test_content, "ui_test/"+testPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func redirectUI(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// The base path should not redirect to the root.
|
|
||||||
if r.URL.Path == "/ui/" {
|
|
||||||
http.NotFound(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if path.Ext(r.URL.Path) != ".js" {
|
|
||||||
http.Error(w, "403 forbidden", http.StatusForbidden)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
|
||||||
w.Header().Set("Pragma", "no-cache")
|
|
||||||
w.Header().Set("Expires", "0")
|
|
||||||
|
|
||||||
http.Redirect(w, r, strings.TrimPrefix(r.URL.Path, "/ui"), http.StatusFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testUiRoutes(mux *http.ServeMux) {
|
|
||||||
mux.HandleFunc("GET /test.html", serveTestWebUI)
|
|
||||||
mux.HandleFunc("GET /testui/", serveTestWebUIStaticContent)
|
|
||||||
mux.HandleFunc("GET /test/lib", serveTestLibrary)
|
|
||||||
mux.HandleFunc("GET /test/", serveTests)
|
|
||||||
mux.HandleFunc("GET /ui/", redirectUI)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ package main
|
|||||||
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|
||||||
func testUiRoutes(mux *http.ServeMux) {}
|
func testUIRoutes(mux *http.ServeMux) {}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// Import all test files to execute their suite registrations.
|
// Import all test files to register their test suites.
|
||||||
import "./test_tests.js";
|
import "./index_test.js";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
// development.
|
// development.
|
||||||
|
|
||||||
import "../all_tests.js";
|
import "../all_tests.js";
|
||||||
import { StreamReporter, TESTS } from "./test.js";
|
import { StreamReporter, GLOBAL_REGISTRAR } from "./test.js";
|
||||||
|
|
||||||
// TypeScript doesn't like process and Deno as their type definitions aren't
|
// 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
|
// installed, but doesn't seem to complain if they're accessed through
|
||||||
@@ -44,5 +44,5 @@ if (args.length === 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let reporter = new StreamReporter({ writeln: console.log }, verbose);
|
let reporter = new StreamReporter({ writeln: console.log }, verbose);
|
||||||
TESTS.run(reporter);
|
GLOBAL_REGISTRAR.run(reporter);
|
||||||
exit(reporter.succeeded() ? 0 : 1);
|
exit(reporter.succeeded() ? 0 : 1);
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import "../all_tests.js";
|
import "../all_tests.js";
|
||||||
import { GoTestReporter, TESTS } from "./test.js";
|
import { GoTestReporter, GLOBAL_REGISTRAR } from "./test.js";
|
||||||
TESTS.run(new GoTestReporter());
|
GLOBAL_REGISTRAR.run(new GoTestReporter());
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// DSL
|
// DSL
|
||||||
|
|
||||||
type TestTree = TestGroup | Test;
|
type TestTree = TestGroup | Test;
|
||||||
type TestGroup = { name: string, children: TestTree[] };
|
type TestGroup = { name: string; children: TestTree[] };
|
||||||
type Test = { name: string, test: (t: TestController) => void };
|
type Test = { name: string; test: (t: TestController) => void };
|
||||||
|
|
||||||
export class TestRegistrar {
|
export class TestRegistrar {
|
||||||
#suites: TestGroup[];
|
#suites: TestGroup[];
|
||||||
@@ -13,7 +13,7 @@ export class TestRegistrar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suite(name: string, children: TestTree[]) {
|
suite(name: string, children: TestTree[]) {
|
||||||
checkDuplicates(name, children)
|
checkDuplicates(name, children);
|
||||||
this.#suites.push({ name, children });
|
this.#suites.push({ name, children });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,18 +26,19 @@ export class TestRegistrar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export let TESTS = new TestRegistrar();
|
export let GLOBAL_REGISTRAR = new TestRegistrar();
|
||||||
|
|
||||||
// Register a suite in the global registrar.
|
// Register a suite in the global registrar.
|
||||||
export function suite(name: string, children: TestTree[]) {
|
export function suite(name: string, children: TestTree[]) {
|
||||||
TESTS.suite(name, children);
|
GLOBAL_REGISTRAR.suite(name, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function context(name: string, children: TestTree[]): TestTree {
|
export function group(name: string, children: TestTree[]): TestTree {
|
||||||
checkDuplicates(name, children);
|
checkDuplicates(name, children);
|
||||||
return { name, children };
|
return { name, children };
|
||||||
}
|
}
|
||||||
export const group = context;
|
export const context = group;
|
||||||
|
export const describe = group;
|
||||||
|
|
||||||
export function test(name: string, test: (t: TestController) => void): TestTree {
|
export function test(name: string, test: (t: TestController) => void): TestTree {
|
||||||
return { name, test };
|
return { name, test };
|
||||||
@@ -148,7 +149,7 @@ function extractExceptionString(e: any): string {
|
|||||||
// Reporting
|
// Reporting
|
||||||
|
|
||||||
export interface Reporter {
|
export interface Reporter {
|
||||||
register(suites: TestGroup[]): void
|
register(suites: TestGroup[]): void;
|
||||||
update(path: string[], result: TestResult): void;
|
update(path: string[], result: TestResult): void;
|
||||||
finalize(): void;
|
finalize(): void;
|
||||||
}
|
}
|
||||||
@@ -229,8 +230,8 @@ export class StreamReporter implements Reporter {
|
|||||||
this.#displaySection("skips", this.#skips);
|
this.#displaySection("skips", this.#skips);
|
||||||
this.stream.writeln("");
|
this.stream.writeln("");
|
||||||
this.stream.writeln(
|
this.stream.writeln(
|
||||||
`${this.#successes.length} succeeded, ${this.#failures.length} failed`
|
`${this.#successes.length} succeeded, ${this.#failures.length} failed` +
|
||||||
+ (this.#skips.length ? `, ${this.#skips.length} skipped` : "")
|
(this.#skips.length ? `, ${this.#skips.length} skipped` : ""),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +294,7 @@ export class DOMReporter implements Reporter {
|
|||||||
update(path: string[], result: TestResult) {
|
update(path: string[], result: TestResult) {
|
||||||
if (path.length === 0) throw new RangeError("path is empty");
|
if (path.length === 0) throw new RangeError("path is empty");
|
||||||
if (result.state === "skip") {
|
if (result.state === "skip") {
|
||||||
assertGetElementById("skip-counter-text").classList.remove("hidden");
|
assertGetElementById("skip-counter-text").hidden = false;
|
||||||
}
|
}
|
||||||
const counter = assertGetElementById(`${result.state}-counter`);
|
const counter = assertGetElementById(`${result.state}-counter`);
|
||||||
counter.innerText = (Number(counter.innerText) + 1).toString();
|
counter.innerText = (Number(counter.innerText) + 1).toString();
|
||||||
@@ -331,6 +332,8 @@ export class DOMReporter implements Reporter {
|
|||||||
child.classList.add("failure");
|
child.classList.add("failure");
|
||||||
child.classList.remove("skip");
|
child.classList.remove("skip");
|
||||||
child.classList.remove("success");
|
child.classList.remove("success");
|
||||||
|
// The summary marker does not appear in the AOM, so setting its
|
||||||
|
// alt text is fruitless; label the summary itself instead.
|
||||||
summary.setAttribute("aria-labelledby", "failure-description");
|
summary.setAttribute("aria-labelledby", "failure-description");
|
||||||
break;
|
break;
|
||||||
case "skip":
|
case "skip":
|
||||||
@@ -367,23 +370,23 @@ export class DOMReporter implements Reporter {
|
|||||||
|
|
||||||
interface GoNode {
|
interface GoNode {
|
||||||
name: string;
|
name: string;
|
||||||
subtests: GoNode[] | null;
|
subtests?: GoNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to display results via `go test`, via some glue code from the Go side.
|
// Used to display results via `go test`, via some glue code from the Go side.
|
||||||
export class GoTestReporter implements Reporter {
|
export class GoTestReporter implements Reporter {
|
||||||
|
register(suites: TestGroup[]) {
|
||||||
|
console.log(JSON.stringify(suites.map(GoTestReporter.serialize)));
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a test tree into the one expected by the Go code.
|
// Convert a test tree into the one expected by the Go code.
|
||||||
static serialize(node: TestTree): GoNode {
|
static serialize(node: TestTree): GoNode {
|
||||||
return {
|
return {
|
||||||
name: node.name,
|
name: node.name,
|
||||||
subtests: "children" in node ? node.children.map(GoTestReporter.serialize) : null,
|
subtests: "children" in node ? node.children.map(GoTestReporter.serialize) : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register(suites: TestGroup[]) {
|
|
||||||
console.log(JSON.stringify(suites.map(GoTestReporter.serialize)));
|
|
||||||
}
|
|
||||||
|
|
||||||
update(path: string[], result: TestResult) {
|
update(path: string[], result: TestResult) {
|
||||||
let state: number;
|
let state: number;
|
||||||
switch (result.state) {
|
switch (result.state) {
|
||||||
@@ -391,7 +394,7 @@ export class GoTestReporter implements Reporter {
|
|||||||
case "failure": state = 1; break;
|
case "failure": state = 1; break;
|
||||||
case "skip": state = 2; break;
|
case "skip": state = 2; break;
|
||||||
}
|
}
|
||||||
console.log(JSON.stringify({ path: path, state, logs: result.logs }));
|
console.log(JSON.stringify({ path, state, logs: result.logs }));
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize() {
|
finalize() {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="/testui/style.css">
|
<link rel="stylesheet" href="/test/style.css">
|
||||||
<title>PkgServer Tests</title>
|
<title>PkgServer Tests</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<main>
|
<main>
|
||||||
<p id="counters">
|
<p id="counters">
|
||||||
<span id="success-counter">0</span> succeeded, <span id="failure-counter">0</span>
|
<span id="success-counter">0</span> succeeded, <span id="failure-counter">0</span>
|
||||||
failed<span id="skip-counter-text" class="hidden">, <span id="skip-counter">0</span> skipped</span>.
|
failed<span id="skip-counter-text" hidden>, <span id="skip-counter">0</span> skipped</span>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p hidden id="success-description">Successful test</p>
|
<p hidden id="success-description">Successful test</p>
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import "/test/all_tests.js";
|
import "/test/all_tests.js";
|
||||||
import { DOMReporter, TESTS } from "/test/lib/test.js";
|
import { DOMReporter, GLOBAL_REGISTRAR } from "/test/lib/test.js";
|
||||||
TESTS.run(new DOMReporter());
|
GLOBAL_REGISTRAR.run(new DOMReporter());
|
||||||
</script>
|
</script>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* If updating the theme colors, also update them in success-closed.svg and
|
||||||
|
* success-open.svg!
|
||||||
|
*/
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bg: #d3d3d3;
|
--bg: #d3d3d3;
|
||||||
--fg: black;
|
--fg: black;
|
||||||
@@ -49,24 +54,24 @@ details.test-node {
|
|||||||
* [3]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/summary#changing_the_summarys_icon
|
* [3]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/summary#changing_the_summarys_icon
|
||||||
*/
|
*/
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
content: url("/testui/success-closed.svg") / "success";
|
content: url("/test/success-closed.svg") / "success";
|
||||||
}
|
}
|
||||||
&.success[open] > summary::marker {
|
&.success[open] > summary::marker {
|
||||||
content: url("/testui/success-open.svg") / "success";
|
content: url("/test/success-open.svg") / "success";
|
||||||
}
|
}
|
||||||
&.failure > summary::marker {
|
&.failure > summary::marker {
|
||||||
color: red;
|
color: red;
|
||||||
content: url("/testui/failure-closed.svg") / "failure";
|
content: url("/test/failure-closed.svg") / "failure";
|
||||||
}
|
}
|
||||||
&.failure[open] > summary::marker {
|
&.failure[open] > summary::marker {
|
||||||
content: url("/testui/failure-open.svg") / "failure";
|
content: url("/test/failure-open.svg") / "failure";
|
||||||
}
|
}
|
||||||
&.skip > summary::marker {
|
&.skip > summary::marker {
|
||||||
color: blue;
|
color: blue;
|
||||||
content: url("/testui/skip-closed.svg") / "skip";
|
content: url("/test/skip-closed.svg") / "skip";
|
||||||
}
|
}
|
||||||
&.skip[open] > summary::marker {
|
&.skip[open] > summary::marker {
|
||||||
content: url("/testui/skip-open.svg") / "skip";
|
content: url("/test/skip-open.svg") / "skip";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,10 +83,6 @@ p.test-desc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.italic {
|
.italic {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import { NoOpReporter, TestRegistrar, context, group, suite, test } from "./lib/test.js";
|
|
||||||
|
|
||||||
suite("dog", [
|
|
||||||
group("tail", [
|
|
||||||
test("wags when happy", (t) => {
|
|
||||||
if (0 / 0 !== Infinity / Infinity) {
|
|
||||||
t.fatal("undefined must not be defined");
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
test("idle when down", (t) => {
|
|
||||||
t.log("test test");
|
|
||||||
t.error("dog whining noises go here");
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
test("likes headpats", (t) => {
|
|
||||||
if (2 !== 2) {
|
|
||||||
t.error("IEEE 754 violated: 2 is NaN");
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
context("near cat", [
|
|
||||||
test("is ecstatic", (t) => {
|
|
||||||
if (("b" + "a" + + "a" + "a").toLowerCase() === "banana") {
|
|
||||||
t.error("🍌🍌🍌");
|
|
||||||
t.error("🍌🍌🍌");
|
|
||||||
t.error("🍌🍌🍌");
|
|
||||||
t.failNow();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
test("playfully bites cats' tails", (t) => {
|
|
||||||
t.log("arf!");
|
|
||||||
throw new Error("nom");
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
suite("cat", [
|
|
||||||
test("likes headpats", (t) => {
|
|
||||||
t.log("meow");
|
|
||||||
}),
|
|
||||||
test("owns skipping rope", (t) => {
|
|
||||||
t.skip("this cat is stuck in your machine!");
|
|
||||||
t.log("never logged");
|
|
||||||
}),
|
|
||||||
test("tester tester", (t) => {
|
|
||||||
const r = new TestRegistrar();
|
|
||||||
r.suite("explod", [
|
|
||||||
test("with yarn", (t) => {
|
|
||||||
t.log("YAY");
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
const reporter = new NoOpReporter();
|
|
||||||
r.run(reporter);
|
|
||||||
if (reporter.suites.length !== 1) {
|
|
||||||
t.fatal(`incorrect number of suites registered got=${reporter.suites.length} want=1`);
|
|
||||||
}
|
|
||||||
const suite = reporter.suites[0];
|
|
||||||
if (suite.name !== "explod") {
|
|
||||||
t.error(`suite name incorrect got='${suite.name}' want='explod'`);
|
|
||||||
}
|
|
||||||
if (suite.children.length !== 1) {
|
|
||||||
t.fatal(`incorrect number of suite children got=${suite.children.length} want=1`);
|
|
||||||
}
|
|
||||||
const test_ = suite.children[0];
|
|
||||||
if (test_.name !== "with yarn") {
|
|
||||||
t.error(`incorrect test name got='${test_.name}' want='with yarn'`);
|
|
||||||
}
|
|
||||||
if ("children" in test_) {
|
|
||||||
t.error(`expected leaf node, got group of ${test_.children.length} children`);
|
|
||||||
}
|
|
||||||
if (!reporter.finalized) t.error(`expected reporter to have been finalized`);
|
|
||||||
if (reporter.results.length !== 1) {
|
|
||||||
t.fatal(`incorrect result count got=${reporter.results.length} want=1`);
|
|
||||||
}
|
|
||||||
const result = reporter.results[0];
|
|
||||||
if (!(result.path.length === 2 &&
|
|
||||||
result.path[0] === "explod" &&
|
|
||||||
result.path[1] === "with yarn")) {
|
|
||||||
t.error(`incorrect result path got=${result.path} want=["explod", "with yarn"]`);
|
|
||||||
}
|
|
||||||
if (result.state !== "success") t.error(`expected test to succeed`);
|
|
||||||
if (!(result.logs.length === 1 && result.logs[0] === "YAY")) {
|
|
||||||
t.error(`incorrect result logs got=${result.logs} want=["YAY"]`);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
Reference in New Issue
Block a user