mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-31 17:51:49 +00:00
669 lines
17 KiB
TypeScript
669 lines
17 KiB
TypeScript
import {
|
|
CompilerOptionsJsxImportSource,
|
|
CompilerOptionsJsxImportSourceTypes,
|
|
CompilerOptionsTypes,
|
|
DenoDependency,
|
|
DenoExtract,
|
|
DenoLock,
|
|
ImportMapExtract,
|
|
Imports,
|
|
Lint,
|
|
Lock,
|
|
Scopes,
|
|
Tasks,
|
|
UpdateDenoJsonFile,
|
|
UpdateImportMapJsonFile,
|
|
Workspace,
|
|
} from './schema.ts';
|
|
|
|
describe('modules/manager/deno/schema', () => {
|
|
describe('DenoLock', () => {
|
|
it('parses lock file with specifiers', () => {
|
|
expect(
|
|
DenoLock.parse(
|
|
JSON.stringify({
|
|
version: '5',
|
|
specifiers: {
|
|
'jsr:@scope/package': '1.0.0_other@2.0.0',
|
|
},
|
|
redirects: {},
|
|
remote: {},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
lockedVersions: {
|
|
'jsr:@scope/package': '1.0.0',
|
|
},
|
|
redirectVersions: {},
|
|
remoteVersions: new Set(),
|
|
lockfileVersion: 5,
|
|
});
|
|
});
|
|
|
|
it('parses lock file with specifiers that do not match regex', () => {
|
|
expect(
|
|
DenoLock.parse(
|
|
JSON.stringify({
|
|
version: '5',
|
|
specifiers: {
|
|
valid_key: '_startswith_underscore',
|
|
},
|
|
redirects: {},
|
|
remote: {},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
lockedVersions: {},
|
|
redirectVersions: {},
|
|
remoteVersions: new Set(),
|
|
lockfileVersion: 5,
|
|
});
|
|
});
|
|
|
|
it('parses lock file with redirects', () => {
|
|
expect(
|
|
DenoLock.parse(
|
|
JSON.stringify({
|
|
version: '5',
|
|
specifiers: {},
|
|
redirects: {
|
|
'https://example.com/old': 'https://example.com/new',
|
|
},
|
|
remote: {},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
lockedVersions: {},
|
|
redirectVersions: {
|
|
'https://example.com/old': 'https://example.com/new',
|
|
},
|
|
remoteVersions: new Set(),
|
|
lockfileVersion: 5,
|
|
});
|
|
});
|
|
|
|
it('parses lock file with remote entries', () => {
|
|
expect(
|
|
DenoLock.parse(
|
|
JSON.stringify({
|
|
version: '5',
|
|
specifiers: {},
|
|
redirects: {},
|
|
remote: {
|
|
'https://example.com/module.ts': 'sha256-hash',
|
|
},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
lockedVersions: {},
|
|
redirectVersions: {},
|
|
remoteVersions: new Set(['https://example.com/module.ts']),
|
|
lockfileVersion: 5,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Lock', () => {
|
|
it('parses lock as string', () => {
|
|
expect(Lock.parse('deno.lock')).toEqual('deno.lock');
|
|
});
|
|
|
|
it('parses lock as object', () => {
|
|
expect(Lock.parse({ path: 'genuine-deno.lock' })).toEqual(
|
|
'genuine-deno.lock',
|
|
);
|
|
});
|
|
|
|
it('parses lock as boolean true', () => {
|
|
expect(Lock.parse(true)).toEqual('deno.lock');
|
|
});
|
|
|
|
it('parses lock as boolean false', () => {
|
|
expect(Lock.parse(false)).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('Imports', () => {
|
|
it('parses default values', () => {
|
|
expect(Imports.parse({})).toEqual([]);
|
|
});
|
|
|
|
it('parses imports', () => {
|
|
expect(
|
|
Imports.parse({
|
|
dep1: 'jsr:@scope/package-name@^1.0.0',
|
|
}),
|
|
).toEqual([
|
|
{
|
|
currentRawValue: 'jsr:@scope/package-name@^1.0.0',
|
|
currentValue: '^1.0.0',
|
|
datasource: 'jsr',
|
|
depName: '@scope/package-name',
|
|
depType: 'imports',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('scopes', () => {
|
|
it('parses default values', () => {
|
|
expect(Scopes.parse({})).toEqual([]);
|
|
});
|
|
|
|
it('parses scopes', () => {
|
|
expect(
|
|
Scopes.parse({
|
|
'/scope': {
|
|
dep1: 'jsr:@scope/package-name@^1.0.0',
|
|
},
|
|
}),
|
|
).toEqual([
|
|
{
|
|
currentRawValue: 'jsr:@scope/package-name@^1.0.0',
|
|
currentValue: '^1.0.0',
|
|
datasource: 'jsr',
|
|
depName: '@scope/package-name',
|
|
depType: 'scopes',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('Tasks', () => {
|
|
it('parses default values', () => {
|
|
expect(Tasks.parse({})).toEqual([]);
|
|
});
|
|
|
|
it('parses tasks', () => {
|
|
expect(
|
|
Tasks.parse({
|
|
task1: 'deno run jsr:@scope/package-name@^1.0.0',
|
|
}),
|
|
).toEqual([
|
|
{
|
|
currentRawValue: 'jsr:@scope/package-name@^1.0.0',
|
|
currentValue: '^1.0.0',
|
|
datasource: 'jsr',
|
|
depName: '@scope/package-name',
|
|
depType: 'tasks',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('parses tasks.command', () => {
|
|
expect(
|
|
Tasks.parse({
|
|
task1: {
|
|
command: 'deno run npm:dep1',
|
|
},
|
|
}),
|
|
).toEqual([
|
|
{
|
|
currentRawValue: 'npm:dep1',
|
|
currentValue: undefined,
|
|
datasource: 'npm',
|
|
depName: 'dep1',
|
|
depType: 'tasks.command',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('CompilerOptionsTypes', () => {
|
|
it('parses compilerOptions.types', () => {
|
|
expect(CompilerOptionsTypes.parse(['npm:@types/dep1'])).toEqual([
|
|
{
|
|
currentRawValue: 'npm:@types/dep1',
|
|
currentValue: undefined,
|
|
datasource: 'npm',
|
|
depName: '@types/dep1',
|
|
depType: 'compilerOptions.types',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('CompilerOptionsJsxImportSource', () => {
|
|
it('parses compilerOptions.jsxImportSource', () => {
|
|
expect(CompilerOptionsJsxImportSource.parse('npm:dep1')).toEqual([
|
|
{
|
|
currentRawValue: 'npm:dep1',
|
|
currentValue: undefined,
|
|
datasource: 'npm',
|
|
depName: 'dep1',
|
|
depType: 'compilerOptions.jsxImportSource',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('parses undefined compilerOptions.jsxImportSource', () => {
|
|
expect(CompilerOptionsJsxImportSource.parse(undefined)).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('CompilerOptionsJsxImportSourceTypes', () => {
|
|
it('parses compilerOptions.jsxImportSourceTypes', () => {
|
|
expect(
|
|
CompilerOptionsJsxImportSourceTypes.parse('npm:@types/dep1'),
|
|
).toEqual([
|
|
{
|
|
currentRawValue: 'npm:@types/dep1',
|
|
currentValue: undefined,
|
|
datasource: 'npm',
|
|
depName: '@types/dep1',
|
|
depType: 'compilerOptions.jsxImportSourceTypes',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('parses undefined compilerOptions.jsxImportSourceTypes', () => {
|
|
expect(CompilerOptionsJsxImportSourceTypes.parse(undefined)).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('Lint', () => {
|
|
it('parses default values', () => {
|
|
expect(Lint.parse({})).toEqual([]);
|
|
});
|
|
|
|
it('parses lint.plugins', () => {
|
|
expect(
|
|
Lint.parse({
|
|
plugins: ['npm:dep1'],
|
|
}),
|
|
).toEqual([
|
|
{
|
|
currentRawValue: 'npm:dep1',
|
|
currentValue: undefined,
|
|
datasource: 'npm',
|
|
depName: 'dep1',
|
|
depType: 'lint.plugins',
|
|
versioning: 'deno',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('Workspace', () => {
|
|
it('parses workspace array', () => {
|
|
expect(Workspace.parse(['packages/*', 'libs/*'])).toEqual([
|
|
'packages/*',
|
|
'libs/*',
|
|
]);
|
|
});
|
|
|
|
it('parses workspace object', () => {
|
|
expect(
|
|
Workspace.parse({
|
|
members: ['packages/*', 'libs/*'],
|
|
}),
|
|
).toEqual(['packages/*', 'libs/*']);
|
|
});
|
|
});
|
|
|
|
describe('DenoDependency', () => {
|
|
// https://github.com/renovatebot/renovate/discussions/43015
|
|
it('parses npm package names containing dots', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'npm:discord.js@14.26.3',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
currentRawValue: 'npm:discord.js@14.26.3',
|
|
currentValue: '14.26.3',
|
|
datasource: 'npm',
|
|
depName: 'discord.js',
|
|
depType: 'imports',
|
|
versioning: 'deno',
|
|
});
|
|
});
|
|
|
|
it('invalid npm package names', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'npm:_test@1.0.0',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
datasource: 'npm',
|
|
skipReason: 'invalid-name',
|
|
versioning: 'deno',
|
|
});
|
|
});
|
|
|
|
it('invalid npm package versions', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'npm:dep1@INVALID',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
datasource: 'npm',
|
|
versioning: 'deno',
|
|
skipReason: 'invalid-version',
|
|
});
|
|
});
|
|
|
|
it('invalid jsr package names', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'jsr:@scope//name@1.0.0',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
datasource: 'jsr',
|
|
skipReason: 'invalid-name',
|
|
versioning: 'deno',
|
|
});
|
|
});
|
|
|
|
it('jsr package under a short scope', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'jsr:@db/sqlite@^0.13.0',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
currentRawValue: 'jsr:@db/sqlite@^0.13.0',
|
|
currentValue: '^0.13.0',
|
|
datasource: 'jsr',
|
|
depName: '@db/sqlite',
|
|
depType: 'imports',
|
|
versioning: 'deno',
|
|
});
|
|
});
|
|
|
|
it('invalid jsr package versions', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'jsr:@scope/name@INVALID',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
datasource: 'jsr',
|
|
versioning: 'deno',
|
|
skipReason: 'invalid-version',
|
|
});
|
|
});
|
|
|
|
it('unsupported datasource', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'unsupported:package@1.0.0',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
depType: 'imports',
|
|
depName: 'unsupported:package@1.0.0',
|
|
skipStage: 'extract',
|
|
skipReason: 'unsupported',
|
|
});
|
|
});
|
|
|
|
it('deno.land URL without package name', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'https://deno.land/',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
depType: 'imports',
|
|
depName: 'https://deno.land/',
|
|
skipStage: 'extract',
|
|
skipReason: 'unsupported',
|
|
});
|
|
});
|
|
|
|
it('deno.land URL with version', () => {
|
|
expect(
|
|
DenoDependency.parse({
|
|
depValue: 'https://deno.land/x/package@1.0.0',
|
|
depType: 'imports',
|
|
}),
|
|
).toEqual({
|
|
datasource: 'deno',
|
|
depType: 'imports',
|
|
depName: 'https://deno.land/x/package',
|
|
currentValue: '1.0.0',
|
|
currentRawValue: 'https://deno.land/x/package@1.0.0',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('DenoLock via DenoDependency transform path', () => {
|
|
it('handles empty specifiers in lock file', () => {
|
|
expect(
|
|
DenoLock.parse(
|
|
JSON.stringify({
|
|
version: '5',
|
|
specifiers: {},
|
|
redirects: {},
|
|
remote: {},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
lockedVersions: {},
|
|
redirectVersions: {},
|
|
remoteVersions: new Set(),
|
|
lockfileVersion: 5,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('UpdateDenoJsonFile', () => {
|
|
it('keep original field that is irrelevant for schema', () => {
|
|
expect(
|
|
UpdateDenoJsonFile.parse(
|
|
JSON.stringify({
|
|
name: 'package',
|
|
version: '1.0.0',
|
|
unknownFiled: 'should keep',
|
|
}),
|
|
),
|
|
).toEqual({
|
|
name: 'package',
|
|
version: '1.0.0',
|
|
unknownFiled: 'should keep',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('ImportMapExtract', () => {
|
|
it('parses import map with imports and scopes', () => {
|
|
expect(
|
|
ImportMapExtract.parse(
|
|
JSON.stringify({
|
|
imports: {
|
|
dep1: 'npm:package@1.0.0',
|
|
},
|
|
scopes: {
|
|
'/scope': {
|
|
dep2: 'jsr:@scope/package@2.0.0',
|
|
},
|
|
},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
dependencies: [
|
|
{
|
|
currentRawValue: 'npm:package@1.0.0',
|
|
currentValue: '1.0.0',
|
|
datasource: 'npm',
|
|
depName: 'package',
|
|
depType: 'imports',
|
|
versioning: 'deno',
|
|
},
|
|
{
|
|
currentRawValue: 'jsr:@scope/package@2.0.0',
|
|
currentValue: '2.0.0',
|
|
datasource: 'jsr',
|
|
depName: '@scope/package',
|
|
depType: 'scopes',
|
|
versioning: 'deno',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('parses import map with only imports', () => {
|
|
expect(
|
|
ImportMapExtract.parse(
|
|
JSON.stringify({
|
|
imports: {
|
|
dep1: 'npm:package@1.0.0',
|
|
},
|
|
}),
|
|
),
|
|
).toEqual({
|
|
dependencies: [
|
|
{
|
|
currentRawValue: 'npm:package@1.0.0',
|
|
currentValue: '1.0.0',
|
|
datasource: 'npm',
|
|
depName: 'package',
|
|
depType: 'imports',
|
|
versioning: 'deno',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('parses empty import map', () => {
|
|
expect(ImportMapExtract.parse(JSON.stringify({}))).toEqual({
|
|
dependencies: [],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('DenoExtract', () => {
|
|
it('parses deno.json with all sections', () => {
|
|
const result = DenoExtract.parse({
|
|
content: JSON.stringify({
|
|
imports: {
|
|
dep1: 'npm:package@1.0.0',
|
|
},
|
|
scopes: {
|
|
'/scope': {
|
|
dep2: 'jsr:@scope/package@2.0.0',
|
|
},
|
|
},
|
|
tasks: {
|
|
task1: 'deno run npm:dep3',
|
|
},
|
|
compilerOptions: {
|
|
types: ['npm:@types/dep4'],
|
|
jsxImportSource: 'npm:react',
|
|
jsxImportSourceTypes: 'npm:@types/react',
|
|
},
|
|
lint: {
|
|
plugins: ['npm:eslint-plugin'],
|
|
},
|
|
}),
|
|
fileName: 'deno.json',
|
|
});
|
|
|
|
expect(result.fileName).toBe('deno.json');
|
|
expect(result.content).toHaveProperty('lock');
|
|
expect(result.content).toHaveProperty('importMap');
|
|
expect(result.content).toHaveProperty('managerData');
|
|
expect(result.content).toHaveProperty('dependencies');
|
|
expect(result.content.dependencies.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('parses minimal deno.json', () => {
|
|
const result = DenoExtract.parse({
|
|
content: JSON.stringify({}),
|
|
fileName: 'deno.json',
|
|
});
|
|
|
|
expect(result.fileName).toBe('deno.json');
|
|
expect(result.content.dependencies).toEqual([]);
|
|
});
|
|
|
|
it('parses deno.json with compilerOptions lacking dependency fields', () => {
|
|
const result = DenoExtract.parse({
|
|
content: JSON.stringify({
|
|
compilerOptions: {
|
|
lib: ['deno.ns', 'deno.window'],
|
|
strict: true,
|
|
},
|
|
imports: {
|
|
dep1: 'npm:package@1.0.0',
|
|
},
|
|
}),
|
|
fileName: 'deno.json',
|
|
});
|
|
|
|
expect(result.content.dependencies).toEqual([
|
|
expect.objectContaining({ depName: 'package', depType: 'imports' }),
|
|
]);
|
|
});
|
|
|
|
it('parses deno.json with workspace', () => {
|
|
const result = DenoExtract.parse({
|
|
content: JSON.stringify({
|
|
workspace: ['packages/*', 'libs/*'],
|
|
}),
|
|
fileName: 'deno.json',
|
|
});
|
|
|
|
expect(result.content.managerData.workspaces).toEqual([
|
|
'packages/*',
|
|
'libs/*',
|
|
]);
|
|
});
|
|
|
|
it('parses deno.json with lock config', () => {
|
|
const result = DenoExtract.parse({
|
|
content: JSON.stringify({
|
|
lock: 'genuine-deno.lock',
|
|
}),
|
|
fileName: 'deno.json',
|
|
});
|
|
|
|
expect(result.content.lock).toBe('genuine-deno.lock');
|
|
});
|
|
|
|
it('parses deno.json with importMap', () => {
|
|
const result = DenoExtract.parse({
|
|
content: JSON.stringify({
|
|
importMap: './import_map.json',
|
|
}),
|
|
fileName: 'deno.json',
|
|
});
|
|
|
|
expect(result.content.importMap).toBe('./import_map.json');
|
|
});
|
|
});
|
|
|
|
describe('UpdateImportMapJsonFile', () => {
|
|
it('keep original field that is irrelevant for schema', () => {
|
|
expect(
|
|
UpdateImportMapJsonFile.parse(
|
|
JSON.stringify({
|
|
integrity: {
|
|
'./modules/shapes/square.js':
|
|
'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC',
|
|
},
|
|
unknownFiled: 'should keep',
|
|
}),
|
|
),
|
|
).toEqual({
|
|
integrity: {
|
|
'./modules/shapes/square.js':
|
|
'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC',
|
|
},
|
|
unknownFiled: 'should keep',
|
|
});
|
|
});
|
|
});
|
|
});
|