Files
qwen-code/packages/web-shell/client/utils/sessionPath.test.ts
Lilian0122and铃蓝 43868d6a69 feat(web-shell): add shared URL navigation for pages and sessions (#12499)
* feat(web-shell): add shared URL navigation for pages and sessions

* test(web-shell): expect settings route after remote connection return

* fix(web-shell): preserve navigation state across workspace flows

---------

Co-authored-by: 铃蓝 <[email protected]>
2026-09-23 09:43:09 +00:00

111 lines
3.5 KiB
TypeScript

/**
* @license
* Copyright 2026 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, expect, it } from 'vitest';
import { buildSessionPathname, parseSessionId } from './sessionPath';
describe('buildSessionPathname', () => {
it('replaces an existing session segment at the root', () => {
expect(buildSessionPathname('/session/old', 'new')).toBe('/session/new');
});
it('preserves a sub-path deployment base', () => {
expect(buildSessionPathname('/app/session/old', 'new')).toBe(
'/app/session/new',
);
});
it('appends a session under a base path with no existing session', () => {
expect(buildSessionPathname('/app', 'new')).toBe('/app/session/new');
});
it('appends a session at the root when there is no existing session', () => {
expect(buildSessionPathname('/', 'new')).toBe('/session/new');
});
it('strips a trailing slash from the base path', () => {
expect(buildSessionPathname('/app/', 'new')).toBe('/app/session/new');
});
it('strips a trailing slash after an existing session id', () => {
expect(buildSessionPathname('/session/old/', 'new')).toBe('/session/new');
expect(buildSessionPathname('/app/session/old/', 'new')).toBe(
'/app/session/new',
);
});
it('encodes the session id', () => {
expect(buildSessionPathname('/', 'a b/c')).toBe('/session/a%20b%2Fc');
});
it('returns the base path when no session is given', () => {
expect(buildSessionPathname('/app/session/old', undefined)).toBe('/app');
});
it('returns "/" when no session is given at the root', () => {
expect(buildSessionPathname('/', undefined)).toBe('/');
expect(buildSessionPathname('/session/old', undefined)).toBe('/');
});
});
describe('parseSessionId', () => {
it('reads the session id at the root', () => {
expect(parseSessionId('/session/abc')).toBe('abc');
});
it('reads the last session segment under a base path', () => {
expect(parseSessionId('/app/session/abc')).toBe('abc');
});
it('ignores a trailing slash', () => {
expect(parseSessionId('/session/abc/')).toBe('abc');
});
it('decodes the session id', () => {
expect(parseSessionId('/session/a%20b%2Fc')).toBe('a b/c');
});
it('returns undefined for malformed percent-encoding', () => {
expect(parseSessionId('/session/%E0%A4%A')).toBeUndefined();
});
it('returns undefined when there is no session segment', () => {
expect(parseSessionId('/')).toBeUndefined();
expect(parseSessionId('/app')).toBeUndefined();
});
it('returns undefined for an empty session id', () => {
expect(parseSessionId('/app/session/')).toBeUndefined();
});
});
describe('build/parse round-trip', () => {
it('reads back the written session id', () => {
for (const base of ['/', '/app', '/app/', '/app/session/old']) {
expect(parseSessionId(buildSessionPathname(base, 'real-id'))).toBe(
'real-id',
);
}
});
it('reads back the written id when the base path ends in a session segment', () => {
const pathname = buildSessionPathname('/app/session/', 'real-id');
expect(parseSessionId(pathname)).toBe('real-id');
});
});
describe('page route base compatibility', () => {
it.each(['plugins', 'channels', 'scheduled-tasks', 'goals', 'settings'])(
'keeps page %s alongside sessions when building links',
(page) => {
expect(buildSessionPathname(`/agentic-code/${page}`, 'next')).toBe(
'/agentic-code/session/next',
);
expect(buildSessionPathname(`/${page}`, undefined)).toBe('/');
},
);
});