@factorialco/shadowdog
Version:
<img src="https://raw.githubusercontent.com/factorialco/shadowdog/refs/heads/main/logo.png" alt="drawing" width="100"/>
209 lines (208 loc) • 7.73 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const shadowdog_tree_1 = __importDefault(require("./shadowdog-tree"));
(0, vitest_1.it)('shadowdog tree organize tasks with dependencies in serial tasks', () => {
const task = {
type: 'parallel',
tasks: [
{
type: 'command',
config: {
command: 'echo first',
artifacts: [
{
output: 'first.artifact',
},
],
tags: [],
workingDirectory: '',
},
files: [],
environment: [],
},
{
type: 'command',
config: {
command: 'echo second',
artifacts: [
{
output: 'second.artifact',
},
],
tags: [],
workingDirectory: '',
},
files: ['first.artifact'],
environment: [],
},
{
type: 'command',
config: {
command: 'echo third',
artifacts: [
{
output: 'third.artifact',
},
],
tags: [],
workingDirectory: '',
},
files: ['second.artifact'],
environment: [],
},
],
};
(0, vitest_1.expect)(shadowdog_tree_1.default.command(task)).toEqual({
type: 'serial',
tasks: [
{
type: 'parallel',
tasks: [
{
type: 'command',
config: {
command: 'echo first',
artifacts: [
{
output: 'first.artifact',
},
],
tags: [],
workingDirectory: '',
},
files: [],
environment: [],
},
],
},
{
type: 'parallel',
tasks: [
{
type: 'command',
config: {
command: 'echo second',
artifacts: [
{
output: 'second.artifact',
},
],
tags: [],
workingDirectory: '',
},
files: ['first.artifact'],
environment: [],
},
],
},
{
type: 'parallel',
tasks: [
{
type: 'command',
config: {
command: 'echo third',
artifacts: [
{
output: 'third.artifact',
},
],
tags: [],
workingDirectory: '',
},
files: ['second.artifact'],
environment: [],
},
],
},
],
});
});
(0, vitest_1.it)('shadowdog tree preserves dependency chain even when intermediate files do not exist', () => {
// This test simulates the real-world scenario where backend/resources.json doesn't exist
// but is needed as a dependency for the second command
const task = {
type: 'parallel',
tasks: [
{
type: 'command',
config: {
command: 'cd backend && bundle exec rake resource_registry:generate_cache',
artifacts: [
{
output: 'backend/resources.json',
},
],
tags: [],
workingDirectory: '',
},
files: ['backend/lib/resource_registry/catalog.rb'], // Some existing file
environment: [],
},
{
type: 'command',
config: {
command: 'cd backend && bundle exec rake autodiscovery:generate_graphql_schema',
artifacts: [
{
output: 'backend/schema.graphql',
},
],
tags: [],
workingDirectory: '',
},
files: ['backend/resources.json'], // This file doesn't exist but should be preserved for dependency tracking
environment: [],
},
{
type: 'command',
config: {
command: 'cd frontend && pnpm graphql-codegen',
artifacts: [
{
output: 'frontend/src/generated/resources',
},
],
tags: [],
workingDirectory: '',
},
files: ['backend/schema.graphql'], // This file also doesn't exist but should be preserved
environment: [],
},
],
};
const result = shadowdog_tree_1.default.command(task);
(0, vitest_1.expect)(result.type).toBe('serial');
if (result.type === 'serial') {
(0, vitest_1.expect)(result.tasks).toHaveLength(3); // Should have 3 layers
// Verify the correct dependency order
(0, vitest_1.expect)(result.tasks[0].type).toBe('parallel');
if (result.tasks[0].type === 'parallel') {
(0, vitest_1.expect)(result.tasks[0].tasks).toHaveLength(1);
const firstTask = result.tasks[0].tasks[0];
if (firstTask.type === 'command') {
(0, vitest_1.expect)(firstTask.config.command).toContain('resource_registry:generate_cache');
}
}
(0, vitest_1.expect)(result.tasks[1].type).toBe('parallel');
if (result.tasks[1].type === 'parallel') {
(0, vitest_1.expect)(result.tasks[1].tasks).toHaveLength(1);
const secondTask = result.tasks[1].tasks[0];
if (secondTask.type === 'command') {
(0, vitest_1.expect)(secondTask.config.command).toContain('autodiscovery:generate_graphql_schema');
}
}
(0, vitest_1.expect)(result.tasks[2].type).toBe('parallel');
if (result.tasks[2].type === 'parallel') {
(0, vitest_1.expect)(result.tasks[2].tasks).toHaveLength(1);
const thirdTask = result.tasks[2].tasks[0];
if (thirdTask.type === 'command') {
(0, vitest_1.expect)(thirdTask.config.command).toContain('pnpm graphql-codegen');
}
}
}
});