@ripplo/testing 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DSL.md +357 -0
- package/LICENSE.md +1 -0
- package/README.md +47 -273
- package/dist/engine-BfvzXgLg.d.ts +1091 -0
- package/dist/express.d.ts +7 -9
- package/dist/express.js +422 -48
- package/dist/index.d.ts +134 -59
- package/dist/index.js +1654 -1126
- package/package.json +31 -113
- package/dist/actions.d.ts +0 -260
- package/dist/actions.js +0 -177
- package/dist/assert.d.ts +0 -188
- package/dist/assert.js +0 -111
- package/dist/builder-SsgqYqSC.d.ts +0 -156
- package/dist/chunk-2YLI7VD4.js +0 -65
- package/dist/chunk-4MGIQFAJ.js +0 -16
- package/dist/chunk-DCJBLS2U.js +0 -26
- package/dist/chunk-MGATMMCZ.js +0 -16
- package/dist/chunk-XO36IU66.js +0 -88
- package/dist/chunk-YFOTJIVF.js +0 -134
- package/dist/chunk-YQAEOH5W.js +0 -111
- package/dist/compiler.d.ts +0 -32
- package/dist/compiler.js +0 -8
- package/dist/control.d.ts +0 -45
- package/dist/control.js +0 -17
- package/dist/elysia.d.ts +0 -78
- package/dist/elysia.js +0 -114
- package/dist/engine-BOqzK_go.d.ts +0 -61
- package/dist/fastify.d.ts +0 -14
- package/dist/fastify.js +0 -79
- package/dist/hono.d.ts +0 -19
- package/dist/hono.js +0 -89
- package/dist/koa.d.ts +0 -14
- package/dist/koa.js +0 -135
- package/dist/locators.d.ts +0 -40
- package/dist/locators.js +0 -11
- package/dist/lockfile.d.ts +0 -722
- package/dist/lockfile.js +0 -707
- package/dist/nestjs.d.ts +0 -17
- package/dist/nestjs.js +0 -139
- package/dist/nextjs.d.ts +0 -14
- package/dist/nextjs.js +0 -137
- package/dist/step-De52hTLd.d.ts +0 -19
- package/dist/types-BzZrl65Z.d.ts +0 -115
package/dist/fastify.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
batchRequestSchema,
|
|
3
|
-
observerRequestSchema,
|
|
4
|
-
readAdapterWebhookSecret,
|
|
5
|
-
teardownRequestSchema,
|
|
6
|
-
toBatchRunResults,
|
|
7
|
-
toTeardownResults,
|
|
8
|
-
verifyWebhookSignature
|
|
9
|
-
} from "./chunk-XO36IU66.js";
|
|
10
|
-
import "./chunk-4MGIQFAJ.js";
|
|
11
|
-
|
|
12
|
-
// src/adapters/fastify.ts
|
|
13
|
-
function registerFastifyHandler({
|
|
14
|
-
enabled,
|
|
15
|
-
engine
|
|
16
|
-
}) {
|
|
17
|
-
if (!enabled) {
|
|
18
|
-
return async () => {
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
const webhookSecret = readAdapterWebhookSecret();
|
|
22
|
-
return async (fastify) => {
|
|
23
|
-
fastify.addHook("preHandler", async (req, reply) => {
|
|
24
|
-
const payload = JSON.stringify(req.body);
|
|
25
|
-
const headers = {
|
|
26
|
-
"webhook-id": extractHeader(req, "webhook-id"),
|
|
27
|
-
"webhook-signature": extractHeader(req, "webhook-signature"),
|
|
28
|
-
"webhook-timestamp": extractHeader(req, "webhook-timestamp")
|
|
29
|
-
};
|
|
30
|
-
if (!verifyWebhookSignature(payload, headers, webhookSecret)) {
|
|
31
|
-
return reply.code(401).send({ error: "Invalid webhook signature" });
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
fastify.put("/execute-preconditions", async (req, reply) => {
|
|
35
|
-
const parsed = batchRequestSchema.safeParse(req.body);
|
|
36
|
-
if (!parsed.success) {
|
|
37
|
-
return reply.code(400).send({ error: "Invalid request body" });
|
|
38
|
-
}
|
|
39
|
-
const appUrl = `${req.protocol}://${req.hostname}`;
|
|
40
|
-
const items = parsed.data.batch.map((b) => ({ names: b.preconditions, runId: b.runId }));
|
|
41
|
-
const results = await engine.executePreconditions(items, { appUrl });
|
|
42
|
-
return reply.send({ results: toBatchRunResults(results) });
|
|
43
|
-
});
|
|
44
|
-
fastify.put("/execute-observer", async (req, reply) => {
|
|
45
|
-
const parsed = observerRequestSchema.safeParse(req.body);
|
|
46
|
-
if (!parsed.success) {
|
|
47
|
-
return reply.code(400).send({ error: "Invalid request body", success: false });
|
|
48
|
-
}
|
|
49
|
-
const result = await engine.executeObserver(parsed.data.observer, parsed.data.params);
|
|
50
|
-
return reply.send({ error: result.error, outcome: result.outcome, success: result.success });
|
|
51
|
-
});
|
|
52
|
-
fastify.put("/teardown-preconditions", async (req, reply) => {
|
|
53
|
-
const parsed = teardownRequestSchema.safeParse(req.body);
|
|
54
|
-
if (!parsed.success) {
|
|
55
|
-
return reply.code(400).send({ error: "Invalid request body" });
|
|
56
|
-
}
|
|
57
|
-
const items = parsed.data.batch.map((b) => ({
|
|
58
|
-
data: b.data,
|
|
59
|
-
names: b.preconditions,
|
|
60
|
-
runId: b.runId
|
|
61
|
-
}));
|
|
62
|
-
const results = await engine.teardown(items);
|
|
63
|
-
return reply.send({ results: toTeardownResults(results) });
|
|
64
|
-
});
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
function extractHeader(req, name) {
|
|
68
|
-
const value = req.headers[name];
|
|
69
|
-
if (typeof value === "string") {
|
|
70
|
-
return value;
|
|
71
|
-
}
|
|
72
|
-
if (Array.isArray(value)) {
|
|
73
|
-
return value[0] ?? void 0;
|
|
74
|
-
}
|
|
75
|
-
return void 0;
|
|
76
|
-
}
|
|
77
|
-
export {
|
|
78
|
-
registerFastifyHandler
|
|
79
|
-
};
|
package/dist/hono.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Hono } from 'hono';
|
|
2
|
-
import { R as RipploEngine } from './engine-BOqzK_go.js';
|
|
3
|
-
import './builder-SsgqYqSC.js';
|
|
4
|
-
import './types-BzZrl65Z.js';
|
|
5
|
-
import './step-De52hTLd.js';
|
|
6
|
-
import '@ripplo/spec';
|
|
7
|
-
|
|
8
|
-
interface CreateHonoHandlerParams {
|
|
9
|
-
readonly enabled: boolean;
|
|
10
|
-
readonly engine: RipploEngine;
|
|
11
|
-
}
|
|
12
|
-
interface HonoEnv {
|
|
13
|
-
Variables: {
|
|
14
|
-
rawBody: string;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
declare function createHonoHandler({ enabled, engine }: CreateHonoHandlerParams): Hono<HonoEnv>;
|
|
18
|
-
|
|
19
|
-
export { type CreateHonoHandlerParams, createHonoHandler };
|
package/dist/hono.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
batchRequestSchema,
|
|
3
|
-
observerRequestSchema,
|
|
4
|
-
readAdapterWebhookSecret,
|
|
5
|
-
teardownRequestSchema,
|
|
6
|
-
toBatchRunResults,
|
|
7
|
-
toTeardownResults,
|
|
8
|
-
verifyWebhookSignature
|
|
9
|
-
} from "./chunk-XO36IU66.js";
|
|
10
|
-
import "./chunk-4MGIQFAJ.js";
|
|
11
|
-
|
|
12
|
-
// src/adapters/hono.ts
|
|
13
|
-
import { Hono } from "hono";
|
|
14
|
-
function createHonoHandler({ enabled, engine }) {
|
|
15
|
-
const app = new Hono();
|
|
16
|
-
if (!enabled) {
|
|
17
|
-
return app;
|
|
18
|
-
}
|
|
19
|
-
const webhookSecret = readAdapterWebhookSecret();
|
|
20
|
-
app.use("*", createWebhookMiddleware(webhookSecret));
|
|
21
|
-
app.put("/execute-preconditions", async (c) => {
|
|
22
|
-
const body = tryParseJson(c.get("rawBody"));
|
|
23
|
-
const parsed = body == null ? null : batchRequestSchema.safeParse(body);
|
|
24
|
-
if (parsed == null || !parsed.success) {
|
|
25
|
-
return c.json({ error: "Invalid request body" }, 400);
|
|
26
|
-
}
|
|
27
|
-
const host = c.req.header("host");
|
|
28
|
-
if (host == null || host.length === 0) {
|
|
29
|
-
return c.json({ error: "Missing host header" }, 400);
|
|
30
|
-
}
|
|
31
|
-
const proto = c.req.header("x-forwarded-proto") ?? "http";
|
|
32
|
-
const appUrl = `${proto}://${host}`;
|
|
33
|
-
const items = parsed.data.batch.map((b) => ({ names: b.preconditions, runId: b.runId }));
|
|
34
|
-
const results = await engine.executePreconditions(items, { appUrl });
|
|
35
|
-
return c.json({ results: toBatchRunResults(results) });
|
|
36
|
-
});
|
|
37
|
-
app.put("/execute-observer", async (c) => {
|
|
38
|
-
const body = tryParseJson(c.get("rawBody"));
|
|
39
|
-
const parsed = body == null ? null : observerRequestSchema.safeParse(body);
|
|
40
|
-
if (parsed == null || !parsed.success) {
|
|
41
|
-
return c.json({ error: "Invalid request body", success: false }, 400);
|
|
42
|
-
}
|
|
43
|
-
const result = await engine.executeObserver(parsed.data.observer, parsed.data.params);
|
|
44
|
-
return c.json({ error: result.error, outcome: result.outcome, success: result.success });
|
|
45
|
-
});
|
|
46
|
-
app.put("/teardown-preconditions", async (c) => {
|
|
47
|
-
const body = tryParseJson(c.get("rawBody"));
|
|
48
|
-
const parsed = body == null ? null : teardownRequestSchema.safeParse(body);
|
|
49
|
-
if (parsed == null || !parsed.success) {
|
|
50
|
-
return c.json({ error: "Invalid request body" }, 400);
|
|
51
|
-
}
|
|
52
|
-
const items = parsed.data.batch.map((b) => ({
|
|
53
|
-
data: b.data,
|
|
54
|
-
names: b.preconditions,
|
|
55
|
-
runId: b.runId
|
|
56
|
-
}));
|
|
57
|
-
const results = await engine.teardown(items);
|
|
58
|
-
return c.json({ results: toTeardownResults(results) });
|
|
59
|
-
});
|
|
60
|
-
return app;
|
|
61
|
-
}
|
|
62
|
-
function createWebhookMiddleware(webhookSecret) {
|
|
63
|
-
return async (c, next) => {
|
|
64
|
-
if (webhookSecret.length === 0) {
|
|
65
|
-
return c.json({ error: "Webhook secret not configured" }, 403);
|
|
66
|
-
}
|
|
67
|
-
const body = await c.req.text();
|
|
68
|
-
const headers = {
|
|
69
|
-
"webhook-id": c.req.header("webhook-id"),
|
|
70
|
-
"webhook-signature": c.req.header("webhook-signature"),
|
|
71
|
-
"webhook-timestamp": c.req.header("webhook-timestamp")
|
|
72
|
-
};
|
|
73
|
-
if (!verifyWebhookSignature(body, headers, webhookSecret)) {
|
|
74
|
-
return c.json({ error: "Invalid webhook signature" }, 401);
|
|
75
|
-
}
|
|
76
|
-
c.set("rawBody", body);
|
|
77
|
-
await next();
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function tryParseJson(body) {
|
|
81
|
-
try {
|
|
82
|
-
return JSON.parse(body);
|
|
83
|
-
} catch {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
export {
|
|
88
|
-
createHonoHandler
|
|
89
|
-
};
|
package/dist/koa.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Middleware } from 'koa';
|
|
2
|
-
import { R as RipploEngine } from './engine-BOqzK_go.js';
|
|
3
|
-
import './builder-SsgqYqSC.js';
|
|
4
|
-
import './types-BzZrl65Z.js';
|
|
5
|
-
import './step-De52hTLd.js';
|
|
6
|
-
import '@ripplo/spec';
|
|
7
|
-
|
|
8
|
-
interface CreateKoaHandlerParams {
|
|
9
|
-
readonly enabled: boolean;
|
|
10
|
-
readonly engine: RipploEngine;
|
|
11
|
-
}
|
|
12
|
-
declare function createKoaHandler({ enabled, engine }: CreateKoaHandlerParams): Middleware;
|
|
13
|
-
|
|
14
|
-
export { type CreateKoaHandlerParams, createKoaHandler };
|
package/dist/koa.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
batchRequestSchema,
|
|
3
|
-
observerRequestSchema,
|
|
4
|
-
readAdapterWebhookSecret,
|
|
5
|
-
teardownRequestSchema,
|
|
6
|
-
toBatchRunResults,
|
|
7
|
-
toTeardownResults,
|
|
8
|
-
verifyWebhookSignature
|
|
9
|
-
} from "./chunk-XO36IU66.js";
|
|
10
|
-
import "./chunk-4MGIQFAJ.js";
|
|
11
|
-
|
|
12
|
-
// src/adapters/koa.ts
|
|
13
|
-
function createKoaHandler({ enabled, engine }) {
|
|
14
|
-
if (!enabled) {
|
|
15
|
-
return async (_ctx, next) => {
|
|
16
|
-
await next();
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
const webhookSecret = readAdapterWebhookSecret();
|
|
20
|
-
return async (ctx, next) => {
|
|
21
|
-
if (ctx.method !== "PUT") {
|
|
22
|
-
await next();
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const action = lastPathSegment(ctx.path);
|
|
26
|
-
if (action == null) {
|
|
27
|
-
await next();
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const body = await readBody(ctx);
|
|
31
|
-
const headers = {
|
|
32
|
-
"webhook-id": headerString(ctx.get("webhook-id")),
|
|
33
|
-
"webhook-signature": headerString(ctx.get("webhook-signature")),
|
|
34
|
-
"webhook-timestamp": headerString(ctx.get("webhook-timestamp"))
|
|
35
|
-
};
|
|
36
|
-
if (!verifyWebhookSignature(body, headers, webhookSecret)) {
|
|
37
|
-
ctx.status = 401;
|
|
38
|
-
ctx.body = { error: "Invalid webhook signature" };
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
await dispatchAction({ action, body, ctx, engine });
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
async function dispatchAction({ action, body, ctx, engine }) {
|
|
45
|
-
if (action === "execute-preconditions") {
|
|
46
|
-
await handleExecutePreconditions({ body, ctx, engine });
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
if (action === "execute-observer") {
|
|
50
|
-
await handleExecuteObserver({ body, ctx, engine });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
await handleTeardown({ body, ctx, engine });
|
|
54
|
-
}
|
|
55
|
-
async function handleExecutePreconditions({ body, ctx, engine }) {
|
|
56
|
-
const json = tryParseJson(body);
|
|
57
|
-
const parsed = json == null ? null : batchRequestSchema.safeParse(json);
|
|
58
|
-
if (parsed == null || !parsed.success) {
|
|
59
|
-
ctx.status = 400;
|
|
60
|
-
ctx.body = { error: "Invalid request body" };
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const host = ctx.get("host");
|
|
64
|
-
if (host.length === 0) {
|
|
65
|
-
ctx.status = 400;
|
|
66
|
-
ctx.body = { error: "Missing host header" };
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const proto = ctx.get("x-forwarded-proto").length > 0 ? ctx.get("x-forwarded-proto") : "http";
|
|
70
|
-
const appUrl = `${proto}://${host}`;
|
|
71
|
-
const items = parsed.data.batch.map((b) => ({ names: b.preconditions, runId: b.runId }));
|
|
72
|
-
const results = await engine.executePreconditions(items, { appUrl });
|
|
73
|
-
ctx.status = 200;
|
|
74
|
-
ctx.body = { results: toBatchRunResults(results) };
|
|
75
|
-
}
|
|
76
|
-
async function handleExecuteObserver({ body, ctx, engine }) {
|
|
77
|
-
const json = tryParseJson(body);
|
|
78
|
-
const parsed = json == null ? null : observerRequestSchema.safeParse(json);
|
|
79
|
-
if (parsed == null || !parsed.success) {
|
|
80
|
-
ctx.status = 400;
|
|
81
|
-
ctx.body = { error: "Invalid request body", success: false };
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const result = await engine.executeObserver(parsed.data.observer, parsed.data.params);
|
|
85
|
-
ctx.status = 200;
|
|
86
|
-
ctx.body = { error: result.error, outcome: result.outcome, success: result.success };
|
|
87
|
-
}
|
|
88
|
-
async function handleTeardown({ body, ctx, engine }) {
|
|
89
|
-
const json = tryParseJson(body);
|
|
90
|
-
const parsed = json == null ? null : teardownRequestSchema.safeParse(json);
|
|
91
|
-
if (parsed == null || !parsed.success) {
|
|
92
|
-
ctx.status = 400;
|
|
93
|
-
ctx.body = { error: "Invalid request body" };
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const items = parsed.data.batch.map((b) => ({
|
|
97
|
-
data: b.data,
|
|
98
|
-
names: b.preconditions,
|
|
99
|
-
runId: b.runId
|
|
100
|
-
}));
|
|
101
|
-
const results = await engine.teardown(items);
|
|
102
|
-
ctx.status = 200;
|
|
103
|
-
ctx.body = { results: toTeardownResults(results) };
|
|
104
|
-
}
|
|
105
|
-
function lastPathSegment(path) {
|
|
106
|
-
const segments = path.split("/").filter((s) => s.length > 0);
|
|
107
|
-
const last = segments.at(-1);
|
|
108
|
-
if (last === "execute-preconditions" || last === "execute-observer" || last === "teardown-preconditions") {
|
|
109
|
-
return last;
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
async function readBody(ctx) {
|
|
114
|
-
return new Promise((resolve, reject) => {
|
|
115
|
-
const chunks = [];
|
|
116
|
-
ctx.req.on("data", (chunk) => chunks.push(chunk));
|
|
117
|
-
ctx.req.on("end", () => {
|
|
118
|
-
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
119
|
-
});
|
|
120
|
-
ctx.req.on("error", reject);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
function headerString(value) {
|
|
124
|
-
return value.length > 0 ? value : void 0;
|
|
125
|
-
}
|
|
126
|
-
function tryParseJson(body) {
|
|
127
|
-
try {
|
|
128
|
-
return JSON.parse(body);
|
|
129
|
-
} catch {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
export {
|
|
134
|
-
createKoaHandler
|
|
135
|
-
};
|
package/dist/locators.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
type AriaRole = "alert" | "alertdialog" | "button" | "checkbox" | "combobox" | "dialog" | "form" | "grid" | "heading" | "img" | "link" | "list" | "listbox" | "listitem" | "menu" | "menuitem" | "navigation" | "option" | "progressbar" | "radio" | "region" | "row" | "searchbox" | "separator" | "slider" | "spinbutton" | "status" | "switch" | "tab" | "tabpanel" | "textbox" | "toolbar" | "tooltip" | "tree" | "treeitem";
|
|
2
|
-
type LocatorSpec = RoleLocatorSpec | TestIdLocatorSpec;
|
|
3
|
-
interface RoleLocatorSpec {
|
|
4
|
-
readonly by: "role";
|
|
5
|
-
readonly name: string | undefined;
|
|
6
|
-
readonly role: AriaRole;
|
|
7
|
-
}
|
|
8
|
-
interface TestIdLocatorSpec {
|
|
9
|
-
readonly by: "testId";
|
|
10
|
-
readonly value: string;
|
|
11
|
-
}
|
|
12
|
-
declare const STRATEGY_BRAND: unique symbol;
|
|
13
|
-
declare const ROLE_BRAND: unique symbol;
|
|
14
|
-
declare const LOCATOR_INTERNAL: unique symbol;
|
|
15
|
-
interface Locator<TStrategy extends string> {
|
|
16
|
-
readonly [LOCATOR_INTERNAL]: LocatorSpec;
|
|
17
|
-
readonly [STRATEGY_BRAND]: TStrategy;
|
|
18
|
-
}
|
|
19
|
-
interface RoleLocator<TRole extends AriaRole> extends Locator<"role"> {
|
|
20
|
-
readonly [ROLE_BRAND]: TRole;
|
|
21
|
-
}
|
|
22
|
-
declare function readLocator(loc: Locator<string>): LocatorSpec;
|
|
23
|
-
type AnyLocator = Locator<"role" | "testId">;
|
|
24
|
-
type InputLocator = Locator<"testId"> | RoleLocator<"combobox" | "searchbox" | "spinbutton" | "textbox">;
|
|
25
|
-
type SelectLocator = Locator<"testId"> | RoleLocator<"combobox" | "listbox">;
|
|
26
|
-
type CheckLocator = Locator<"testId"> | RoleLocator<"checkbox" | "switch">;
|
|
27
|
-
/**
|
|
28
|
-
* Preferred locator: targets an element by its ARIA role and accessible name.
|
|
29
|
-
* Survives DOM churn and doubles as an accessibility check — if a role query
|
|
30
|
-
* can't find your element, real users likely can't either.
|
|
31
|
-
*/
|
|
32
|
-
declare function role<TRole extends AriaRole>(ariaRole: TRole, name?: string): RoleLocator<TRole>;
|
|
33
|
-
/**
|
|
34
|
-
* Escape hatch for elements without a semantic role (decorative wrappers,
|
|
35
|
-
* non-interactive panels). Prefer `role()` when the element has one; a
|
|
36
|
-
* test-id locator has no accessibility signal.
|
|
37
|
-
*/
|
|
38
|
-
declare function testId(id: string): Locator<"testId">;
|
|
39
|
-
|
|
40
|
-
export { type AnyLocator, type AriaRole, type CheckLocator, type InputLocator, type Locator, type LocatorSpec, type RoleLocator, type SelectLocator, readLocator, role, testId };
|