Files
appstore/test/test.node.ts
T

132 lines
3.9 KiB
TypeScript

import { tap, expect } from '@git.zone/tstest/tapbundle';
import {
AppStoreResolver,
parseDockerImageReference,
parseServezoneAppStoreManifest,
} from '../ts_client/index.js';
tap.test('parses docker image references', async () => {
expect(parseDockerImageReference('nginx:alpine')).toEqual({
registry: 'registry-1.docker.io',
repository: 'library/nginx',
tag: 'alpine',
digest: undefined,
});
expect(parseDockerImageReference('code.foss.global/serve.zone/cloudly:latest')).toEqual({
registry: 'code.foss.global',
repository: 'serve.zone/cloudly',
tag: 'latest',
digest: undefined,
});
});
tap.test('validates servezone appstore manifests', async () => {
const manifest = parseServezoneAppStoreManifest({
schemaVersion: 1,
app: {
id: 'cloudly',
name: 'Cloudly',
description: 'Control plane',
category: 'Dev Tools',
},
runtime: {
image: 'code.foss.global/serve.zone/cloudly:latest',
port: 80,
},
});
expect(manifest.app.id).toEqual('cloudly');
});
tap.test('resolves repo manifests and digest tracked images', async () => {
const baseUrl = 'https://appstore.example.test';
const manifestUrl = 'https://code.example.test/cloudly/servezone.appstore.json';
const digest = 'sha256:1234567890abcdef';
const fakeFetch: typeof fetch = async (inputArg, initArg) => {
const url = inputArg instanceof Request ? inputArg.url : inputArg.toString();
const method = initArg?.method || 'GET';
if (url === `${baseUrl}/appstore.resolved.json`) {
return new Response('not found', { status: 404 });
}
if (url === `${baseUrl}/appstore.json`) {
return Response.json({
schemaVersion: 1,
updatedAt: '2026-05-25T00:00:00Z',
apps: [
{
id: 'cloudly',
name: 'Cloudly',
description: 'Curated listing metadata.',
category: 'Dev Tools',
latestVersion: 'latest',
source: {
type: 'repoManifest',
url: manifestUrl,
ref: 'main',
},
},
],
});
}
if (url === manifestUrl) {
return Response.json({
schemaVersion: 1,
app: {
id: 'cloudly',
name: 'Cloudly',
description: 'Manifest-owned metadata.',
category: 'Dev Tools',
},
latestVersion: 'latest',
source: {
type: 'dockerImage',
image: 'registry.example.test/serve.zone/cloudly:latest',
tracking: 'digest',
},
runtime: {
image: 'registry.example.test/serve.zone/cloudly:latest',
port: 80,
},
});
}
if (
url === 'https://registry.example.test/v2/serve.zone/cloudly/manifests/latest' &&
method === 'HEAD'
) {
return new Response(null, {
status: 200,
headers: { 'docker-content-digest': digest },
});
}
return new Response(`unexpected ${method} ${url}`, { status: 500 });
};
const resolver = new AppStoreResolver({
baseUrl,
fetch: fakeFetch,
now: () => new Date('2026-05-25T12:00:00Z'),
});
const appStore = await resolver.getAppStoreIndex();
expect(appStore.apps[0].latestVersion).toEqual(`latest@${digest}`);
expect(appStore.apps[0].resolvedSource?.manifestHash?.length).toEqual(64);
expect(appStore.apps[0].upgradeStrategy).toEqual('dockerDigest');
const appMeta = await resolver.getAppMeta('cloudly');
expect(appMeta.latestVersion).toEqual(`latest@${digest}`);
expect(appMeta.versions).toEqual([`latest@${digest}`]);
const config = await resolver.getAppVersionConfig('cloudly', appMeta.latestVersion);
expect(config.image).toEqual('registry.example.test/serve.zone/cloudly:latest');
expect(config.appStoreVersion).toEqual(`latest@${digest}`);
expect(config.resolvedImageDigest).toEqual(digest);
});
export default tap.start();