feat: release toolbox portal 0.1.0
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
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 an internal app 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(1);
|
||||
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/zemion/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',
|
||||
]);
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user