generated from nhcarrigan/template
feat: productivity suite — task loop, workflow, theming, docs & more (#197)
## Summary A large productivity-focused feature branch delivering a suite of improvements across automation, project management, theming, performance, and documentation. ### Features - **Guided Project Workflow** (#189) — Four-phase workflow panel (Discuss → Plan → Execute → Verify) to keep projects structured from idea to completion - **Automated Task Loop** (#179) — Per-task conversation orchestration with wave-based parallel execution, blocked-task detection, and concurrency control - **Wave-Based Parallel Execution** (#191) — Tasks run in dependency-aware waves with configurable concurrency; independent tasks execute in parallel - **Auto-Commit After Task Completion** (#192) — Task Loop optionally commits after each completed task so progress is never lost - **PRD Creator** (#180) — AI-assisted PRD and task list panel that outputs `hikari-tasks.json` for the Task Loop to consume - **Project Context Panel** (#188) — Persistent `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` files injected into Claude's context automatically - **Codebase Mapper** (#190) — Generates a `CODEBASE.md` architectural summary so Claude always understands the project structure - **Community Preset Themes** (#181) — Six built-in community themes: Dracula, Catppuccin Mocha, Nord, Solarized Dark, Gruvbox Dark, and Rosé Pine - **In-App Changelog Panel** (#193) — Fetches release notes from GitHub at runtime and displays them inside the app - **Full Embedded Documentation** (#196) — Replaced the single-page help modal with a 12-page paginated docs browser featuring a sidebar TOC, prev/next navigation, keyboard navigation (arrow keys, `?` shortcut), and comprehensive coverage of every feature ### Performance & Fixes - **Lazy Loading & Virtualisation** (#194) — Virtual windowing for conversation history, markdown memoisation, and debounced search for smooth rendering of large sessions - **Ctrl+C Copy Fix** (#195) — `Ctrl+C` now copies selected text as expected; interrupt-Claude behaviour only fires when no text is selected ### UX - Back-to-workflow button in PRD Creator and Task Loop panels for easy navigation - Navigation icon cluster replaced with a single clean dropdown menu ## Closes Closes #179 Closes #180 Closes #181 Closes #188 Closes #189 Closes #190 Closes #191 Closes #192 Closes #193 Closes #194 Closes #195 Closes #196 --- ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #197 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #197.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* ChangelogPanel Component Tests
|
||||
*
|
||||
* Tests the pure helper function exported by ChangelogPanel for formatting
|
||||
* ISO 8601 date strings into human-readable release dates.
|
||||
*
|
||||
* What this component does:
|
||||
* - Opens as a modal dialog from the nav menu
|
||||
* - Fetches all releases via the `fetch_changelog` Tauri IPC command on mount
|
||||
* - Shows a loading spinner while fetching
|
||||
* - Renders each release with version badge, date, pre-release badge, and notes
|
||||
* - Highlights the currently installed version with a pink "current" badge
|
||||
* - Provides a "View on Gitea" link per release
|
||||
* - Shows an error state with a Retry button if the fetch fails
|
||||
*
|
||||
* Manual testing checklist:
|
||||
* - [ ] Changelog item appears in the nav dropdown
|
||||
* - [ ] Clicking opens the panel with a loading spinner
|
||||
* - [ ] Spinner resolves to a list of releases
|
||||
* - [ ] Current version entry shows pink version text + "current" badge
|
||||
* - [ ] Pre-release entries show a yellow "pre-release" badge
|
||||
* - [ ] "View on Gitea" opens the release URL in the browser
|
||||
* - [ ] Backdrop click and Escape key close the panel
|
||||
* - [ ] Network error shows a red error message and a Retry button
|
||||
* - [ ] Retry button re-fetches the changelog
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
function formatReleaseDate(isoString: string): string {
|
||||
if (!isoString) return "Unknown date";
|
||||
const date = new Date(isoString);
|
||||
if (isNaN(date.getTime())) return "Unknown date";
|
||||
return date.toLocaleDateString("en-GB", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
timeZone: "UTC",
|
||||
});
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
describe("formatReleaseDate", () => {
|
||||
it("formats a valid ISO 8601 timestamp to en-GB locale", () => {
|
||||
const result = formatReleaseDate("2026-02-25T00:00:00Z");
|
||||
// en-GB format: "25 February 2026"
|
||||
expect(result).toBe("25 February 2026");
|
||||
});
|
||||
|
||||
it("returns 'Unknown date' for an empty string", () => {
|
||||
expect(formatReleaseDate("")).toBe("Unknown date");
|
||||
});
|
||||
|
||||
it("returns 'Unknown date' for a non-date string", () => {
|
||||
expect(formatReleaseDate("not-a-date")).toBe("Unknown date");
|
||||
});
|
||||
|
||||
it("handles a timestamp with a time component", () => {
|
||||
const result = formatReleaseDate("2025-12-01T14:32:00Z");
|
||||
expect(result).toBe("1 December 2025");
|
||||
});
|
||||
|
||||
it("formats a single-digit day without leading zero in en-GB", () => {
|
||||
const result = formatReleaseDate("2026-03-06T00:00:00Z");
|
||||
expect(result).toBe("6 March 2026");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user