@ishibashi0112/webview2-bridge-test 0.5.0

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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/bridge.d.ts +34 -0
  4. package/dist/bridge.d.ts.map +1 -0
  5. package/dist/bridge.js +72 -0
  6. package/dist/bridge.js.map +1 -0
  7. package/dist/cli.d.ts +4 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +166 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/clipboard.d.ts +2 -0
  12. package/dist/clipboard.d.ts.map +1 -0
  13. package/dist/clipboard.js +39 -0
  14. package/dist/clipboard.js.map +1 -0
  15. package/dist/config.d.ts +106 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +65 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/db/diff.d.ts +29 -0
  20. package/dist/db/diff.d.ts.map +1 -0
  21. package/dist/db/diff.js +76 -0
  22. package/dist/db/diff.js.map +1 -0
  23. package/dist/db/env.d.ts +19 -0
  24. package/dist/db/env.d.ts.map +1 -0
  25. package/dist/db/env.js +119 -0
  26. package/dist/db/env.js.map +1 -0
  27. package/dist/db/guard.d.ts +28 -0
  28. package/dist/db/guard.d.ts.map +1 -0
  29. package/dist/db/guard.js +68 -0
  30. package/dist/db/guard.js.map +1 -0
  31. package/dist/db/index.d.ts +72 -0
  32. package/dist/db/index.d.ts.map +1 -0
  33. package/dist/db/index.js +120 -0
  34. package/dist/db/index.js.map +1 -0
  35. package/dist/fixtures.d.ts +25 -0
  36. package/dist/fixtures.d.ts.map +1 -0
  37. package/dist/fixtures.js +167 -0
  38. package/dist/fixtures.js.map +1 -0
  39. package/dist/host.d.ts +41 -0
  40. package/dist/host.d.ts.map +1 -0
  41. package/dist/host.js +154 -0
  42. package/dist/host.js.map +1 -0
  43. package/dist/index.d.ts +9 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +9 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/reporter.d.ts +42 -0
  48. package/dist/reporter.d.ts.map +1 -0
  49. package/dist/reporter.js +221 -0
  50. package/dist/reporter.js.map +1 -0
  51. package/package.json +82 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Playwright のフィクスチャ。テストは `import { test, expect } from "@ishibashi0112/webview2-bridge-test"` で使う。
