diff --git a/.changeset/dirpicker-select-created-folder.md b/.changeset/dirpicker-select-created-folder.md index 1fb6ee7d23..efeccc6da2 100644 --- a/.changeset/dirpicker-select-created-folder.md +++ b/.changeset/dirpicker-select-created-folder.md @@ -2,6 +2,6 @@ "@runfusion/fusion": patch --- -summary: Creating a new folder in project setup now selects it fully — the browser panel follows the created folder so Select confirms it. +summary: Creating a folder in project setup now selects it so Select confirms it. category: fix dev: "DirectoryPicker: with selectCreatedDirectory, handleCreateFolder now navigates the browse panel into the created directory instead of refreshing the parent; the footer Select button commits browser.currentPath, so staying on the parent let the next click overwrite the auto-selected new folder." diff --git a/.changeset/git-missing-project-warning.md b/.changeset/git-missing-project-warning.md index a821455382..f9bd5e4f7b 100644 --- a/.changeset/git-missing-project-warning.md +++ b/.changeset/git-missing-project-warning.md @@ -2,6 +2,6 @@ "@runfusion/fusion": minor --- -summary: Project creation now warns up front when Git is missing, with the choice to open the Git downloads or create the project without a git repo. +summary: Project creation warns when Git is missing, with install or create-anyway options. category: feature dev: "SetupWizardModal probes gitCli before registering and shows a three-way ConfirmDialog (create anyway / open downloads / cancel; clone mode offers install-only). New skipGitInit passthrough: ProjectCreateInput → POST /api/projects (rejected for clone mode) → EnsureProjectForPathInput → ensureProjectForPath skips ensureGitRepositoryForProjectPath." diff --git a/.changeset/git-stale-path-recovery.md b/.changeset/git-stale-path-recovery.md index ee386e141c..819547cc18 100644 --- a/.changeset/git-stale-path-recovery.md +++ b/.changeset/git-stale-path-recovery.md @@ -2,6 +2,6 @@ "@runfusion/fusion": patch --- -summary: Git installed while Fusion is running is now detected without a restart — project setup no longer fails with spawn git ENOENT. +summary: Git installed while Fusion runs is detected without restart for project setup. category: fix dev: "New core git-binary resolver: on PATH ENOENT, probes well-known install locations (win32 Program Files/LocalAppData Git\\cmd, macOS homebrew//usr/local//usr/bin, linux /usr/bin//usr/local/bin) with caching + invalidation on later ENOENT. Wired into ensureGitRepositoryForProjectPath's runner, probeGitCliStatus (onboarding git indicator), and the dashboard clone route." diff --git a/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx b/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx index eee64639eb..6f06905d55 100644 --- a/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx +++ b/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx @@ -1596,7 +1596,7 @@ describe("QuickEntryBox", () => { it("clears input after successful creation", async () => { const { props } = renderQuickEntryBox({}); - const textarea = screen.getByTestId("quick-entry-input"); + const textarea = screen.getByTestId("quick-entry-input") as HTMLTextAreaElement; fireEvent.change(textarea, { target: { value: "Task to create" } }); fireEvent.keyDown(textarea, { key: "Enter" }); @@ -1604,8 +1604,12 @@ describe("QuickEntryBox", () => { await waitFor(() => { expect(props.onCreate).toHaveBeenCalled(); }); - - expect((textarea as HTMLTextAreaElement).value).toBe(""); + /* + FNXC:DashboardTests 2026-07-18-07:25: + Full-suite shard load can observe onCreate before the optimistic setDescription("") + commit flushes into the DOM. Wait for the cleared value, not only the mock call. + */ + await waitForSubmitSuccessToClear(textarea); }); it("shows error toast on failure and keeps input content", async () => { @@ -2759,9 +2763,12 @@ describe("QuickEntryBox", () => { it("resets priority to normal after successful task creation", async () => { const { props } = renderQuickEntryBox({}); expandQuickEntry(); - const textarea = screen.getByTestId("quick-entry-input"); + const textarea = screen.getByTestId("quick-entry-input") as HTMLTextAreaElement; fireEvent.change(textarea, { target: { value: "Priority reset after save" } }); + await waitFor(() => { + expect(screen.getByTestId("quick-entry-priority-button")).toBeTruthy(); + }); openPriorityMenu(); fireEvent.click(screen.getByTestId("quick-entry-priority-option-high")); fireEvent.keyDown(textarea, { key: "Enter" }); @@ -2769,9 +2776,12 @@ describe("QuickEntryBox", () => { await waitFor(() => { expect(props.onCreate).toHaveBeenCalledTimes(1); }); + await waitForSubmitSuccessToClear(textarea); expandQuickEntry(); - expectQuickEntryPriorityButton("normal"); + await waitFor(() => { + expectQuickEntryPriorityButton("normal"); + }); }); it("resets priority to normal after Subtask flow", async () => { diff --git a/packages/dashboard/app/components/__tests__/TaskDetailModal.css.test.ts b/packages/dashboard/app/components/__tests__/TaskDetailModal.css.test.ts index 16794af01d..50d58cc200 100644 --- a/packages/dashboard/app/components/__tests__/TaskDetailModal.css.test.ts +++ b/packages/dashboard/app/components/__tests__/TaskDetailModal.css.test.ts @@ -44,6 +44,13 @@ describe("TaskDetailModal CSS contract", () => { expect(planBlock).toContain("max-width: 100%;"); }); + /* + FNXC:TaskDetailActivity 2026-07-18-07:25: + FN-8166 zeroed mobile `.detail-activity` padding-inline-end (equal insets from + `.detail-body`); overlay clearance lives only on first-row selectors. Keep the + contract aligned with TaskDetailModal.css so full-suite does not assert the + pre-8166 `var(--space-md)` residual inset. + */ it("FN-8154 keeps the mobile Feed inset narrow while clearing its overlay toggle from first rows", async () => { const css = await loadAllAppCss(); const baseCss = await loadAllAppCssBaseOnly(); @@ -57,8 +64,9 @@ describe("TaskDetailModal CSS contract", () => { ]; expect(baseCss).toContain(".detail-activity {\n position: relative;\n padding-inline-end: calc(var(--space-2xl) + var(--space-md));\n}"); - expect(mobileCss).toContain(" .detail-activity {\n padding-inline-end: var(--space-md);\n }"); + expect(mobileCss).toContain(" .detail-activity {\n padding-inline-end: 0;\n }"); expect(mobileCss).not.toContain(" .detail-activity {\n padding-inline-end: calc(var(--space-2xl) + var(--space-lg));\n }"); + expect(mobileCss).not.toContain(" .detail-activity {\n padding-inline-end: var(--space-md);\n }"); expect(mobileCss).toContain(" .detail-activity--interventions {\n padding-inline-end: 0;\n }"); for (const selector of firstRowSelectors) { const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); diff --git a/plugins/fusion-plugin-grok-runtime/src/__tests__/process-lifecycle.test.ts b/plugins/fusion-plugin-grok-runtime/src/__tests__/process-lifecycle.test.ts index c1a84db5e8..4ac15f874a 100644 --- a/plugins/fusion-plugin-grok-runtime/src/__tests__/process-lifecycle.test.ts +++ b/plugins/fusion-plugin-grok-runtime/src/__tests__/process-lifecycle.test.ts @@ -15,10 +15,11 @@ describe("Grok plugin process lifecycle", () => { }); /* - FNXC:GrokRuntimeTests 2026-07-18-07:15: - Bound is proven by a few re-evaluations (Symbol.for exit-hook guard). Full-suite - shard load made 15 dynamic imports hit the default 5s testTimeout (transform-heavy - plugin graph), not a product hang — keep the assertion, reduce iterations. + FNXC:GrokRuntimeTests 2026-07-18-07:25: + Symbol.for exit-hook guard is proven by two re-evaluations after the baseline + import. Full-suite shard transform load made 5–15 dynamic imports of the full + plugin graph hit the default 5s testTimeout; keep the bound assertion, not the + iteration marathon. */ it("keeps its process cleanup owner bounded across repeated module evaluation", async () => { const baseline = listenerCounts(); @@ -27,7 +28,7 @@ describe("Grok plugin process lifecycle", () => { process.on("warning", onWarning); try { - for (let iteration = 0; iteration < 5; iteration += 1) { + for (let iteration = 0; iteration < 2; iteration += 1) { vi.resetModules(); await import("../index.js"); }