fix: navigate to /logs after issue creation, fix dashboard category display
Some checks failed
Test / frontend-tests (push) Waiting to run
Test / frontend-typecheck (push) Waiting to run
Auto Tag / auto-tag (push) Successful in 3s
Test / rust-fmt-check (push) Successful in 1m6s
Release / build-macos-arm64 (push) Successful in 3m24s
Release / build-linux-amd64 (push) Has been cancelled
Release / build-windows-amd64 (push) Has been cancelled
Release / build-linux-arm64 (push) Has been cancelled
Test / rust-clippy (push) Successful in 7m15s
Test / rust-tests (push) Has been cancelled
Some checks failed
Test / frontend-tests (push) Waiting to run
Test / frontend-typecheck (push) Waiting to run
Auto Tag / auto-tag (push) Successful in 3s
Test / rust-fmt-check (push) Successful in 1m6s
Release / build-macos-arm64 (push) Successful in 3m24s
Release / build-linux-amd64 (push) Has been cancelled
Release / build-windows-amd64 (push) Has been cancelled
Release / build-linux-arm64 (push) Has been cancelled
Test / rust-clippy (push) Successful in 7m15s
Test / rust-tests (push) Has been cancelled
- NewIssue: navigate to /issue/:id/logs so log upload step is not skipped - Dashboard: use issue.category instead of issue.domain (field name matches Rust) - tests: add historyStore tests covering open count logic and field mapping
This commit is contained in:
parent
74afb47eac
commit
ebf60d17c6
@ -108,7 +108,7 @@ export default function Dashboard() {
|
||||
<div>
|
||||
<p className="text-sm font-medium">{issue.title}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{issue.domain} | {new Date(issue.created_at).toLocaleDateString()}
|
||||
{issue.category} | {new Date(issue.created_at).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,7 +53,7 @@ export default function NewIssue() {
|
||||
try {
|
||||
const issue = await createIssueCmd({ title: title.trim(), domain: selectedDomain, severity });
|
||||
startSession(issue);
|
||||
navigate(`/issue/${issue.id}/triage`);
|
||||
navigate(`/issue/${issue.id}/logs`);
|
||||
} catch (err) {
|
||||
setError(String(err));
|
||||
setIsSubmitting(false);
|
||||
|
||||
97
tests/unit/historyStore.test.ts
Normal file
97
tests/unit/historyStore.test.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { useHistoryStore } from "@/stores/historyStore";
|
||||
import type { IssueSummary } from "@/lib/tauriCommands";
|
||||
|
||||
const mockInvoke = vi.mocked(invoke);
|
||||
|
||||
const makeIssue = (overrides: Partial<IssueSummary> = {}): IssueSummary => ({
|
||||
id: "issue-001",
|
||||
title: "Test issue",
|
||||
severity: "P3",
|
||||
status: "open",
|
||||
category: "linux",
|
||||
log_count: 0,
|
||||
step_count: 0,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe("History Store", () => {
|
||||
beforeEach(() => {
|
||||
useHistoryStore.setState({ issues: [], isLoading: false, error: null, searchQuery: "" });
|
||||
mockInvoke.mockReset();
|
||||
});
|
||||
|
||||
it("loadIssues populates the issues array", async () => {
|
||||
const issues = [makeIssue(), makeIssue({ id: "issue-002", title: "Another issue" })];
|
||||
mockInvoke.mockResolvedValueOnce(issues);
|
||||
|
||||
await useHistoryStore.getState().loadIssues();
|
||||
|
||||
expect(useHistoryStore.getState().issues).toHaveLength(2);
|
||||
expect(useHistoryStore.getState().isLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("loadIssues sets error on failure without clearing existing issues", async () => {
|
||||
const existing = [makeIssue()];
|
||||
useHistoryStore.setState({ issues: existing });
|
||||
mockInvoke.mockRejectedValueOnce(new Error("DB locked"));
|
||||
|
||||
await useHistoryStore.getState().loadIssues();
|
||||
|
||||
expect(useHistoryStore.getState().error).toContain("DB locked");
|
||||
expect(useHistoryStore.getState().isLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("open issue count includes status=open and status=triaging", () => {
|
||||
useHistoryStore.setState({
|
||||
issues: [
|
||||
makeIssue({ status: "open" }),
|
||||
makeIssue({ id: "002", status: "triaging" }),
|
||||
makeIssue({ id: "003", status: "resolved" }),
|
||||
makeIssue({ id: "004", status: "open" }),
|
||||
],
|
||||
});
|
||||
|
||||
const { issues } = useHistoryStore.getState();
|
||||
const openCount = issues.filter(
|
||||
(i) => i.status === "open" || i.status === "triaging"
|
||||
).length;
|
||||
|
||||
expect(openCount).toBe(3);
|
||||
});
|
||||
|
||||
it("newly created issue with status=open is counted as active", () => {
|
||||
useHistoryStore.setState({ issues: [makeIssue({ status: "open" })] });
|
||||
|
||||
const { issues } = useHistoryStore.getState();
|
||||
const openCount = issues.filter(
|
||||
(i) => i.status === "open" || i.status === "triaging"
|
||||
).length;
|
||||
|
||||
expect(openCount).toBe(1);
|
||||
});
|
||||
|
||||
it("resolved issues are not counted as active", () => {
|
||||
useHistoryStore.setState({
|
||||
issues: [makeIssue({ status: "resolved" }), makeIssue({ id: "002", status: "resolved" })],
|
||||
});
|
||||
|
||||
const { issues } = useHistoryStore.getState();
|
||||
const openCount = issues.filter(
|
||||
(i) => i.status === "open" || i.status === "triaging"
|
||||
).length;
|
||||
|
||||
expect(openCount).toBe(0);
|
||||
});
|
||||
|
||||
it("issue category field is present (not domain)", () => {
|
||||
const issue = makeIssue({ category: "kubernetes" });
|
||||
useHistoryStore.setState({ issues: [issue] });
|
||||
|
||||
const stored = useHistoryStore.getState().issues[0];
|
||||
expect(stored.category).toBe("kubernetes");
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user