@stardeck-customer-apps/testing 0.13.0 → 0.14.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.
package/SKILL.md CHANGED
@@ -295,6 +295,32 @@ expect(app.edge.latestDisplay()?.action).toBe("show");
295
295
  - `allowNetwork` — permit non-Stardeck outbound fetches (off by default).
296
296
  - `app.reset()` — wipe + re-apply schema + re-seed + clear inbox/sessions.
297
297
  Call in `beforeEach`.
298
+ - `app.reset({ mode: "data" })` — available in testing SDK **0.14.0+**. Faster
299
+ opt-in for stable schemas: truncate ordinary tables in `public`, restart their
300
+ owned serial/identity sequences, re-run the data-only seed, and clear the same
301
+ simulator/user/session state as the default. It preserves tables and other
302
+ schema objects instead of rebuilding them. The default remains full schema
303
+ reset; `app.reset({ mode: "schema" })` explicitly selects that default.
304
+
305
+ ```ts
306
+ // Only after verifying this suite keeps its schema fixed and uses a data-only seed:
307
+ beforeEach(() => app.reset({ mode: "data" }));
308
+ ```
309
+
310
+ Keep `app.reset()` for tests that change schema or depend on INSERTs in the
311
+ schema script. Also keep full reset for independent sequences, materialized
312
+ views, partitioned/foreign tables, temporary tables, and custom triggers or
313
+ cross-schema dependencies. Data mode does not restore those states or detect
314
+ eligibility; inspect both the tests and seed before opting in. All required
315
+ baseline rows must come from the data-only seed callback, not schema SQL.
316
+ Data mode refuses foreign keys requiring a cross-schema cascade. Database and
317
+ seed errors reject the reset; fix them before running the next test.
318
+
319
+ Do not use `it.concurrent` or `test.concurrent` with a shared test app: user,
320
+ database, and simulator state are shared within the file. Keep file isolation
321
+ enabled and let Vitest parallelize files. This option does not change workers
322
+ or the platform's test-run deadline.
323
+
298
324
  - `app.asUser(partial?)` — sign in a test user; `getSession()` in app code
299
325
  resolves to it. `app.signOut()` clears.
300
326
  - `app.issueSession(partial?)` — mint access/refresh tokens for cookie-based
package/dist/index.d.mts CHANGED
@@ -520,8 +520,15 @@ interface TestApp {
520
520
  * control-plane verify endpoint resolves these tokens back to the user.
521
521
  */
522
522
  issueSession(user?: Partial<TestUser>): SessionTokens;
523
- /** Drop all tables, re-apply the schema, re-run the seed, clear inbox/user. */
524
- reset(): Promise<void>;
523
+ /**
524
+ * Rebuild the schema (default), re-run the seed, and clear simulator/user state.
525
+ * `mode: "data"` instead truncates ordinary public tables and restarts owned
526
+ * sequences. Use only with a stable schema and data-only seed; it does not
527
+ * restore DDL changes, schema-script data, or independent sequences.
528
+ */
529
+ reset(options?: {
530
+ mode: "schema" | "data";
531
+ }): Promise<void>;
525
532
  /** Tear down the app and restore global fetch. */
526
533
  close(): Promise<void>;
527
534
  }
package/dist/index.d.ts CHANGED
@@ -520,8 +520,15 @@ interface TestApp {
520
520
  * control-plane verify endpoint resolves these tokens back to the user.
521
521
  */
522
522
  issueSession(user?: Partial<TestUser>): SessionTokens;
523
- /** Drop all tables, re-apply the schema, re-run the seed, clear inbox/user. */
524
- reset(): Promise<void>;
523
+ /**
524
+ * Rebuild the schema (default), re-run the seed, and clear simulator/user state.
525
+ * `mode: "data"` instead truncates ordinary public tables and restarts owned
526
+ * sequences. Use only with a stable schema and data-only seed; it does not
527
+ * restore DDL changes, schema-script data, or independent sequences.
528
+ */
529
+ reset(options?: {
530
+ mode: "schema" | "data";
531
+ }): Promise<void>;
525
532
  /** Tear down the app and restore global fetch. */
526
533
  close(): Promise<void>;
527
534
  }
