Files
fusion/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphData.test.ts
Fusion 3f09037cfe feat(FN-3085): harden graph task filtering with in-review and orphan edge s
Merges graph task filtering hardening (FN-3085) — adding in-review node treatment and orphan dependency edge handling with comprehensive tests and documentation — alongside drag interaction wiring (FN-3625) that enables TaskCard drag override and graph drag opt-out.

Fusion-Task-Id: FN-3085
2026-05-07 03:42:51 -07:00

87 lines
3.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { renderHook } from "@testing-library/react";
import type { Task } from "@fusion/core";
import { useGraphData } from "../useGraphData";
function createTask(id: string, column: Task["column"] = "todo", dependencies: string[] = []): Task {
return {
id,
description: id,
column,
dependencies,
steps: [],
currentStep: 0,
log: [],
} as Task;
}
describe("useGraphData", () => {
it("returns empty graph for empty tasks", () => {
const { result } = renderHook(() => useGraphData([]));
expect(result.current).toEqual({ nodes: [], edges: [] });
});
it("creates node for single task with no deps", () => {
const { result } = renderHook(() => useGraphData([createTask("A")]));
expect(result.current.nodes.map((node) => node.task.id)).toEqual(["A"]);
expect(result.current.edges).toEqual([]);
});
describe("orphan dependencies to excluded tasks", () => {
it("drops dependency edge to done task while keeping dependent node", () => {
const filteredTasks = [createTask("A", "in-progress", ["DONE-1"])];
const { result } = renderHook(() => useGraphData(filteredTasks));
expect(result.current.nodes.map((node) => node.task.id)).toEqual(["A"]);
expect(result.current.edges).toEqual([]);
});
it("drops dependency edge to archived task while keeping dependent node", () => {
const filteredTasks = [createTask("A", "triage", ["ARCH-1"])];
const { result } = renderHook(() => useGraphData(filteredTasks));
expect(result.current.nodes.map((node) => node.task.id)).toEqual(["A"]);
expect(result.current.edges).toEqual([]);
});
it("keeps only included dependency edges when mixed dependencies are present", () => {
const filteredTasks = [createTask("A", "in-progress", ["B", "DONE-1", "ARCH-1"]), createTask("B", "todo")];
const { result } = renderHook(() => useGraphData(filteredTasks));
expect(result.current.nodes.map((node) => node.task.id)).toEqual(["A", "B"]);
expect(result.current.edges).toEqual([{ source: "A", target: "B" }]);
});
it("shows zero edges when all dependencies are excluded", () => {
const filteredTasks = [createTask("A", "in-progress", ["DONE-1", "ARCH-1"])];
const { result } = renderHook(() => useGraphData(filteredTasks));
expect(result.current.nodes.map((node) => node.task.id)).toEqual(["A"]);
expect(result.current.edges).toEqual([]);
});
});
describe("in-review dependency edges", () => {
it("renders edges between in-review tasks", () => {
const tasks = [createTask("A", "in-review", ["B"]), createTask("B", "in-review")];
const { result } = renderHook(() => useGraphData(tasks));
expect(result.current.edges).toEqual([{ source: "A", target: "B" }]);
});
it("renders edge from in-review task to in-progress task", () => {
const tasks = [createTask("A", "in-review", ["B"]), createTask("B", "in-progress")];
const { result } = renderHook(() => useGraphData(tasks));
expect(result.current.edges).toEqual([{ source: "A", target: "B" }]);
});
it("renders edge from in-progress task to in-review task", () => {
const tasks = [createTask("A", "in-progress", ["B"]), createTask("B", "in-review")];
const { result } = renderHook(() => useGraphData(tasks));
expect(result.current.edges).toEqual([{ source: "A", target: "B" }]);
});
});
});