mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 08:33:36 +00:00
Merge main into massive-terminal-upgrade
Resolves merge conflicts: - apps/server/src/routes/terminal/common.ts: Keep randomBytes import, use @automaker/utils for createLogger - apps/ui/eslint.config.mjs: Use main's explicit globals list with XMLHttpRequest and MediaQueryListEvent additions - apps/ui/src/components/views/terminal-view.tsx: Keep our terminal improvements (killAllSessions, beforeunload, better error handling) - apps/ui/src/config/terminal-themes.ts: Keep our search highlight colors for all themes - apps/ui/src/store/app-store.ts: Keep our terminal settings persistence improvements (merge function) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import {
|
||||
resolveDependencies,
|
||||
areDependenciesSatisfied,
|
||||
getBlockingDependencies,
|
||||
type DependencyResolutionResult,
|
||||
} from "@/lib/dependency-resolver.js";
|
||||
import type { Feature } from "@/services/feature-loader.js";
|
||||
} from '@automaker/dependency-resolver';
|
||||
import type { Feature } from '@automaker/types';
|
||||
|
||||
// Helper to create test features
|
||||
function createFeature(
|
||||
@@ -20,17 +20,17 @@ function createFeature(
|
||||
): Feature {
|
||||
return {
|
||||
id,
|
||||
category: options.category || "test",
|
||||
category: options.category || 'test',
|
||||
description: options.description || `Feature ${id}`,
|
||||
status: options.status || "backlog",
|
||||
status: options.status || 'backlog',
|
||||
priority: options.priority,
|
||||
dependencies: options.dependencies,
|
||||
};
|
||||
}
|
||||
|
||||
describe("dependency-resolver.ts", () => {
|
||||
describe("resolveDependencies", () => {
|
||||
it("should handle empty feature list", () => {
|
||||
describe('dependency-resolver.ts', () => {
|
||||
describe('resolveDependencies', () => {
|
||||
it('should handle empty feature list', () => {
|
||||
const result = resolveDependencies([]);
|
||||
|
||||
expect(result.orderedFeatures).toEqual([]);
|
||||
@@ -39,103 +39,103 @@ describe("dependency-resolver.ts", () => {
|
||||
expect(result.blockedFeatures.size).toBe(0);
|
||||
});
|
||||
|
||||
it("should handle features with no dependencies", () => {
|
||||
it('should handle features with no dependencies', () => {
|
||||
const features = [
|
||||
createFeature("f1", { priority: 1 }),
|
||||
createFeature("f2", { priority: 2 }),
|
||||
createFeature("f3", { priority: 3 }),
|
||||
createFeature('f1', { priority: 1 }),
|
||||
createFeature('f2', { priority: 2 }),
|
||||
createFeature('f3', { priority: 3 }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.orderedFeatures).toHaveLength(3);
|
||||
expect(result.orderedFeatures[0].id).toBe("f1"); // Highest priority first
|
||||
expect(result.orderedFeatures[1].id).toBe("f2");
|
||||
expect(result.orderedFeatures[2].id).toBe("f3");
|
||||
expect(result.orderedFeatures[0].id).toBe('f1'); // Highest priority first
|
||||
expect(result.orderedFeatures[1].id).toBe('f2');
|
||||
expect(result.orderedFeatures[2].id).toBe('f3');
|
||||
expect(result.circularDependencies).toEqual([]);
|
||||
expect(result.missingDependencies.size).toBe(0);
|
||||
expect(result.blockedFeatures.size).toBe(0);
|
||||
});
|
||||
|
||||
it("should order features by dependencies (simple chain)", () => {
|
||||
it('should order features by dependencies (simple chain)', () => {
|
||||
const features = [
|
||||
createFeature("f3", { dependencies: ["f2"] }),
|
||||
createFeature("f1"),
|
||||
createFeature("f2", { dependencies: ["f1"] }),
|
||||
createFeature('f3', { dependencies: ['f2'] }),
|
||||
createFeature('f1'),
|
||||
createFeature('f2', { dependencies: ['f1'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.orderedFeatures).toHaveLength(3);
|
||||
expect(result.orderedFeatures[0].id).toBe("f1");
|
||||
expect(result.orderedFeatures[1].id).toBe("f2");
|
||||
expect(result.orderedFeatures[2].id).toBe("f3");
|
||||
expect(result.orderedFeatures[0].id).toBe('f1');
|
||||
expect(result.orderedFeatures[1].id).toBe('f2');
|
||||
expect(result.orderedFeatures[2].id).toBe('f3');
|
||||
expect(result.circularDependencies).toEqual([]);
|
||||
});
|
||||
|
||||
it("should respect priority within same dependency level", () => {
|
||||
it('should respect priority within same dependency level', () => {
|
||||
const features = [
|
||||
createFeature("f1", { priority: 3, dependencies: ["base"] }),
|
||||
createFeature("f2", { priority: 1, dependencies: ["base"] }),
|
||||
createFeature("f3", { priority: 2, dependencies: ["base"] }),
|
||||
createFeature("base"),
|
||||
createFeature('f1', { priority: 3, dependencies: ['base'] }),
|
||||
createFeature('f2', { priority: 1, dependencies: ['base'] }),
|
||||
createFeature('f3', { priority: 2, dependencies: ['base'] }),
|
||||
createFeature('base'),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.orderedFeatures[0].id).toBe("base");
|
||||
expect(result.orderedFeatures[1].id).toBe("f2"); // Priority 1
|
||||
expect(result.orderedFeatures[2].id).toBe("f3"); // Priority 2
|
||||
expect(result.orderedFeatures[3].id).toBe("f1"); // Priority 3
|
||||
expect(result.orderedFeatures[0].id).toBe('base');
|
||||
expect(result.orderedFeatures[1].id).toBe('f2'); // Priority 1
|
||||
expect(result.orderedFeatures[2].id).toBe('f3'); // Priority 2
|
||||
expect(result.orderedFeatures[3].id).toBe('f1'); // Priority 3
|
||||
});
|
||||
|
||||
it("should use default priority of 2 when not specified", () => {
|
||||
it('should use default priority of 2 when not specified', () => {
|
||||
const features = [
|
||||
createFeature("f1", { priority: 1 }),
|
||||
createFeature("f2"), // No priority = default 2
|
||||
createFeature("f3", { priority: 3 }),
|
||||
createFeature('f1', { priority: 1 }),
|
||||
createFeature('f2'), // No priority = default 2
|
||||
createFeature('f3', { priority: 3 }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.orderedFeatures[0].id).toBe("f1");
|
||||
expect(result.orderedFeatures[1].id).toBe("f2");
|
||||
expect(result.orderedFeatures[2].id).toBe("f3");
|
||||
expect(result.orderedFeatures[0].id).toBe('f1');
|
||||
expect(result.orderedFeatures[1].id).toBe('f2');
|
||||
expect(result.orderedFeatures[2].id).toBe('f3');
|
||||
});
|
||||
|
||||
it("should detect missing dependencies", () => {
|
||||
it('should detect missing dependencies', () => {
|
||||
const features = [
|
||||
createFeature("f1", { dependencies: ["missing1", "missing2"] }),
|
||||
createFeature("f2", { dependencies: ["f1", "missing3"] }),
|
||||
createFeature('f1', { dependencies: ['missing1', 'missing2'] }),
|
||||
createFeature('f2', { dependencies: ['f1', 'missing3'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.missingDependencies.size).toBe(2);
|
||||
expect(result.missingDependencies.get("f1")).toEqual(["missing1", "missing2"]);
|
||||
expect(result.missingDependencies.get("f2")).toEqual(["missing3"]);
|
||||
expect(result.missingDependencies.get('f1')).toEqual(['missing1', 'missing2']);
|
||||
expect(result.missingDependencies.get('f2')).toEqual(['missing3']);
|
||||
expect(result.orderedFeatures).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("should detect blocked features (incomplete dependencies)", () => {
|
||||
it('should detect blocked features (incomplete dependencies)', () => {
|
||||
const features = [
|
||||
createFeature("f1", { status: "in_progress" }),
|
||||
createFeature("f2", { status: "backlog", dependencies: ["f1"] }),
|
||||
createFeature("f3", { status: "completed" }),
|
||||
createFeature("f4", { status: "backlog", dependencies: ["f3"] }),
|
||||
createFeature('f1', { status: 'in_progress' }),
|
||||
createFeature('f2', { status: 'backlog', dependencies: ['f1'] }),
|
||||
createFeature('f3', { status: 'completed' }),
|
||||
createFeature('f4', { status: 'backlog', dependencies: ['f3'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.blockedFeatures.size).toBe(1);
|
||||
expect(result.blockedFeatures.get("f2")).toEqual(["f1"]);
|
||||
expect(result.blockedFeatures.has("f4")).toBe(false); // f3 is completed
|
||||
expect(result.blockedFeatures.get('f2')).toEqual(['f1']);
|
||||
expect(result.blockedFeatures.has('f4')).toBe(false); // f3 is completed
|
||||
});
|
||||
|
||||
it("should not block features whose dependencies are verified", () => {
|
||||
it('should not block features whose dependencies are verified', () => {
|
||||
const features = [
|
||||
createFeature("f1", { status: "verified" }),
|
||||
createFeature("f2", { status: "backlog", dependencies: ["f1"] }),
|
||||
createFeature('f1', { status: 'verified' }),
|
||||
createFeature('f2', { status: 'backlog', dependencies: ['f1'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
@@ -143,25 +143,25 @@ describe("dependency-resolver.ts", () => {
|
||||
expect(result.blockedFeatures.size).toBe(0);
|
||||
});
|
||||
|
||||
it("should detect circular dependencies (simple cycle)", () => {
|
||||
it('should detect circular dependencies (simple cycle)', () => {
|
||||
const features = [
|
||||
createFeature("f1", { dependencies: ["f2"] }),
|
||||
createFeature("f2", { dependencies: ["f1"] }),
|
||||
createFeature('f1', { dependencies: ['f2'] }),
|
||||
createFeature('f2', { dependencies: ['f1'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.circularDependencies).toHaveLength(1);
|
||||
expect(result.circularDependencies[0]).toContain("f1");
|
||||
expect(result.circularDependencies[0]).toContain("f2");
|
||||
expect(result.circularDependencies[0]).toContain('f1');
|
||||
expect(result.circularDependencies[0]).toContain('f2');
|
||||
expect(result.orderedFeatures).toHaveLength(2); // Features still included
|
||||
});
|
||||
|
||||
it("should detect circular dependencies (multi-node cycle)", () => {
|
||||
it('should detect circular dependencies (multi-node cycle)', () => {
|
||||
const features = [
|
||||
createFeature("f1", { dependencies: ["f3"] }),
|
||||
createFeature("f2", { dependencies: ["f1"] }),
|
||||
createFeature("f3", { dependencies: ["f2"] }),
|
||||
createFeature('f1', { dependencies: ['f3'] }),
|
||||
createFeature('f2', { dependencies: ['f1'] }),
|
||||
createFeature('f3', { dependencies: ['f2'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
@@ -170,47 +170,47 @@ describe("dependency-resolver.ts", () => {
|
||||
expect(result.orderedFeatures).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("should handle mixed valid and circular dependencies", () => {
|
||||
it('should handle mixed valid and circular dependencies', () => {
|
||||
const features = [
|
||||
createFeature("base"),
|
||||
createFeature("f1", { dependencies: ["base", "f2"] }),
|
||||
createFeature("f2", { dependencies: ["f1"] }), // Circular with f1
|
||||
createFeature("f3", { dependencies: ["base"] }),
|
||||
createFeature('base'),
|
||||
createFeature('f1', { dependencies: ['base', 'f2'] }),
|
||||
createFeature('f2', { dependencies: ['f1'] }), // Circular with f1
|
||||
createFeature('f3', { dependencies: ['base'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.circularDependencies.length).toBeGreaterThan(0);
|
||||
expect(result.orderedFeatures[0].id).toBe("base");
|
||||
expect(result.orderedFeatures[0].id).toBe('base');
|
||||
expect(result.orderedFeatures).toHaveLength(4);
|
||||
});
|
||||
|
||||
it("should handle complex dependency graph", () => {
|
||||
it('should handle complex dependency graph', () => {
|
||||
const features = [
|
||||
createFeature("ui", { dependencies: ["api", "auth"], priority: 1 }),
|
||||
createFeature("api", { dependencies: ["db"], priority: 2 }),
|
||||
createFeature("auth", { dependencies: ["db"], priority: 1 }),
|
||||
createFeature("db", { priority: 1 }),
|
||||
createFeature("tests", { dependencies: ["ui"], priority: 3 }),
|
||||
createFeature('ui', { dependencies: ['api', 'auth'], priority: 1 }),
|
||||
createFeature('api', { dependencies: ['db'], priority: 2 }),
|
||||
createFeature('auth', { dependencies: ['db'], priority: 1 }),
|
||||
createFeature('db', { priority: 1 }),
|
||||
createFeature('tests', { dependencies: ['ui'], priority: 3 }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
const order = result.orderedFeatures.map(f => f.id);
|
||||
const order = result.orderedFeatures.map((f) => f.id);
|
||||
|
||||
expect(order[0]).toBe("db");
|
||||
expect(order.indexOf("db")).toBeLessThan(order.indexOf("api"));
|
||||
expect(order.indexOf("db")).toBeLessThan(order.indexOf("auth"));
|
||||
expect(order.indexOf("api")).toBeLessThan(order.indexOf("ui"));
|
||||
expect(order.indexOf("auth")).toBeLessThan(order.indexOf("ui"));
|
||||
expect(order.indexOf("ui")).toBeLessThan(order.indexOf("tests"));
|
||||
expect(order[0]).toBe('db');
|
||||
expect(order.indexOf('db')).toBeLessThan(order.indexOf('api'));
|
||||
expect(order.indexOf('db')).toBeLessThan(order.indexOf('auth'));
|
||||
expect(order.indexOf('api')).toBeLessThan(order.indexOf('ui'));
|
||||
expect(order.indexOf('auth')).toBeLessThan(order.indexOf('ui'));
|
||||
expect(order.indexOf('ui')).toBeLessThan(order.indexOf('tests'));
|
||||
expect(result.circularDependencies).toEqual([]);
|
||||
});
|
||||
|
||||
it("should handle features with empty dependencies array", () => {
|
||||
it('should handle features with empty dependencies array', () => {
|
||||
const features = [
|
||||
createFeature("f1", { dependencies: [] }),
|
||||
createFeature("f2", { dependencies: [] }),
|
||||
createFeature('f1', { dependencies: [] }),
|
||||
createFeature('f2', { dependencies: [] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
@@ -220,22 +220,20 @@ describe("dependency-resolver.ts", () => {
|
||||
expect(result.blockedFeatures.size).toBe(0);
|
||||
});
|
||||
|
||||
it("should track multiple blocking dependencies", () => {
|
||||
it('should track multiple blocking dependencies', () => {
|
||||
const features = [
|
||||
createFeature("f1", { status: "in_progress" }),
|
||||
createFeature("f2", { status: "backlog" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'in_progress' }),
|
||||
createFeature('f2', { status: 'backlog' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
expect(result.blockedFeatures.get("f3")).toEqual(["f1", "f2"]);
|
||||
expect(result.blockedFeatures.get('f3')).toEqual(['f1', 'f2']);
|
||||
});
|
||||
|
||||
it("should handle self-referencing dependency", () => {
|
||||
const features = [
|
||||
createFeature("f1", { dependencies: ["f1"] }),
|
||||
];
|
||||
it('should handle self-referencing dependency', () => {
|
||||
const features = [createFeature('f1', { dependencies: ['f1'] })];
|
||||
|
||||
const result = resolveDependencies(features);
|
||||
|
||||
@@ -244,195 +242,191 @@ describe("dependency-resolver.ts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("areDependenciesSatisfied", () => {
|
||||
it("should return true for feature with no dependencies", () => {
|
||||
const feature = createFeature("f1");
|
||||
describe('areDependenciesSatisfied', () => {
|
||||
it('should return true for feature with no dependencies', () => {
|
||||
const feature = createFeature('f1');
|
||||
const allFeatures = [feature];
|
||||
|
||||
expect(areDependenciesSatisfied(feature, allFeatures)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return true for feature with empty dependencies array", () => {
|
||||
const feature = createFeature("f1", { dependencies: [] });
|
||||
it('should return true for feature with empty dependencies array', () => {
|
||||
const feature = createFeature('f1', { dependencies: [] });
|
||||
const allFeatures = [feature];
|
||||
|
||||
expect(areDependenciesSatisfied(feature, allFeatures)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return true when all dependencies are completed", () => {
|
||||
it('should return true when all dependencies are completed', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "completed" }),
|
||||
createFeature("f2", { status: "completed" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'completed' }),
|
||||
createFeature('f2', { status: 'completed' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[2], allFeatures)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return true when all dependencies are verified", () => {
|
||||
it('should return true when all dependencies are verified', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "verified" }),
|
||||
createFeature("f2", { status: "verified" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'verified' }),
|
||||
createFeature('f2', { status: 'verified' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[2], allFeatures)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return true when dependencies are mix of completed and verified", () => {
|
||||
it('should return true when dependencies are mix of completed and verified', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "completed" }),
|
||||
createFeature("f2", { status: "verified" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'completed' }),
|
||||
createFeature('f2', { status: 'verified' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[2], allFeatures)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false when any dependency is in_progress", () => {
|
||||
it('should return false when any dependency is in_progress', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "completed" }),
|
||||
createFeature("f2", { status: "in_progress" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'completed' }),
|
||||
createFeature('f2', { status: 'in_progress' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[2], allFeatures)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when any dependency is in backlog", () => {
|
||||
it('should return false when any dependency is in backlog', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "completed" }),
|
||||
createFeature("f2", { status: "backlog" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'completed' }),
|
||||
createFeature('f2', { status: 'backlog' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[2], allFeatures)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when dependency is missing", () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "backlog", dependencies: ["missing"] }),
|
||||
];
|
||||
it('should return false when dependency is missing', () => {
|
||||
const allFeatures = [createFeature('f1', { status: 'backlog', dependencies: ['missing'] })];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[0], allFeatures)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false when multiple dependencies are incomplete", () => {
|
||||
it('should return false when multiple dependencies are incomplete', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "backlog" }),
|
||||
createFeature("f2", { status: "in_progress" }),
|
||||
createFeature("f3", { status: "waiting_approval" }),
|
||||
createFeature("f4", { status: "backlog", dependencies: ["f1", "f2", "f3"] }),
|
||||
createFeature('f1', { status: 'backlog' }),
|
||||
createFeature('f2', { status: 'in_progress' }),
|
||||
createFeature('f3', { status: 'waiting_approval' }),
|
||||
createFeature('f4', { status: 'backlog', dependencies: ['f1', 'f2', 'f3'] }),
|
||||
];
|
||||
|
||||
expect(areDependenciesSatisfied(allFeatures[3], allFeatures)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getBlockingDependencies", () => {
|
||||
it("should return empty array for feature with no dependencies", () => {
|
||||
const feature = createFeature("f1");
|
||||
describe('getBlockingDependencies', () => {
|
||||
it('should return empty array for feature with no dependencies', () => {
|
||||
const feature = createFeature('f1');
|
||||
const allFeatures = [feature];
|
||||
|
||||
expect(getBlockingDependencies(feature, allFeatures)).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return empty array for feature with empty dependencies array", () => {
|
||||
const feature = createFeature("f1", { dependencies: [] });
|
||||
it('should return empty array for feature with empty dependencies array', () => {
|
||||
const feature = createFeature('f1', { dependencies: [] });
|
||||
const allFeatures = [feature];
|
||||
|
||||
expect(getBlockingDependencies(feature, allFeatures)).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return empty array when all dependencies are completed", () => {
|
||||
it('should return empty array when all dependencies are completed', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "completed" }),
|
||||
createFeature("f2", { status: "completed" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'completed' }),
|
||||
createFeature('f2', { status: 'completed' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return empty array when all dependencies are verified", () => {
|
||||
it('should return empty array when all dependencies are verified', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "verified" }),
|
||||
createFeature("f2", { status: "verified" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'verified' }),
|
||||
createFeature('f2', { status: 'verified' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return blocking dependencies in backlog status", () => {
|
||||
it('should return blocking dependencies in backlog status', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "backlog" }),
|
||||
createFeature("f2", { status: "completed" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'backlog' }),
|
||||
createFeature('f2', { status: 'completed' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual(["f1"]);
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual(['f1']);
|
||||
});
|
||||
|
||||
it("should return blocking dependencies in in_progress status", () => {
|
||||
it('should return blocking dependencies in in_progress status', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "in_progress" }),
|
||||
createFeature("f2", { status: "verified" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'in_progress' }),
|
||||
createFeature('f2', { status: 'verified' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual(["f1"]);
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual(['f1']);
|
||||
});
|
||||
|
||||
it("should return blocking dependencies in waiting_approval status", () => {
|
||||
it('should return blocking dependencies in waiting_approval status', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "waiting_approval" }),
|
||||
createFeature("f2", { status: "completed" }),
|
||||
createFeature("f3", { status: "backlog", dependencies: ["f1", "f2"] }),
|
||||
createFeature('f1', { status: 'waiting_approval' }),
|
||||
createFeature('f2', { status: 'completed' }),
|
||||
createFeature('f3', { status: 'backlog', dependencies: ['f1', 'f2'] }),
|
||||
];
|
||||
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual(["f1"]);
|
||||
expect(getBlockingDependencies(allFeatures[2], allFeatures)).toEqual(['f1']);
|
||||
});
|
||||
|
||||
it("should return all blocking dependencies", () => {
|
||||
it('should return all blocking dependencies', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "backlog" }),
|
||||
createFeature("f2", { status: "in_progress" }),
|
||||
createFeature("f3", { status: "waiting_approval" }),
|
||||
createFeature("f4", { status: "completed" }),
|
||||
createFeature("f5", { status: "backlog", dependencies: ["f1", "f2", "f3", "f4"] }),
|
||||
createFeature('f1', { status: 'backlog' }),
|
||||
createFeature('f2', { status: 'in_progress' }),
|
||||
createFeature('f3', { status: 'waiting_approval' }),
|
||||
createFeature('f4', { status: 'completed' }),
|
||||
createFeature('f5', { status: 'backlog', dependencies: ['f1', 'f2', 'f3', 'f4'] }),
|
||||
];
|
||||
|
||||
const blocking = getBlockingDependencies(allFeatures[4], allFeatures);
|
||||
expect(blocking).toHaveLength(3);
|
||||
expect(blocking).toContain("f1");
|
||||
expect(blocking).toContain("f2");
|
||||
expect(blocking).toContain("f3");
|
||||
expect(blocking).not.toContain("f4");
|
||||
expect(blocking).toContain('f1');
|
||||
expect(blocking).toContain('f2');
|
||||
expect(blocking).toContain('f3');
|
||||
expect(blocking).not.toContain('f4');
|
||||
});
|
||||
|
||||
it("should handle missing dependencies", () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "backlog", dependencies: ["missing"] }),
|
||||
];
|
||||
it('should handle missing dependencies', () => {
|
||||
const allFeatures = [createFeature('f1', { status: 'backlog', dependencies: ['missing'] })];
|
||||
|
||||
// Missing dependencies won't be in the blocking list since they don't exist
|
||||
expect(getBlockingDependencies(allFeatures[0], allFeatures)).toEqual([]);
|
||||
});
|
||||
|
||||
it("should handle mix of completed, verified, and incomplete dependencies", () => {
|
||||
it('should handle mix of completed, verified, and incomplete dependencies', () => {
|
||||
const allFeatures = [
|
||||
createFeature("f1", { status: "completed" }),
|
||||
createFeature("f2", { status: "verified" }),
|
||||
createFeature("f3", { status: "in_progress" }),
|
||||
createFeature("f4", { status: "backlog" }),
|
||||
createFeature("f5", { status: "backlog", dependencies: ["f1", "f2", "f3", "f4"] }),
|
||||
createFeature('f1', { status: 'completed' }),
|
||||
createFeature('f2', { status: 'verified' }),
|
||||
createFeature('f3', { status: 'in_progress' }),
|
||||
createFeature('f4', { status: 'backlog' }),
|
||||
createFeature('f5', { status: 'backlog', dependencies: ['f1', 'f2', 'f3', 'f4'] }),
|
||||
];
|
||||
|
||||
const blocking = getBlockingDependencies(allFeatures[4], allFeatures);
|
||||
expect(blocking).toHaveLength(2);
|
||||
expect(blocking).toContain("f3");
|
||||
expect(blocking).toContain("f4");
|
||||
expect(blocking).toContain('f3');
|
||||
expect(blocking).toContain('f4');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user