feat(FN-2611): merge fusion/fn-2611 (auto-resolved)
- feat(FN-2611): complete Step 4 — add changeset and docs - test(FN-2611): complete Step 2 — cover legacy alias cleanup payload - feat(FN-2611): complete Step 1 — normalize legacy experimental aliases
This commit is contained in:
5
.changeset/fix-dev-server-experimental-toggle.md
Normal file
5
.changeset/fix-dev-server-experimental-toggle.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Fix experimental feature save normalization so disabling Dev Server clears the legacy `devServer` alias (`null` delete) alongside canonical `devServerView`, preventing stale nav visibility after save.
|
||||
@@ -126,16 +126,22 @@ function isExperimentalFeatureEnabled(features: Record<string, boolean>, key: st
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeExperimentalFeaturesForSave(features?: Record<string, boolean>): Record<string, boolean> {
|
||||
function normalizeExperimentalFeaturesForSave(features?: Record<string, boolean>): Record<string, boolean | null> {
|
||||
if (!features) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const normalized: Record<string, boolean> = {};
|
||||
const normalized: Record<string, boolean | null> = {};
|
||||
for (const [key, enabled] of Object.entries(features)) {
|
||||
normalized[getCanonicalExperimentalFeatureKey(key)] = enabled;
|
||||
}
|
||||
|
||||
for (const [legacyKey, canonicalKey] of Object.entries(EXPERIMENTAL_FEATURE_LEGACY_ALIASES)) {
|
||||
if (normalized[canonicalKey] !== undefined && !(legacyKey in normalized)) {
|
||||
normalized[legacyKey] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
|
||||
@@ -1191,7 +1191,7 @@ describe("SettingsModal", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes legacy devServer flag to canonical devServerView on save", async () => {
|
||||
it("sends canonical devServerView=false and devServer=null when disabling legacy dev server flag", async () => {
|
||||
mockFetchSettings.mockResolvedValue({
|
||||
...defaultSettings,
|
||||
experimentalFeatures: { devServer: true },
|
||||
@@ -1204,6 +1204,9 @@ describe("SettingsModal", () => {
|
||||
const devServerToggle = screen.getByLabelText("Dev Server") as HTMLInputElement;
|
||||
expect(devServerToggle).toBeChecked();
|
||||
|
||||
await userEvent.click(devServerToggle);
|
||||
expect(devServerToggle).not.toBeChecked();
|
||||
|
||||
await userEvent.click(screen.getByText("Save"));
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -1211,7 +1214,27 @@ describe("SettingsModal", () => {
|
||||
});
|
||||
|
||||
const payload = mockUpdateSettings.mock.calls[0][0];
|
||||
expect(payload.experimentalFeatures).toEqual({ devServerView: true });
|
||||
expect(payload.experimentalFeatures).toEqual({ devServerView: false, devServer: null });
|
||||
});
|
||||
|
||||
it("does not emit legacy alias null deletes when canonical key is absent", async () => {
|
||||
mockFetchSettings.mockResolvedValue({
|
||||
...defaultSettings,
|
||||
experimentalFeatures: { insights: true },
|
||||
});
|
||||
|
||||
renderModal();
|
||||
|
||||
await openExperimentalFeaturesSection();
|
||||
|
||||
await userEvent.click(screen.getByText("Save"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdateSettings).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
const payload = mockUpdateSettings.mock.calls[0][0];
|
||||
expect(payload.experimentalFeatures).toEqual({ insights: true });
|
||||
expect(payload.experimentalFeatures.devServer).toBeUndefined();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user