Files
toolbox-portal/src/catalogue.test.ts
T

110 lines
3.2 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest';
import { contextualLaunchUrl, loadCatalogue } from './catalogue';
import { catalogue, catalogueFetch } from './test/fixtures';
afterEach(() => vi.unstubAllGlobals());
describe('catalogue loading', () => {
it('loads and resolves internal apps using the shared contract', async () => {
vi.stubGlobal('fetch', vi.fn(catalogueFetch()));
const loaded = await loadCatalogue('/toolbox.catalog.json');
expect(loaded.catalogue.name).toBe('add·ideas Toolbox');
expect(loaded.homeUrl).toBe('http://localhost:3000/');
expect(loaded.apps).toHaveLength(8);
expect(loaded.apps[0]).toMatchObject({
id: 'de.add-ideas.pdf-tools',
name: 'PDF Workbench',
entryUrl: 'http://localhost:3000/apps/pdf/',
sourceUrl: 'https://git.add-ideas.de/lotobo/pdf-tools',
});
});
it('keeps valid apps available when another manifest fails', async () => {
const twoApps = {
...catalogue,
apps: [
...catalogue.apps,
{ manifest: './apps/missing/toolbox-app.json', enabled: true },
],
};
vi.stubGlobal(
'fetch',
vi.fn(
catalogueFetch({
'/toolbox.catalog.json': Response.json(twoApps),
})
)
);
const loaded = await loadCatalogue('/toolbox.catalog.json');
expect(loaded.apps.map((app) => app.id)).toEqual([
'de.add-ideas.pdf-tools',
'de.add-ideas.xslt-tools',
'de.add-ideas.onenote-tools',
'de.add-ideas.svg-tools',
'de.add-ideas.auth-tools',
'de.add-ideas.sudoku-tools',
'de.add-ideas.colour-tools',
'de.add-ideas.office-tools',
]);
expect(loaded.unavailable).toHaveLength(1);
expect(loaded.unavailable[0]?.reason).toMatch(/HTTP 404/);
});
it('rejects cross-origin manifest references', async () => {
vi.stubGlobal(
'fetch',
vi.fn(
catalogueFetch({
'/toolbox.catalog.json': Response.json({
...catalogue,
apps: [
{
manifest: 'https://example.invalid/toolbox-app.json',
enabled: true,
},
],
}),
})
)
);
await expect(loadCatalogue('/toolbox.catalog.json')).rejects.toThrow(
/share the page origin/i
);
});
it('rejects a cross-origin catalogue home', async () => {
vi.stubGlobal(
'fetch',
vi.fn(
catalogueFetch({
'/toolbox.catalog.json': Response.json({
...catalogue,
home: 'https://example.invalid/',
}),
})
)
);
await expect(loadCatalogue('/toolbox.catalog.json')).rejects.toThrow(
/share the page origin/i
);
});
it('adds catalogue context only to same-origin launch links', () => {
const contextual = new URL(
contextualLaunchUrl(
'http://localhost:3000/apps/pdf/',
'http://localhost:3000/toolbox.catalog.json'
)
);
expect(contextual.searchParams.get('toolbox')).toBe(
'http://localhost:3000/toolbox.catalog.json'
);
expect(
contextualLaunchUrl(
'https://example.com/tool',
'http://localhost:3000/toolbox.catalog.json'
)
).toBe('https://example.com/tool');
});
});