config: tsx,icons,fakemui (15 files)

This commit is contained in:
Richard Ward
2025-12-30 14:11:25 +00:00
parent 076005ede3
commit b20432cdfc
15 changed files with 503 additions and 2 deletions

View File

@@ -0,0 +1,12 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const CenterFocusStrong = (props: IconProps) => (
<Icon {...props}>
<circle cx="128" cy="128" r="32" fill="currentColor" stroke="none" />
<path d="M88 32 L56 32 C42.7 32 32 42.7 32 56 L32 88" />
<path d="M168 32 L200 32 C213.3 32 224 42.7 224 56 L224 88" />
<path d="M88 224 L56 224 C42.7 224 32 213.3 32 200 L32 168" />
<path d="M168 224 L200 224 C213.3 224 224 213.3 224 200 L224 168" />
</Icon>
)

View File

@@ -0,0 +1,11 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const CompareArrows = (props: IconProps) => (
<Icon {...props}>
<line x1="48" y1="88" x2="208" y2="88" />
<polyline points="168 48 208 88 168 128" />
<line x1="208" y1="168" x2="48" y2="168" />
<polyline points="88 128 48 168 88 208" />
</Icon>
)

11
fakemui/icons/Launch.tsx Normal file
View File

@@ -0,0 +1,11 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const Launch = (props: IconProps) => (
<Icon {...props}>
<path d="M208 48 L208 120" />
<path d="M136 48 L208 48 L136 120" />
<path d="M168 88 L88 168" />
<path d="M168 168 L168 200 C168 208.8 160.8 216 152 216 L56 216 C47.2 216 40 208.8 40 200 L40 104 C40 95.2 47.2 88 56 88 L88 88" />
</Icon>
)

View File

@@ -0,0 +1,8 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const NavigateBefore = (props: IconProps) => (
<Icon {...props}>
<polyline points="160 48 80 128 160 208" />
</Icon>
)

View File

@@ -0,0 +1,9 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const SwapHoriz = (props: IconProps) => (
<Icon {...props}>
<polyline points="208 96 48 96 88 56" />
<polyline points="48 160 208 160 168 200" />
</Icon>
)

View File

@@ -0,0 +1,9 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const SwapVert = (props: IconProps) => (
<Icon {...props}>
<polyline points="96 208 96 48 56 88" />
<polyline points="160 48 160 208 200 168" />
</Icon>
)

View File

@@ -0,0 +1,9 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const UnfoldLess = (props: IconProps) => (
<Icon {...props}>
<polyline points="128 88 168 48 88 48 128 88" />
<polyline points="128 168 168 208 88 208 128 168" />
</Icon>
)

View File

@@ -0,0 +1,9 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const UnfoldMore = (props: IconProps) => (
<Icon {...props}>
<polyline points="128 48 168 88 88 88 128 48" />
<polyline points="128 208 168 168 88 168 128 208" />
</Icon>
)

View File

@@ -0,0 +1,15 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const ZoomInMap = (props: IconProps) => (
<Icon {...props}>
<polyline points="152 104 152 56 104 56" />
<line x1="104 104" x2="152 56" />
<polyline points="104 152 104 200 152 200" />
<line x1="152 152" x2="104 200" />
<polyline points="56 104 56 152 104 152" />
<line x1="56 104" x2="104 152" />
<polyline points="200 152 200 104 152 104" />
<line x1="200 152" x2="152 104" />
</Icon>
)

View File

@@ -0,0 +1,15 @@
import React from 'react'
import { Icon, IconProps } from './Icon'
export const ZoomOutMap = (props: IconProps) => (
<Icon {...props}>
<polyline points="104 56 56 56 56 104" />
<line x1="104 104" x2="56 56" />
<polyline points="152 200 200 200 200 152" />
<line x1="152 152" x2="200 200" />
<polyline points="56 152 56 200 104 200" />
<line x1="104 152" x2="56 200" />
<polyline points="200 104 200 56 152 56" />
<line x1="152 104" x2="200 56" />
</Icon>
)

View File

@@ -22,10 +22,14 @@
},
"tests": {
"scripts": [
"tests/status.test.lua"
"tests/status.test.lua",
"tests/editor.test.lua",
"tests/run.test.lua"
],
"cases": [
"tests/status.cases.json"
"tests/status.cases.json",
"tests/editor.cases.json",
"tests/run.cases.json"
]
},
"minLevel": 5

View File

