Files
renovate/lib/modules/datasource/jsr/index.spec.ts
Sebastian Poxhofer e01b50c6ab refactor(linter): oxlint prefer partial typed casts for consts (#45239)
* refactor: flag all typed object literal casts in prefer-partial-in-specs

* refactor: type maven spec httpError helper against got response shape
2026-08-12 08:50:57 +00:00

131 lines
3.9 KiB
TypeScript

import { partial } from '~test/util.ts';
import * as httpMock from '../../../../test/http-mock.ts';
import type { Timestamp } from '../../../util/timestamp.ts';
import { JsrDatasource } from './index.ts';
import { MINIMUM_RELEASE_TIMESTAMP } from './schema.ts';
interface JsrPackageMetadataResponse {
latest: string;
versions: Record<string, { createdAt?: string; yanked?: boolean }>;
}
const jsrPackageMetadataResponse = partial<JsrPackageMetadataResponse>({
latest: '0.0.2',
versions: {
// Mixed createdAt fields for testing:
// Actually, it's either all there or none.
// has no createdAt (should use fallback MINIMUM_RELEASE_TIMESTAMP)
'0.0.1': {},
// has explicit createdAt (should use actual timestamp)
'0.0.2': { createdAt: '2025-11-15T00:00:00.000Z' },
},
});
describe('modules/datasource/jsr/index', () => {
const jsr = new JsrDatasource();
it('should return null for invalid package name', async () => {
const res = await jsr.getReleases({
packageName: 'invalid',
registryUrl: jsr.defaultRegistryUrls[0],
});
expect(res).toBeNull();
});
it('should return null for no versions', async () => {
const missingVersions = { ...jsrPackageMetadataResponse };
missingVersions.versions = {};
httpMock
.scope(jsr.defaultRegistryUrls[0])
.get('/@scope/package-name/meta.json')
.reply(200, missingVersions);
const res = await jsr.getReleases({
packageName: '@scope/package-name',
registryUrl: jsr.defaultRegistryUrls[0],
});
expect(res).toBeNull();
});
it('should fetch package info from jsr', async () => {
httpMock
.scope(jsr.defaultRegistryUrls[0])
.get('/@scope/package-name/meta.json')
.reply(200, jsrPackageMetadataResponse, {
'Cache-control': 'public, expires=300',
});
const res = await jsr.getReleases({
packageName: '@scope/package-name',
registryUrl: jsr.defaultRegistryUrls[0],
});
expect(res).toMatchObject({
homepage: 'https://jsr.io/@scope/package-name',
registryUrl: 'https://jsr.io/',
releases: [
{
version: '0.0.1',
releaseTimestamp: MINIMUM_RELEASE_TIMESTAMP,
},
{
isLatest: true,
version: '0.0.2',
releaseTimestamp: '2025-11-15T00:00:00.000Z' as Timestamp,
},
],
});
});
it('contains yanked versions', async () => {
jsrPackageMetadataResponse.versions['0.0.1'].yanked = true;
httpMock
.scope(jsr.defaultRegistryUrls[0])
.get('/@scope/package-name/meta.json')
.reply(200, jsrPackageMetadataResponse);
const res = await jsr.getReleases({
packageName: '@scope/package-name',
registryUrl: jsr.defaultRegistryUrls[0],
});
expect(res).toMatchObject({
homepage: 'https://jsr.io/@scope/package-name',
registryUrl: 'https://jsr.io/',
releases: [
{
isDeprecated: true,
version: '0.0.1',
releaseTimestamp: MINIMUM_RELEASE_TIMESTAMP,
},
{
isLatest: true,
version: '0.0.2',
releaseTimestamp: '2025-11-15T00:00:00.000Z' as Timestamp,
},
],
});
});
it('should return null if lookup fails', async () => {
httpMock
.scope(jsr.defaultRegistryUrls[0])
.get('/@scope/package-name/meta.json')
.reply(404);
await expect(
jsr.getReleases({
packageName: '@scope/package-name',
registryUrl: jsr.defaultRegistryUrls[0],
}),
).rejects.toThrow('Request failed with status code 404 (Not Found)');
});
it('should throw error for unparseable', async () => {
httpMock
.scope(jsr.defaultRegistryUrls[0])
.get('/@scope/package-name/meta.json')
.reply(200, 'oops');
await expect(
jsr.getReleases({
packageName: '@scope/package-name',
registryUrl: jsr.defaultRegistryUrls[0],
}),
).rejects.toThrow('Unexpected token \'o\', "oops" is not valid JSON');
});
});