diff --git a/packages/docs/docs-dev/testing/integration.md b/packages/docs/docs-dev/testing/integration.md new file mode 100644 index 000000000..8c1ef46b7 --- /dev/null +++ b/packages/docs/docs-dev/testing/integration.md @@ -0,0 +1,21 @@ +# Integration tests + +Integration tests exercise multiple packages working together and often rely on +sample projects from the [`test-files`](../../../test-files) directory. They are +written with [Vitest](https://vitest.dev) and follow the `*.test.ts` naming +convention alongside the sources. + +Typical scenarios include: + +- Remote procedure calls via the runtime `Communicator`. +- Round‑tripping DAWproject data through import and export utilities using + fixtures like `all-devices.od` and `automation.dawproject`. + +Run all integration suites with: + +```bash +npm test +``` + +This command executes every package's test script via Turbo, ensuring that +features continue to work together across the monorepo. diff --git a/packages/docs/docs-dev/testing/test-files.md b/packages/docs/docs-dev/testing/test-files.md index 3aedb6925..62f47fc2e 100644 --- a/packages/docs/docs-dev/testing/test-files.md +++ b/packages/docs/docs-dev/testing/test-files.md @@ -5,10 +5,10 @@ cover common scenarios and are used across packages for development and regressi | File | Description | | --- | --- | -| `all-devices.od` | OpenDAW project exercising a wide range of built-in devices. | +| `all-devices.od` | OpenDAW project exercising a wide range of built-in devices; used by exporter integration tests. | | `eq.dawproject` | DAWproject fixture containing EQ settings. | | `note-regions.dawproject` | Demonstrates note regions across tracks. | -| `automation.dawproject` | Includes parameter automation curves. | +| `automation.dawproject` | Includes parameter automation curves for automation tests. | | `audio-regions.dawproject` | Contains audio regions with linked media. | | `bitwig.example.xml` | Minimal Bitwig project used for parser tests. | diff --git a/packages/docs/docs-user/examples/test-projects.md b/packages/docs/docs-user/examples/test-projects.md index 218753a57..249fa87f4 100644 --- a/packages/docs/docs-user/examples/test-projects.md +++ b/packages/docs/docs-user/examples/test-projects.md @@ -11,3 +11,4 @@ projects in the [`test-files`](../../../../test-files) directory: - **bitwig.example.xml** – a tiny Bitwig project useful for import experiments. These projects are read‑only fixtures; copy them before making changes. +Developers can reuse them in [integration tests](../../docs-dev/testing/integration.md). diff --git a/packages/lib/midi/src/index.test.ts b/packages/lib/midi/src/index.test.ts new file mode 100644 index 000000000..fadfd8879 --- /dev/null +++ b/packages/lib/midi/src/index.test.ts @@ -0,0 +1,16 @@ +/** + * Smoke tests for the MIDI entry module, ensuring exports and global registration. + */ +import { describe, expect, it } from "vitest"; +import * as Midi from "./index"; + +describe("lib-midi index", () => { + it("registers a global symbol", () => { + const key = Symbol.for("@openDAW/lib-midi"); + expect((globalThis as any)[key]).toBe(true); + }); + + it("exposes MidiFileDecoder", () => { + expect(Midi.MidiFileDecoder).toBeTypeOf("function"); + }); +}); diff --git a/packages/studio/core/src/dawproject/DawProjectExporter.test.ts b/packages/studio/core/src/dawproject/DawProjectExporter.test.ts index 3b3fd4ea0..296e65103 100644 --- a/packages/studio/core/src/dawproject/DawProjectExporter.test.ts +++ b/packages/studio/core/src/dawproject/DawProjectExporter.test.ts @@ -1,54 +1,76 @@ -import {describe, it} from "vitest" -import {fileURLToPath} from "url" -import * as path from "node:path" -import * as fs from "node:fs" -import {Project} from "../Project" -import {AudioData, SampleLoader, SampleLoaderState, SampleManager} from "@opendaw/studio-adapters" -import {Observer, Option, panic, Subscription, Terminable, UUID} from "@opendaw/lib-std" -import {Xml} from "@opendaw/lib-xml" -import {FileReferenceSchema} from "@opendaw/lib-dawproject" -import {DawProjectExporter} from "./DawProjectExporter" -import {Peaks} from "@opendaw/lib-fusion" - -/** Verifies that a project can be exported to DAWproject format. */ +/** + * Verifies that a complex OpenDAW project exports to DAWproject format. + */ +import { describe, it } from "vitest"; +import { fileURLToPath } from "url"; +import * as path from "node:path"; +import * as fs from "node:fs"; +import { Project } from "../Project"; +import { + AudioData, + SampleLoader, + SampleLoaderState, + SampleManager, +} from "@opendaw/studio-adapters"; +import { + Observer, + Option, + panic, + Subscription, + Terminable, + UUID, +} from "@opendaw/lib-std"; +import { Xml } from "@opendaw/lib-xml"; +import { FileReferenceSchema } from "@opendaw/lib-dawproject"; +import { DawProjectExporter } from "./DawProjectExporter"; +import { Peaks } from "@opendaw/lib-fusion"; describe("DawProjectExport", () => { - it("export", async () => { - const __dirname = path.dirname(fileURLToPath(import.meta.url)) - const projectPath = "../../../../../test-files/all-devices.od" - const buffer = fs.readFileSync(path.join(__dirname, projectPath)) - const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) - const project = Project.load({ - sampleRate: 44100, - sampleManager: new class implements SampleManager { - record(loader: SampleLoader & { uuid: UUID.Format }): void { - throw new Error("Method not implemented.") - } - getOrCreate(format: UUID.Format): SampleLoader { - return new class implements SampleLoader { - data: Option = Option.None - peaks: Option = Option.None - uuid: UUID.Format = format - state: SampleLoaderState = {type: "progress", progress: 0.0} - meta: Option = Option.None - invalidate(): void {throw new Error("Method not implemented.")} - subscribe(_observer: Observer): Subscription { - return Terminable.Empty - } - } - } - invalidate(_uuid: UUID.Format): void { - return panic("Method not implemented.") - } - } - }, arrayBuffer) - const schema = DawProjectExporter.write(project, { - write: (path: string, buffer: ArrayBufferLike): FileReferenceSchema => { - console.debug(`store ${buffer.byteLength} bytes at ${path}`) - return Xml.element({path, external: false}, FileReferenceSchema) - } - }) - // console.dir(schema, {depth: Number.MAX_SAFE_INTEGER}) - console.debug(Xml.pretty(Xml.toElement("Project", schema))) - }) -}) \ No newline at end of file + it("export", async () => { + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const projectPath = "../../../../../test-files/all-devices.od"; + const buffer = fs.readFileSync(path.join(__dirname, projectPath)); + const arrayBuffer = buffer.buffer.slice( + buffer.byteOffset, + buffer.byteOffset + buffer.byteLength, + ); + const project = Project.load( + { + sampleRate: 44100, + sampleManager: new (class implements SampleManager { + record(loader: SampleLoader & { uuid: UUID.Format }): void { + throw new Error("Method not implemented."); + } + getOrCreate(format: UUID.Format): SampleLoader { + return new (class implements SampleLoader { + data: Option = Option.None; + peaks: Option = Option.None; + uuid: UUID.Format = format; + state: SampleLoaderState = { type: "progress", progress: 0.0 }; + meta: Option = Option.None; + invalidate(): void { + throw new Error("Method not implemented."); + } + subscribe(_observer: Observer): Subscription { + return Terminable.Empty; + } + })(); + } + invalidate(_uuid: UUID.Format): void { + return panic("Method not implemented."); + } + })(), + }, + arrayBuffer, + ); + const schema = DawProjectExporter.write(project, { + write: (path: string, buffer: ArrayBufferLike): FileReferenceSchema => { + console.debug(`store ${buffer.byteLength} bytes at ${path}`); + return Xml.element({ path, external: false }, FileReferenceSchema); + }, + }); + // console.dir(schema, {depth: Number.MAX_SAFE_INTEGER}) + console.debug(Xml.pretty(Xml.toElement("Project", schema))); + void schema; + }); +}); diff --git a/packages/studio/core/src/dawproject/DawProjectImport.test.ts b/packages/studio/core/src/dawproject/DawProjectImport.test.ts index 858889d95..f6ab69069 100644 --- a/packages/studio/core/src/dawproject/DawProjectImport.test.ts +++ b/packages/studio/core/src/dawproject/DawProjectImport.test.ts @@ -1,18 +1,20 @@ -import {describe, it} from "vitest" -import {fileURLToPath} from "url" -import * as path from "node:path" -import * as fs from "node:fs" -import {DawProject} from "./DawProject" -import {DawProjectImport} from "./DawProjectImport" - -/** Basic sanity checks for the DAWproject importer. */ +/** + * Basic sanity checks for the DAWproject importer using a sample EQ project. + */ +import { describe, it } from "vitest"; +import { fileURLToPath } from "url"; +import * as path from "node:path"; +import * as fs from "node:fs"; +import { DawProject } from "./DawProject"; +import { DawProjectImport } from "./DawProjectImport"; describe("DawProjectImport", () => { - it("import", async () => { - const __dirname = path.dirname(fileURLToPath(import.meta.url)) - const testFile = "../../../../../test-files/eq.dawproject" - const buffer = fs.readFileSync(path.join(__dirname, testFile)) - const {project, resources} = await DawProject.decode(buffer) - const {skeleton} = await DawProjectImport.read(project, resources) - }) -}) \ No newline at end of file + it("import", async () => { + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const testFile = "../../../../../test-files/eq.dawproject"; + const buffer = fs.readFileSync(path.join(__dirname, testFile)); + const { project, resources } = await DawProject.decode(buffer); + const { skeleton } = await DawProjectImport.read(project, resources); + void skeleton; + }); +});