@@ -0,0 +1,121 @@
{
"render": [
{
"desc": "Renders new workflow with default name",
"input": null,
"expected_name": "New Workflow",
"expected_steps_count": 0
},
{
"desc": "Renders existing workflow with name",
"input": {
"id": "wf-123",
"name": "Deploy Pipeline",
"steps": []
},
"expected_id": "wf-123",
"expected_name": "Deploy Pipeline",
"expected_steps_count": 0
},
{
"desc": "Renders workflow with steps",
"input": {
"id": "wf-456",
"name": "Build & Test",
"steps": [
{ "type": "build" },
{ "type": "test" }
]
},
"expected_id": "wf-456",
"expected_name": "Build & Test",
"expected_steps_count": 2
},
{
"desc": "Renders workflow without ID",
"input": {
"name": "CI Pipeline"
},
"expected_name": "CI Pipeline",
"expected_steps_count": 0
}
],
"add_step": [
{
"desc": "Adds build step without config",
"step_type": "build",
"config": null
},
{
"desc": "Adds test step with config",
"step_type": "test",
"config": {
"framework": "jest",
"coverage": true
}
},
{
"desc": "Adds deploy step with target",
"step_type": "deploy",
"config": {
"target": "production",
"region": "us-east-1"
}
},
{
"desc": "Adds notification step",
"step_type": "notify",
"config": {
"channel": "slack",
"webhook": "https://hooks.slack.com/..."
}
},
{
"desc": "Adds approval step",
"step_type": "approval",
"config": {
"approvers": ["admin", "devops"]
}
},
{
"desc": "Adds script step with inline code",
"step_type": "script",
"config": {
"language": "bash",
"code": "echo 'Hello World'"
}
}
],
"connect_steps": [
{
"desc": "Connects two steps without condition",
"from": "step-1",
"to": "step-2",
"condition": null
},
{
"desc": "Connects steps with success condition",
"from": "build",
"to": "test",
"condition": "on_success"
},
{
"desc": "Connects steps with failure condition",
"from": "test",
"to": "notify-failure",
"condition": "on_failure"
},
{
"desc": "Connects steps with always condition",
"from": "deploy",
"to": "cleanup",
"condition": "always"
},
{
"desc": "Connects approval to deploy",
"from": "approval-step",
"to": "deploy-prod",
"condition": "approved"
}
]
}

View File

