Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/hash-backend-integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"fix:eslint": "eslint --fix .",
"lint:eslint": "eslint --report-unused-disable-directives .",
"lint:tsc": "tsc --noEmit",
"test:integration": "vitest --run"
"test:integration": "vitest --run && vitest --run --config vitest.snapshot.config.ts"
},
"dependencies": {
"@apps/hash-api": "workspace:*",
Expand Down
20 changes: 20 additions & 0 deletions tests/hash-backend-integration/src/tests/admin-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ import { StatusCode } from "@local/status";

import type { GraphStatus } from "@rust/hash-graph-type-defs/typescript/status";

/**
* Throw unless running in the snapshot group (`vitest.snapshot.config.ts`),
* the only group allowed to wipe the shared system graph.
*/
const assertRunningInSnapshotGroup = (operation: string) => {
if (process.env.HASH_TEST_GROUP !== "snapshot") {
throw new Error(
`\`${operation}\` wipes the graph seeded by \`globalSetup\`, so it may only run in the snapshot group (\`vitest.snapshot.config.ts\`). To make a test file destructive, place it under \`src/tests/subgraph/\`.`,
);
}
};

// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const port = process.env.HASH_GRAPH_ADMIN_PORT || "4001";

Expand Down Expand Up @@ -96,8 +108,12 @@ export const deleteEntities = async () => {

/**
* Restore a snapshot from a file.
*
* Destructive – may only run in the snapshot group.
*/
export const restoreSnapshot = async (snapshotPath: string) => {
assertRunningInSnapshotGroup("restoreSnapshot");

await fetch(`http://127.0.0.1:${port}/snapshot`, {
method: "POST",
body: createReadStream(snapshotPath),
Expand Down Expand Up @@ -137,8 +153,12 @@ export const deleteUser = async (
* Reset the Graph.
*
* This is a convenience function for deleting all entities, entity types, property types, data types, and accounts.
*
* Destructive – may only run in the snapshot group.
*/
export const resetGraph = async () => {
assertRunningInSnapshotGroup("resetGraph");

await deleteEntities();
await deleteEntityTypes();
await deletePropertyTypes();
Expand Down
7 changes: 6 additions & 1 deletion tests/hash-backend-integration/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"extends": "@local/tsconfig/legacy-base-tsconfig-to-refactor.json",
"include": ["./src/", "codegen.config.ts", "vitest.config.ts"]
"include": [
"./src/",
"codegen.config.ts",
"vitest.config.ts",
"vitest.snapshot.config.ts"
]
}
81 changes: 32 additions & 49 deletions tests/hash-backend-integration/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,48 @@
/// <reference types="vitest" />
import { defineConfig } from "vitest/config";
import { BaseSequencer } from "vitest/node";

import type { TestSpecification } from "vitest/node";
import type { TestUserConfig } from "vitest/config";

/**
* The subgraph tests reset the graph and restore standalone snapshots,
* destroying the shared system graph seeded once per run by `globalSetup`.
* Sort them after all other test files so that they cannot break tests which
* rely on the shared seed – the next run's `globalSetup` re-seeds the graph
* from scratch.
* Test options shared between the seeded group (this config) and the snapshot
* group (`vitest.snapshot.config.ts`), which `test:integration` runs as
* separate, sequential vitest invocations.
*/
class DestructiveTestsLastSequencer extends BaseSequencer {
override async sort(files: TestSpecification[]) {
const isDestructive = (file: TestSpecification) =>
file.moduleId.includes("/src/tests/subgraph/");

const sorted = await super.sort(files);

return [
...sorted.filter((file) => !isDestructive(file)),
...sorted.filter(isDestructive),
];
}
}
export const sharedTestConfig = {
coverage: {
enabled: process.env.TEST_COVERAGE === "true",
provider: "istanbul",
reporter: ["lcov", "text"],
include: ["**/*.{c,m,}{j,t}s{x,}"],
exclude: ["**/node_modules/**", "**/dist/**"],
},
setupFiles: [
"@local/hash-backend-utils/environment",
"./src/tests/setup-opentelemetry.ts",
],
environment: "node",
testTimeout: 60_000,
hookTimeout: 120_000,
sequence: {
hooks: "list",
},
/**
* These integration tests share a single graph instance, so running files
* in parallel causes graph state races.
*/
fileParallelism: false,
maxWorkers: 1,
maxConcurrency: 1,
} satisfies TestUserConfig;

export default defineConfig({
plugins: [],
build: {
target: "esnext",
},
test: {
coverage: {
enabled: process.env.TEST_COVERAGE === "true",
provider: "istanbul",
reporter: ["lcov", "text"],
include: ["**/*.{c,m,}{j,t}s{x,}"],
exclude: ["**/node_modules/**", "**/dist/**"],
},
...sharedTestConfig,
globalSetup: ["./src/tests/global-setup.ts"],
setupFiles: [
"@local/hash-backend-utils/environment",
"./src/tests/setup-opentelemetry.ts",
],
include: [
"src/tests/graph/**/*.test.ts",
"src/tests/subgraph/**/*.test.ts",
],
environment: "node",
testTimeout: 60_000,
hookTimeout: 120_000,
sequence: {
hooks: "list",
sequencer: DestructiveTestsLastSequencer,
},
/**
* These integration tests share a single graph instance, so running files
* in parallel causes graph state races.
*/
fileParallelism: false,
maxWorkers: 1,
maxConcurrency: 1,
include: ["src/tests/graph/**/*.test.ts"],
},
});
31 changes: 31 additions & 0 deletions tests/hash-backend-integration/vitest.snapshot.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// <reference types="vitest" />
import { defineConfig } from "vitest/config";

import { sharedTestConfig } from "./vitest.config";

/**
* Snapshot group: test files under `src/tests/subgraph/` wipe the graph and
* restore standalone snapshots, so `test:integration` runs this config as a
* separate vitest invocation after the seeded group (`vitest.config.ts`).
* The `HASH_TEST_GROUP` marker lets `admin-server.ts` refuse destructive
* operations outside this group.
*/
export default defineConfig({
plugins: [],
build: {
target: "esnext",
},
test: {
...sharedTestConfig,
coverage: {
...sharedTestConfig.coverage,
// Sharing `./coverage` would discard the seeded group's report –
// vitest cleans the reports directory at the start of a run.
reportsDirectory: "./coverage-snapshot",
},
include: ["src/tests/subgraph/**/*.test.ts"],
env: {
HASH_TEST_GROUP: "snapshot",
},
},
});
Loading