mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-20 07:13:05 +00:00
fix(routing): basename env URLs and defer writes during node hydration (#1598)
* fix(routing): basename env URLs and defer writes during node hydration Encode only env file basenames in ?env= and omit the default file. Resolve legacy absolute-path bookmarks on load. Block history writes until the active node matches a cold-loaded remote deep link. * fix(routing): restore env deep links after stack load hydrates file list Defer env selection until envFiles is populated after loadFileForRoute. Apply default env when the URL omits ?env= (Back/popstate). Document env URL rules and legacy basename resolution in deep-links.mdx.
This commit is contained in:
@@ -97,6 +97,79 @@ describe('useUrlSync', () => {
|
||||
expect(window.location.pathname).toBe('/nodes/local/security');
|
||||
});
|
||||
|
||||
it('does not write local node URL while hydrating a remote node deep link', () => {
|
||||
const remote = makeNode({ id: 2, name: 'nas', type: 'remote', is_default: false });
|
||||
const local = makeNode();
|
||||
const setActiveNode = vi.fn();
|
||||
const pushSpy = vi.spyOn(window.history, 'pushState');
|
||||
|
||||
window.history.replaceState({ senchoIdx: 0 }, '', '/nodes/nas-2/fleet/snapshots');
|
||||
|
||||
act(() => {
|
||||
renderHook(
|
||||
(props) => useUrlSync(props),
|
||||
{
|
||||
initialProps: makeOpts({
|
||||
nodes: [local, remote],
|
||||
activeNode: local,
|
||||
activeView: 'fleet',
|
||||
fleetActiveTab: 'snapshots',
|
||||
setActiveNode,
|
||||
}),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const badPush = pushSpy.mock.calls.find((call) => String(call[2]).includes('/nodes/local/'));
|
||||
expect(badPush).toBeUndefined();
|
||||
expect(setActiveNode).toHaveBeenCalledWith(remote);
|
||||
|
||||
pushSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('restores non-default env selection after stack load populates file list', async () => {
|
||||
const prodPath = '/compose/radarr/.env.prod';
|
||||
const fileList = ['/compose/radarr/.env', prodPath];
|
||||
const loadFileForRoute = vi.fn().mockResolvedValue(true);
|
||||
const changeEnvFile = vi.fn().mockResolvedValue(undefined);
|
||||
|
||||
window.history.replaceState({ senchoIdx: 0 }, '', '/nodes/local/stacks/radarr/env?env=.env.prod');
|
||||
|
||||
const { rerender } = renderHook(
|
||||
(props) => useUrlSync(props),
|
||||
{
|
||||
initialProps: makeOpts({
|
||||
activeView: 'editor',
|
||||
files: ['radarr'],
|
||||
selectedFile: null,
|
||||
envFiles: [],
|
||||
loadFileForRoute,
|
||||
changeEnvFile,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
});
|
||||
expect(loadFileForRoute).toHaveBeenCalledWith('radarr');
|
||||
|
||||
rerender(makeOpts({
|
||||
activeView: 'editor',
|
||||
files: ['radarr'],
|
||||
selectedFile: 'radarr',
|
||||
envFiles: fileList,
|
||||
loadFileForRoute,
|
||||
changeEnvFile,
|
||||
}));
|
||||
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(changeEnvFile).toHaveBeenCalledWith(prodPath);
|
||||
});
|
||||
|
||||
it('pushState increments senchoIdx on user navigation', () => {
|
||||
const pushSpy = vi.spyOn(window.history, 'pushState');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user