package/dist/index.js CHANGED
@@ -73,6 +73,19 @@ async function applySchema(db, schemaSql) {
73
73
  async function dropAllTables(db) {
74
74
  await db.exec(`DROP SCHEMA public CASCADE; CREATE SCHEMA public;`);
75
75
  }
76
+ async function listPublicTables(db) {
77
+ const { rows } = await db.query(`
78
+ SELECT format('%I.%I', n.nspname, c.relname) AS name
79
+ FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
80
+ WHERE n.nspname = 'public' AND c.relkind = 'r'
81
+ ORDER BY c.relname
82
+ `);
83
+ return rows.map(({ name }) => name);
84
+ }
85
+ async function truncateAllTables(db) {
86
+ const tables = await listPublicTables(db);
87
+ if (tables.length) await db.exec(`TRUNCATE TABLE ${tables.join(", ")} RESTART IDENTITY`);
88
+ }
76
89
  var identityParsers = null;
77
90
  function getIdentityParsers() {
78
91
  if (!identityParsers) {
@@ -2841,9 +2854,14 @@ async function createTestApp(options = {}) {
2841
2854
  state.refreshSessions.set(tokens.refreshToken, fullUser);
2842
2855
  return tokens;
2843
2856
  },
2844
- async reset() {
2845
- await dropAllTables(db);
2846
- await initialize();
2857
+ async reset(resetOptions) {
2858
+ if (resetOptions?.mode === "data") {
2859
+ await truncateAllTables(db);
2860
+ if (options.seed) await options.seed(db);
2861
+ } else {
2862
+ await dropAllTables(db);
2863
+ await initialize();
2864
+ }
2847
2865
  state.currentUser = null;
2848
2866
  state.sessions.clear();
2849
2867
  state.refreshSessions.clear();
package/dist/index.mjs CHANGED
@@ -24,6 +24,19 @@ async function applySchema(db, schemaSql) {
24
24
  async function dropAllTables(db) {
25
25
  await db.exec(`DROP SCHEMA public CASCADE; CREATE SCHEMA public;`);
26
26
  }
27
+ async function listPublicTables(db) {
28
+ const { rows } = await db.query(`
29
+ SELECT format('%I.%I', n.nspname, c.relname) AS name
30
+ FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
31
+ WHERE n.nspname = 'public' AND c.relkind = 'r'
32
+ ORDER BY c.relname
33
+ `);
34
+ return rows.map(({ name }) => name);
35
+ }
36
+ async function truncateAllTables(db) {
37
+ const tables = await listPublicTables(db);
38
+ if (tables.length) await db.exec(`TRUNCATE TABLE ${tables.join(", ")} RESTART IDENTITY`);
39
+ }
27
40
  var identityParsers = null;
28
41
  function getIdentityParsers() {
29
42
  if (!identityParsers) {
@@ -2792,9 +2805,14 @@ async function createTestApp(options = {}) {
2792
2805
  state.refreshSessions.set(tokens.refreshToken, fullUser);
2793
2806
  return tokens;
2794
2807
  },
2795
- async reset() {
2796
- await dropAllTables(db);
2797
- await initialize();
2808
+ async reset(resetOptions) {
2809
+ if (resetOptions?.mode === "data") {
2810
+ await truncateAllTables(db);
2811
+ if (options.seed) await options.seed(db);
2812
+ } else {
2813
+ await dropAllTables(db);
2814
+ await initialize();
2815
+ }
2798
2816
  state.currentUser = null;
2799
2817
  state.sessions.clear();
2800
2818
  state.refreshSessions.clear();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stardeck-customer-apps/testing",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Vitest test harness for Stardeck customer apps — in-process Postgres (PGlite) plus a control-plane simulator so the real Stardeck SDKs run unmodified in tests",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",