Ctrl K
ComunidadGuías…

test/scripts/database-snapshot.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { createClient } from "@libsql/client";
import { expect } from "@std/expect";
import { join, toFileUrl } from "@std/path";
import { describe, it as test } from "@std/testing/bdd";
import {
  createDatabaseSnapshot,
  type SnapshotClientFactory,
} from "#scripts/database-snapshot-lib.ts";
import { verifyTursoUploadFile } from "#scripts/turso-migration-file.ts";
import { directoryNames, withTempDir } from "#test-utils/files.ts";

describe("database snapshot", () => {
  test("publishes a complete SQLite database", () =>
    withTempDir(async (dir) => {
      const sourceDirectory = join(dir, "source");
      await Deno.mkdir(sourceDirectory);
      const sourcePath = join(sourceDirectory, "source.sqlite");
      const outputPath = join(dir, "snapshot.sqlite");
      const source = createClient({
        intMode: "bigint",
        url: toFileUrl(sourcePath).href,
      });
      await source.executeMultiple(`
        PRAGMA journal_mode = WAL;
        PRAGMA application_id = 1414090059;
        PRAGMA user_version = 37;
        CREATE TABLE outside_app (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          value INTEGER NOT NULL,
          payload BLOB NOT NULL
        );
        CREATE TABLE audit (outside_id INTEGER NOT NULL);
        CREATE INDEX outside_value_idx ON outside_app (value);
        CREATE VIEW outside_values AS SELECT id, value FROM outside_app;
        CREATE TRIGGER outside_audit AFTER INSERT ON outside_app
        BEGIN
          INSERT INTO audit (outside_id) VALUES (NEW.id);
        END;
      `);
      await source.execute({
        args: [9223372036854775806n, new Uint8Array([0, 127, 128, 255])],
        sql: "INSERT INTO outside_app (value, payload) VALUES (?, ?)",
      });
      await source.execute({
        args: [12n, new Uint8Array([1])],
        sql: "INSERT INTO outside_app (value, payload) VALUES (?, ?)",
      });
      await source.execute("DELETE FROM outside_app WHERE id = 2");
      await source.execute("PRAGMA wal_checkpoint(TRUNCATE)");
      source.close();

      const factory: SnapshotClientFactory = (config) => {
        if (!config.syncUrl) return createClient(config);
        return {
          close: () => {},
          execute: () =>
            Promise.reject(new Error("execute should not be called")),
          sync: async () => {
            await Deno.copyFile(sourcePath, new URL(config.url));
            return {};
          },
        };
      };

      await createDatabaseSnapshot(
        {
          dbToken: "token",
          dbUrl: "libsql://database.example.com",
          outputPath,
        },
        factory,
      );

      expect(await directoryNames(dir)).toEqual(["snapshot.sqlite", "source"]);
      await verifyTursoUploadFile(outputPath, createClient);

      const snapshot = createClient({
        intMode: "bigint",
        url: toFileUrl(outputPath).href,
      });
      try {
        const objects = await snapshot.execute(
          "SELECT type, name FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%' ORDER BY type, name",
        );
        expect(objects.rows).toEqual([
          { name: "outside_value_idx", type: "index" },
          { name: "audit", type: "table" },
          { name: "outside_app", type: "table" },
          { name: "outside_audit", type: "trigger" },
          { name: "outside_values", type: "view" },
        ]);
        const values = await snapshot.execute(
          "SELECT id, value, payload FROM outside_app",
        );
        const [stored] = values.rows;
        if (!stored) throw new Error("Snapshot row is missing");
        expect(stored.id).toBe(1n);
        expect(stored.value).toBe(9223372036854775806n);
        expect(stored.payload).toBeInstanceOf(ArrayBuffer);
        if (!(stored.payload instanceof ArrayBuffer)) {
          throw new Error("Snapshot BLOB is not binary data");
        }
        expect(Array.from(new Uint8Array(stored.payload))).toEqual([
          0, 127, 128, 255,
        ]);
        expect((await snapshot.execute("SELECT * FROM audit")).rows).toEqual([
          { outside_id: 1n },
          { outside_id: 2n },
        ]);
        expect(
          (await snapshot.execute("SELECT seq FROM sqlite_sequence")).rows,
        ).toEqual([{ seq: 2n }]);
        expect((await snapshot.execute("PRAGMA application_id")).rows).toEqual([
          { application_id: 1414090059n },
        ]);
        expect((await snapshot.execute("PRAGMA user_version")).rows).toEqual([
          { user_version: 37n },
        ]);
      } finally {
        snapshot.close();
      }
    }));
});