@@ -0,0 +1,48 @@
-- Workflow editor tests
-- Uses lua_test framework with parameterized test cases
describe("Workflow Editor", function()
local cases = load_cases("editor.cases.json")
local editor = require("editor")
describe("render", function()
it_each(cases.render, "$desc", function(tc)
local result = editor.render(tc.input)
expect(result.type).toBe("workflow_editor")
expect(result.props.name).toBe(tc.expected_name)
if tc.expected_id then
expect(result.props.id).toBe(tc.expected_id)
end
if tc.expected_steps_count ~= nil then
expect(#result.props.steps).toBe(tc.expected_steps_count)
end
end)
end)
describe("add_step", function()
it_each(cases.add_step, "$desc", function(tc)
local result = editor.add_step(tc.step_type, tc.config)
expect(result.type).toBe("workflow_step")
expect(result.step_type).toBe(tc.step_type)
expect(result.position.x).toBe(0)
expect(result.position.y).toBe(0)
if tc.config then
expect(result.config).toBeDefined()
end
end)
end)
describe("connect_steps", function()
it_each(cases.connect_steps, "$desc", function(tc)
local result = editor.connect_steps(tc.from, tc.to, tc.condition)
expect(result.type).toBe("connection")
expect(result.from).toBe(tc.from)
expect(result.to).toBe(tc.to)
if tc.condition then
expect(result.condition).toBe(tc.condition)
else
expect(result.condition).toBeNil()
end
end)
end)
end)

View File

@@ -0,0 +1,167 @@
{
"render": [
{
"desc": "Renders completed run",
"input": {
"workflow_name": "Deploy Production",
"run_number": 42,
"started_at": "2025-01-15 14:30:00",
"duration": "5m 32s",
"status": "success"
},
"expected_title": "Deploy Production",
"expected_subtitle": "Run #42",
"expected_duration": "5m 32s",
"expected_status": "success"
},
{
"desc": "Renders failed run",
"input": {
"workflow_name": "CI Pipeline",
"run_number": 128,
"started_at": "2025-01-15 15:45:00",
"duration": "2m 15s",
"status": "failure"
},
"expected_title": "CI Pipeline",
"expected_subtitle": "Run #128",
"expected_duration": "2m 15s",
"expected_status": "failure"
},
{
"desc": "Renders running workflow",
"input": {
"workflow_name": "Build & Test",
"run_number": 99,
"started_at": "2025-01-15 16:00:00",
"status": "running"
},
"expected_title": "Build & Test",
"expected_subtitle": "Run #99",
"expected_duration": "running",
"expected_status": "running"
},
{
"desc": "Renders cancelled run",
"input": {
"workflow_name": "Nightly Build",
"run_number": 7,
"started_at": "2025-01-15 02:00:00",
"duration": "1m 05s",
"status": "cancelled"
},
"expected_title": "Nightly Build",
"expected_subtitle": "Run #7",
"expected_duration": "1m 05s",
"expected_status": "cancelled"
},
{
"desc": "Renders queued run",
"input": {
"workflow_name": "Integration Tests",
"run_number": 200,
"started_at": "2025-01-15 17:00:00",
"status": "queued"
},
"expected_title": "Integration Tests",
"expected_subtitle": "Run #200",
"expected_duration": "running",
"expected_status": "queued"
},
{
"desc": "Renders run with very long duration",
"input": {
"workflow_name": "Performance Tests",
"run_number": 1,
"started_at": "2025-01-15 10:00:00",
"duration": "1h 45m 30s",
"status": "success"
},
"expected_title": "Performance Tests",
"expected_subtitle": "Run #1",
"expected_duration": "1h 45m 30s",
"expected_status": "success"
}
],
"render_list": [
{
"desc": "Renders single run",
"input": [
{
"workflow_name": "Deploy",
"run_number": 1,
"started_at": "2025-01-15 14:00:00",
"duration": "3m",
"status": "success"
}
],
"expected_count": 1
},
{
"desc": "Renders multiple runs",
"input": [
{
"workflow_name": "Build",
"run_number": 1,
"started_at": "2025-01-15 10:00:00",
"duration": "2m",
"status": "success"
},
{
"workflow_name": "Test",
"run_number": 2,
"started_at": "2025-01-15 11:00:00",
"duration": "5m",
"status": "success"
},
{
"workflow_name": "Deploy",
"run_number": 3,
"started_at": "2025-01-15 12:00:00",
"status": "running"
}
],
"expected_count": 3
},
{
"desc": "Renders many runs in grid",
"input": [
{
"workflow_name": "Run 1",
"run_number": 1,
"started_at": "2025-01-15 08:00:00",
"duration": "1m",
"status": "success"
},
{
"workflow_name": "Run 2",
"run_number": 2,
"started_at": "2025-01-15 09:00:00",
"duration": "2m",
"status": "success"
},
{
"workflow_name": "Run 3",
"run_number": 3,
"started_at": "2025-01-15 10:00:00",
"duration": "1m",
"status": "failure"
},
{
"workflow_name": "Run 4",
"run_number": 4,
"started_at": "2025-01-15 11:00:00",
"status": "running"
},
{
"workflow_name": "Run 5",
"run_number": 5,
"started_at": "2025-01-15 12:00:00",
"duration": "3m",
"status": "success"
}
],
"expected_count": 5
}
]
}

View File

@@ -0,0 +1,53 @@
-- Workflow run card tests
-- Uses lua_test framework with parameterized test cases
describe("Workflow Run Cards", function()
local cases = load_cases("run.cases.json")
local run = require("run")
describe("render", function()
it_each(cases.render, "$desc", function(tc)
local result = run.render(tc.input)
expect(result.type).toBe("card")
expect(result.props.title).toBe(tc.expected_title)
expect(result.props.subtitle).toBe(tc.expected_subtitle)
expect(#result.children).toBe(3)
-- Check started timestamp
expect(result.children[1].type).toBe("text")
expect(result.children[1].content).toContain("Started:")
-- Check duration
expect(result.children[2].type).toBe("text")
expect(result.children[2].content).toContain("Duration:")
if tc.expected_duration then
expect(result.children[2].content).toContain(tc.expected_duration)
end
-- Check status badge
expect(result.children[3].type).toBe("status_badge")
expect(result.children[3].status).toBe(tc.expected_status)
end)
end)
describe("render_list", function()
it_each(cases.render_list, "$desc", function(tc)
local result = run.render_list(tc.input)
expect(result.type).toBe("grid")
expect(result.columns).toBe(2)
expect(#result.children).toBe(tc.expected_count)
-- Verify all children are cards
for i, child in ipairs(result.children) do
expect(child.type).toBe("card")
end
end)
it("renders empty list", function()
local result = run.render_list({})
expect(result.type).toBe("grid")
expect(result.columns).toBe(2)
expect(#result.children).toBe(0)
end)
end)
end)