3
+ *
4
+ * test("...", async ({ page, db, testId, bridge }) => { ... })
5
+ *
6
+ * - page: screen は Playwright が起動したブラウザ、api / host は CDP で繋いだ WebView2 のページ
7
+ * - bridge: (api / host) ページ内のブリッジクライアントを契約メソッド名で呼ぶ
8
+ * - db: (DB 設定があるとき) Knex を包むヘルパ。テスト終了時に入れた行を自動で消す
9
+ * - testId: テストごとの実行 ID(E2E-yyyymmdd-hhmm-xxxx)。前提データのキーの接頭辞に使う
10
+ */
11
+ import path from "node:path";
12
+ import { test as base, expect } from "@playwright/test";
13
+ import { createBridge, DEFAULT_BRIDGE_GLOBAL } from "./bridge.js";
14
+ import { createDb } from "./db/index.js";
15
+ import { checkAllowed, describeConnection } from "./db/guard.js";
16
+ import { knexConfigFromEnv, loadEnvFiles } from "./db/env.js";
17
+ import { launchHost } from "./host.js";
18
+ export function makeTestId(now = new Date(), random = Math.random().toString(36).slice(2, 6)) {
19
+ const p = (n) => String(n).padStart(2, "0");
20
+ return `E2E-${now.getFullYear()}${p(now.getMonth() + 1)}${p(now.getDate())}-${p(now.getHours())}${p(now.getMinutes())}-${random}`;
21
+ }
22
+ /** TrackSpec の where を snapshot 用に解決する("{testId}" の置換 / 関数への testId 注入) */
23
+ export function resolveTrackWhere(where, testId) {
24
+ if (where === undefined)
25
+ return undefined;
26
+ if (typeof where === "function")
27
+ return (qb) => where(qb, testId);
28
+ const out = {};
29
+ for (const [k, v] of Object.entries(where))
30
+ out[k] = typeof v === "string" ? v.replaceAll("{testId}", testId) : v;
31
+ return out;
32
+ }
33
+ function toSnapshotSpecs(track, testId) {
34
+ return track.map((t) => ({ table: t.table, key: t.key, where: resolveTrackWhere(t.where, testId) }));
35
+ }
36
+ function jsonReplacer(_key, value) {
37
+ if (typeof value === "bigint")
38
+ return value.toString();
39
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value))
40
+ return `base64:${value.toString("base64")}`;
41
+ return value;
42
+ }
43
+ function requireConfig(e2e) {
44
+ if (e2e === undefined) {
45
+ throw new Error("use.e2e が設定されていません。playwright.config.ts で playwrightConfig(e2e) を使ってください");
46
+ }
47
+ return e2e;
48
+ }
49
+ export const test = base.extend({
50
+ e2e: [undefined, { option: true, scope: "worker" }],
51
+ layer: ["screen", { option: true, scope: "worker" }],
52
+ appRoot: [
53
+ async ({}, use, workerInfo) => {
54
+ const configFile = workerInfo.config.configFile;
55
+ await use(configFile !== undefined ? path.dirname(configFile) : workerInfo.config.rootDir);
56
+ },
57
+ { scope: "worker" },
58
+ ],
59
+ hostApp: [
60
+ async ({ e2e, layer, appRoot, playwright }, use) => {
61
+ if (layer === "screen") {
62
+ await use(null);
63
+ return;
64
+ }
65
+ const cfg = requireConfig(e2e);
66
+ const host = cfg.host;
67
+ if (host === undefined) {
68
+ throw new Error("e2e.config.ts に host(exe のパス)がありません。api / host プロジェクトには必須です");
69
+ }
70
+ const app = await launchHost({
71
+ exe: path.resolve(appRoot, host.exe),
72
+ devUrl: host.devUrl ?? cfg.web.url,
73
+ cdpPort: host.cdpPort,
74
+ startupTimeoutMs: host.startupTimeoutMs,
75
+ env: host.env,
76
+ chromium: playwright.chromium,
77
+ });
78
+ await use(app);
79
+ await app.close();
80
+ },
81
+ { scope: "worker", timeout: 90_000 },
82
+ ],
83
+ dbConnection: [
84
+ async ({ e2e, appRoot }, use) => {
85
+ const cfg = requireConfig(e2e);
86
+ loadEnvFiles(appRoot, cfg.db?.envFiles);
87
+ const knexConfig = knexConfigFromEnv();
88
+ if (knexConfig === undefined) {
89
+ await use(null);
90
+ return;
91
+ }
92
+ const guard = checkAllowed(describeConnection(knexConfig.client, knexConfig.connection), cfg.db?.allowedDatabases ?? []);
93
+ if (!guard.ok)
94
+ throw new Error(`DB ガード: ${guard.reason}`);
95
+ const knexModule = (await import("knex"));
96
+ const knex = knexModule.default(knexConfig);
97
+ await use(knex);
98
+ await knex.destroy();
99
+ },
100
+ { scope: "worker" },
101
+ ],
102
+ testId: async ({}, use) => {
103
+ await use(makeTestId());
104
+ },
105
+ // screen: Playwright の通常のページ。api / host: WebView2 のページ(テストごとに reload)
106
+ page: async ({ layer, hostApp, context, e2e }, use, testInfo) => {
107
+ if (layer === "screen" || hostApp === null) {
108
+ const p = await context.newPage();
109
+ await use(p);
110
+ return;
111
+ }
112
+ const p = hostApp.page;
113
+ if (e2e?.host?.reloadPerTest !== false) {
114
+ await p.reload({ waitUntil: "domcontentloaded" });
115
+ }
116
+ await use(p);
117
+ if (testInfo.status !== testInfo.expectedStatus) {
118
+ try {
119
+ const body = await p.screenshot({ fullPage: true });
120
+ await testInfo.attach("screenshot", { body, contentType: "image/png" });
121
+ }
122
+ catch {
123
+ // ページが閉じているなど。スクリーンショットは補助情報なので黙って続ける
124
+ }
125
+ }
126
+ },
127
+ bridge: async ({ page, layer, e2e }, use) => {
128
+ if (layer === "screen") {
129
+ throw new Error("bridge フィクスチャは api / host プロジェクトでだけ使えます(screen はモック応答なので契約を直接呼ぶ意味がありません)");
130
+ }
131
+ await use(createBridge(page, e2e?.bridgeGlobal ?? DEFAULT_BRIDGE_GLOBAL));
132
+ },
133
+ db: async ({ dbConnection, e2e, testId }, use, testInfo) => {
134
+ if (dbConnection === null) {
135
+ throw new Error("DB が設定されていません(.env.e2e.local に E2E_DB_CLIENT などを書き、e2e.config.ts の db.allowedDatabases にテスト DB 名を入れる)。DB を使わないテストは db を受け取らないでください");
136
+ }
137
+ const cfg = requireConfig(e2e);
138
+ const warnings = [];
139
+ const db = createDb(dbConnection, {
140
+ maxRows: cfg.db?.maxRows,
141
+ onWarning: (m) => warnings.push(m),
142
+ onDiff: async (diff) => {
143
+ await testInfo.attach("db-diff", { body: JSON.stringify(diff, jsonReplacer, 2), contentType: "application/json" });
144
+ },
145
+ });
146
+ const track = cfg.db?.track ?? [];
147
+ const before = track.length > 0 ? await db.snapshot(toSnapshotSpecs(track, testId)) : null;
148
+ await use(db);
149
+ if (before !== null) {
150
+ try {
151
+ await db.diff(before);
152
+ }
153
+ catch (e) {
154
+ warnings.push(`後片付け前の差分取得に失敗: ${e instanceof Error ? e.message : String(e)}`);
155
+ }
156
+ }
157
+ const result = await db.cleanup();
158
+ if (result.failures.length > 0 || warnings.length > 0) {
159
+ await testInfo.attach("db-cleanup", {
160
+ body: JSON.stringify({ deleted: result.deleted, failures: result.failures, warnings }, jsonReplacer, 2),
161
+ contentType: "application/json",
162
+ });
163
+ }
164
+ },
165
+ });
166
+ export { expect };
167
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../src/fixtures.ts"],"names":[],"mappings":"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"}
package/dist/host.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * WinForms ホスト exe を CDP(Chrome DevTools Protocol)有効で起動し、Playwright から WebView2 に接続する。
3
+ * VB 側は無改修: WebView2 は環境変数 WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS を読む。
4
+ */
5
+ import { type ChildProcess } from "node:child_process";
6
+ import type { Browser, BrowserContext, Page } from "@playwright/test";
7
+ export interface LaunchHostOptions {
8
+ /** ホスト exe の絶対パス */
9
+ exe: string;
10
+ /** exe に WEBVIEW2_BRIDGE_DEV_URL として渡す URL(dev サーバー)。省略すると exe 隣の wwwroot を読む */
11
+ devUrl?: string | undefined;
12
+ cdpPort?: number | undefined;
13
+ startupTimeoutMs?: number | undefined;
14
+ env?: Record<string, string> | undefined;
15
+ /** 接続に使う playwright の chromium(BrowserType) */
16
+ chromium: {
17
+ connectOverCDP(endpointURL: string, options?: {
18
+ timeout?: number;
19
+ }): Promise<Browser>;
20
+ };
21
+ /** ログ出力(既定: なし) */
22
+ log?: ((message: string) => void) | undefined;
23
+ }
24
+ export interface HostApp {
25
+ process: ChildProcess;
26
+ cdpUrl: string;
27
+ userDataDir: string;
28
+ browser: Browser;
29
+ context: BrowserContext;
30
+ page: Page;
31
+ close(): Promise<void>;
32
+ }
33
+ export declare class HostLaunchError extends Error {
34
+ name: string;
35
+ }
36
+ /** CDP の /json/version に応答があるか */
37
+ export declare function probeCdp(cdpUrl: string, timeoutMs?: number): Promise<boolean>;
38
+ export declare function launchHost(options: LaunchHostOptions): Promise<HostApp>;
39
+ /** exe とその子プロセス(msedgewebview2)を終了する */
40
+ export declare function killTree(child: ChildProcess): Promise<void>;
41
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIxE,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACzC,+CAA+C;IAC/C,QAAQ,EAAE;QAAE,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IACpG,mBAAmB;IACnB,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IAC/B,IAAI,SAAqB;CACnC;AAID,kCAAkC;AAClC,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAOjF;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CA8F7E;AAWD,wCAAwC;AACxC,wBAAsB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjE"}
package/dist/host.js ADDED
@@ -0,0 +1,154 @@
1
+ /**
2
+ * WinForms ホスト exe を CDP(Chrome DevTools Protocol)有効で起動し、Playwright から WebView2 に接続する。
3
+ * VB 側は無改修: WebView2 は環境変数 WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS を読む。
4
+ */
5
+ import { execFile, spawn } from "node:child_process";
6
+ import { existsSync, mkdtempSync, rmSync } from "node:fs";
7
+ import { tmpdir } from "node:os";
8
+ import path from "node:path";
9
+ export class HostLaunchError extends Error {
10
+ name = "HostLaunchError";
11
+ }
12
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
13
+ /** CDP の /json/version に応答があるか */
14
+ export async function probeCdp(cdpUrl, timeoutMs = 1000) {
15
+ try {
16
+ const res = await fetch(`${cdpUrl}/json/version`, { signal: AbortSignal.timeout(timeoutMs) });
17
+ return res.ok;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ export async function launchHost(options) {
24
+ const exe = options.exe;
25
+ const port = options.cdpPort ?? 9222;
26
+ const cdpUrl = `http://127.0.0.1:${port}`;
27
+ const timeoutMs = options.startupTimeoutMs ?? 30_000;
28
+ const log = options.log ?? (() => { });
29
+ if (!existsSync(exe)) {
30
+ throw new HostLaunchError(`ホスト exe が見つかりません: ${exe}\n 先に dotnet build(Debug)を実行してください`);
31
+ }
32
+ if (await probeCdp(cdpUrl)) {
33
+ throw new HostLaunchError(`ポート ${port} で既に何かが CDP を待ち受けています(前回の exe が残っていませんか)。終了するか e2e.config.ts の host.cdpPort を変えてください`);
34
+ }
35
+ const userDataDir = mkdtempSync(path.join(tmpdir(), "wv2b-e2e-"));
36
+ const env = {
37
+ ...process.env,
38
+ WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS: `--remote-debugging-port=${port}`,
39
+ WEBVIEW2_USER_DATA_FOLDER: userDataDir,
40
+ ...(options.devUrl !== undefined && { WEBVIEW2_BRIDGE_DEV_URL: options.devUrl }),
41
+ ...options.env,
42
+ };
43
+ log(`launch ${exe} (cdp ${port})`);
44
+ const child = spawn(exe, [], { env, stdio: "ignore", cwd: path.dirname(exe), windowsHide: false });
45
+ let exited;
46
+ child.on("exit", (code, signal) => {
47
+ exited = { code, signal };
48
+ });
49
+ const spawnError = new Promise((_, reject) => child.on("error", (e) => reject(new HostLaunchError(`exe を起動できません: ${e.message}`))));
50
+ const cleanupOnFailure = async () => {
51
+ await killTree(child);
52
+ rmSync(userDataDir, { recursive: true, force: true });
53
+ };
54
+ // CDP が開くまで待つ
55
+ const deadline = Date.now() + timeoutMs;
56
+ try {
57
+ while (!(await probeCdp(cdpUrl))) {
58
+ if (exited !== undefined) {
59
+ throw new HostLaunchError(`exe が起動直後に終了しました(code=${exited.code ?? "?"} signal=${exited.signal ?? "-"})。exe を手で起動してエラーを確認してください`);
60
+ }
61
+ if (Date.now() > deadline) {
62
+ throw new HostLaunchError(`${timeoutMs}ms 待っても CDP(${cdpUrl})が開きません。exe が WebView2 を初期化できているか(WebView2 Runtime の有無)を確認してください`);
63
+ }
64
+ await Promise.race([sleep(250), spawnError]);
65
+ }
66
+ log("cdp ready");
67
+ const browser = await options.chromium.connectOverCDP(cdpUrl, { timeout: Math.max(5_000, deadline - Date.now()) });
68
+ const context = browser.contexts()[0];
69
+ if (context === undefined) {
70
+ await browser.close();
71
+ throw new HostLaunchError("WebView2 に接続できましたが BrowserContext がありません");
72
+ }
73
+ let page = pickPage(context.pages(), options.devUrl);
74
+ while (page === undefined) {
75
+ if (Date.now() > deadline) {
76
+ await browser.close();
77
+ throw new HostLaunchError("WebView2 に接続できましたがページが開きません(MainForm が WebView2 を初期化しているか確認してください)");
78
+ }
79
+ await sleep(250);
80
+ page = pickPage(context.pages(), options.devUrl);
81
+ }
82
+ await page.waitForLoadState("domcontentloaded", { timeout: Math.max(5_000, deadline - Date.now()) });
83
+ log(`page ${page.url()}`);
84
+ const app = {
85
+ process: child,
86
+ cdpUrl,
87
+ userDataDir,
88
+ browser,
89
+ context,
90
+ page,
91
+ async close() {
92
+ try {
93
+ await browser.close();
94
+ }
95
+ catch {
96
+ // 既に切れている
97
+ }
98
+ await killTree(child);
99
+ for (let i = 0; i < 5; i++) {
100
+ try {
101
+ rmSync(userDataDir, { recursive: true, force: true });
102
+ break;
103
+ }
104
+ catch {
105
+ await sleep(300);
106
+ }
107
+ }
108
+ },
109
+ };
110
+ return app;
111
+ }
112
+ catch (e) {
113
+ await cleanupOnFailure();
114
+ throw e;
115
+ }
116
+ }
117
+ function pickPage(pages, devUrl) {
118
+ if (pages.length === 0)
119
+ return undefined;
120
+ if (devUrl !== undefined) {
121
+ const hit = pages.find((p) => p.url().startsWith(devUrl));
122
+ if (hit !== undefined)
123
+ return hit;
124
+ }
125
+ return pages.find((p) => p.url() !== "about:blank") ?? pages[0];
126
+ }
127
+ /** exe とその子プロセス(msedgewebview2)を終了する */
128
+ export async function killTree(child) {
129
+ if (child.exitCode !== null || child.signalCode !== null || child.pid === undefined)
130
+ return;
131
+ const pid = child.pid;
132
+ const exited = new Promise((resolve) => child.once("exit", () => resolve()));
133
+ if (process.platform === "win32") {
134
+ await new Promise((resolve) => execFile("taskkill", ["/PID", String(pid), "/T", "/F"], () => resolve()));
135
+ }
136
+ else {
137
+ try {
138
+ child.kill("SIGTERM");
139
+ }
140
+ catch {
141
+ return;
142
+ }
143
+ }
144
+ await Promise.race([exited, sleep(5_000)]);
145
+ if (child.exitCode === null && child.signalCode === null) {
146
+ try {
147
+ child.kill("SIGKILL");
148
+ }
149
+ catch {
150
+ // ignore
151
+ }
152
+ }
153
+ }
154
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { test, expect, makeTestId, resolveTrackWhere, type E2ETestFixtures, type E2EWorkerFixtures } from "./fixtures.js";
2
+ export { defineE2EConfig, playwrightConfig, browserUse, LAYERS, type DbConfig, type E2EConfig, type E2EPlaywrightConfig, type E2EWorkerOptions, type HostConfig, type Layer, type ReportConfig, type TrackSpec, type TrackWhere, type WebConfig, } from "./config.js";
3
+ export { BridgeCallError, createBridge, DEFAULT_BRIDGE_GLOBAL, type Bridge, type BridgeErrorShape } from "./bridge.js";
4
+ export { launchHost, killTree, probeCdp, HostLaunchError, type HostApp, type LaunchHostOptions } from "./host.js";
5
+ export { createDb, diffRows, summarizeDiff, normalizeRawResult, type CleanupEntry, type CleanupFailure, type CleanupResult, type Db, type DbDiff, type DbOptions, type DbSnapshot, type Row, type SnapshotSpec, type TableDiff, type TableSnapshot, } from "./db/index.js";
6
+ export { checkAllowed, describeConnection, isDbClient, oracleServiceName, type ConnectionDescription, type DbClient, type GuardResult } from "./db/guard.js";
7
+ export { knexConfigFromEnv, loadEnvFiles, DbEnvError, DEFAULT_ENV_FILES, type KnexLikeConfig } from "./db/env.js";
8
+ export { buildReport, type ReportInput, type ReportTestEntry } from "./reporter.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC1H,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,MAAM,EACN,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,qBAAqB,EAAE,KAAK,MAAM,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAClH,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,EAAE,EACP,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,GAAG,EACR,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC7J,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAClH,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { test, expect, makeTestId, resolveTrackWhere } from "./fixtures.js";
2
+ export { defineE2EConfig, playwrightConfig, browserUse, LAYERS, } from "./config.js";
3
+ export { BridgeCallError, createBridge, DEFAULT_BRIDGE_GLOBAL } from "./bridge.js";
4
+ export { launchHost, killTree, probeCdp, HostLaunchError } from "./host.js";
5
+ export { createDb, diffRows, summarizeDiff, normalizeRawResult, } from "./db/index.js";
6
+ export { checkAllowed, describeConnection, isDbClient, oracleServiceName } from "./db/guard.js";
7
+ export { knexConfigFromEnv, loadEnvFiles, DbEnvError, DEFAULT_ENV_FILES } from "./db/env.js";
8
+ export { buildReport } from "./reporter.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAgD,MAAM,eAAe,CAAC;AAC1H,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,MAAM,GAWP,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,qBAAqB,EAAsC,MAAM,aAAa,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAwC,MAAM,WAAW,CAAC;AAClH,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,kBAAkB,GAYnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,iBAAiB,EAA+D,MAAM,eAAe,CAAC;AAC7J,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAuB,MAAM,aAAa,CAAC;AAClH,OAAO,EAAE,WAAW,EAA0C,MAAM,eAAe,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from "@playwright/test/reporter";
2
+ import type { ReportConfig } from "./config.js";
3
+ export interface ReportAttachment {
4
+ name: string;
5
+ contentType: string;
6
+ path?: string | undefined;
7
+ text?: string | undefined;
8
+ }
9
+ export interface ReportTestEntry {
10
+ project: string;
11
+ title: string;
12
+ file: string;
13
+ line: number;
14
+ status: TestResult["status"];
15
+ expectedStatus: TestCase["expectedStatus"];
16
+ durationMs: number;
17
+ errors: string[];
18
+ attachments: ReportAttachment[];
19
+ }
20
+ export interface ReportInput {
21
+ startedAt: Date;
22
+ finishedAt: Date;
23
+ status: FullResult["status"];
24
+ tests: ReportTestEntry[];
25
+ /** 出力ディレクトリの基準(添付のパスを相対にする) */
26
+ rootDir: string;
27
+ }
28
+ export declare function stripAnsi(text: string): string;
29
+ /** Markdown を組み立てる純粋関数(テスト可能) */
30
+ export declare function buildReport(input: ReportInput, maxChars?: number): string;
31
+ export default class MarkdownReporter implements Reporter {
32
+ private readonly options;
33
+ private rootDir;
34
+ private startedAt;
35
+ private readonly entries;
36
+ constructor(options?: ReportConfig);
37
+ printsToStdio(): boolean;
38
+ onBegin(config: FullConfig, _suite: Suite): void;
39
+ onTestEnd(test: TestCase, result: TestResult): void;
40
+ onEnd(result: FullResult): Promise<void>;
41
+ }
42
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE/G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7B,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AASD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAkCD,iCAAiC;AACjC,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,GAAE,MAA0B,GAAG,MAAM,CA6F5F;AAiBD,MAAM,CAAC,OAAO,OAAO,gBAAiB,YAAW,QAAQ;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,OAAO,GAAE,YAAiB;IAItC,aAAa,IAAI,OAAO;IAIxB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI;IAMhD,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAuB7C,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAqB/C"}