mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-27 07:50:47 +00:00
c41b46bac3
* ci(linter): add renovate/logger-static-message rule Adds a custom oxlint rule that enforces a static msg component for logger.warn/error/fatal calls (including logger.once variants) so the messages can be grouped in metrics and error catching services, per docs/development/best-practices.md. It also flags metadata properties named 'error' that hold error-ish values, because the bunyan serializer only handles the 'err' key. The rule is enabled as an error for lib/ production code and disabled for spec files. All 33 pre-existing violations are fixed by moving interpolated values into the metadata object, making messages static, and renaming 'error' metadata keys to 'err'. Affected log-message assertions in co-located specs are updated accordingly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: ignore validator output * fixup new merged in log messages --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
865 lines
22 KiB
TypeScript
865 lines
22 KiB
TypeScript
import { codeBlock, html } from 'common-tags';
|
|
import { Fixtures } from '~test/fixtures.ts';
|
|
import * as httpMock from '~test/http-mock.ts';
|
|
import { fs } from '~test/util.ts';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import { getPkgReleases } from '../index.ts';
|
|
import { CustomDatasource } from './index.ts';
|
|
|
|
vi.mock('../../../util/fs/index.ts');
|
|
|
|
describe('modules/datasource/custom/index', () => {
|
|
describe('getReleases', () => {
|
|
it('return null if only the prefix is supplied', async () => {
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.`,
|
|
packageName: '*',
|
|
customDatasources: {},
|
|
});
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return null if no registryUrl is provided as well no defaultRegistryTemplate is defined', async () => {
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {},
|
|
},
|
|
});
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return null if no custom datasource could be found', async () => {
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: '*',
|
|
customDatasources: {},
|
|
});
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return null on http error', async () => {
|
|
httpMock.scope('https://example.com').get('/v1').reply(404);
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'aPackageName',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return null if schema validation fails', async () => {
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, {
|
|
version: 'v1.0.0',
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return releases for api directly exposing in renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
},
|
|
],
|
|
};
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, expected);
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases with digests for api directly exposing in renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
newDigest: '0123456789abcdef',
|
|
},
|
|
],
|
|
};
|
|
const content = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
digest: '0123456789abcdef',
|
|
},
|
|
],
|
|
};
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, content);
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases with tags and other optional fields for api directly exposing in renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
},
|
|
],
|
|
tags: {
|
|
latest: 'v1.0.0',
|
|
},
|
|
sourceUrl: 'https://example.com/foo.git',
|
|
sourceDirectory: '/',
|
|
changelogUrl: 'https://example.com/foo/blob/main/CHANGELOG.md',
|
|
homepage: 'https://example.com/foo',
|
|
};
|
|
const content = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
},
|
|
],
|
|
tags: {
|
|
latest: 'v1.0.0',
|
|
},
|
|
sourceUrl: 'https://example.com/foo.git',
|
|
sourceDirectory: '/',
|
|
changelogUrl: 'https://example.com/foo/blob/main/CHANGELOG.md',
|
|
homepage: 'https://example.com/foo',
|
|
unknown: {},
|
|
};
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, content);
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for plain text API directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1')
|
|
.reply(200, '1.0.0\n2.0.0\n3.0.0', {
|
|
'Content-Type': 'text/plain',
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for plain text API and trim the content', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1')
|
|
.reply(200, '1.0.0 \n2.0.0 \n 3.0.0 ', {
|
|
'Content-Type': 'text/plain',
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('returns null if transformation compilation using jsonata fails', async () => {
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1')
|
|
.reply(200, '1.0.0 \n2.0.0 \n 3.0.0 ', {
|
|
'Content-Type': 'text/plain',
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
transformTemplates: ['$[.name = "Alice" and'],
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toBeNull();
|
|
|
|
expect(logger.once.warn).toHaveBeenCalledWith(
|
|
{
|
|
errorMessage: 'The symbol "." cannot be used as a unary operator',
|
|
transformTemplate: '$[.name = "Alice" and',
|
|
},
|
|
'Invalid JSONata expression',
|
|
);
|
|
});
|
|
|
|
it('returns null if jsonata expression evaluation fails', async () => {
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1')
|
|
.reply(200, '1.0.0 \n2.0.0 \n 3.0.0 ', {
|
|
'Content-Type': 'text/plain',
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
transformTemplates: ['$notafunction()'],
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toBeNull();
|
|
|
|
expect(logger.once.warn).toHaveBeenCalledWith(
|
|
{ err: expect.any(Object), transformTemplate: '$notafunction()' },
|
|
'Error while evaluating JSONata expression',
|
|
);
|
|
});
|
|
|
|
it('return releases for plain text API when only returns a single version', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
],
|
|
};
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, '1.0.0', {
|
|
'Content-Type': 'text/plain',
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for yaml API directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
const yaml = codeBlock`
|
|
releases:
|
|
- version: 1.0.0
|
|
- version: 2.0.0
|
|
- version: 3.0.0
|
|
`;
|
|
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, yaml, {
|
|
'Content-Type': 'text/yaml',
|
|
});
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
format: 'yaml',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for yaml file directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
|
|
releases:
|
|
- version: 1.0.0
|
|
- version: 2.0.0
|
|
- version: 3.0.0
|
|
`);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.yaml',
|
|
format: 'yaml',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('returns releases for toml API directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
const toml = codeBlock`
|
|
[[releases]]
|
|
version = "1.0.0"
|
|
[[releases]]
|
|
version = "2.0.0"
|
|
[[releases]]
|
|
version = "3.0.0"
|
|
`;
|
|
|
|
httpMock.scope('https://example.com').get('/v1').reply(200, toml, {
|
|
'Content-Type': 'application/toml',
|
|
});
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
format: 'toml',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for toml file directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
fs.readLocalFile.mockResolvedValueOnce(codeBlock`
|
|
[[releases]]
|
|
version = "1.0.0"
|
|
[[releases]]
|
|
version = "2.0.0"
|
|
[[releases]]
|
|
version = "3.0.0"
|
|
`);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.toml',
|
|
format: 'toml',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for json file directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
fs.readLocalFile.mockResolvedValueOnce(codeBlock`{
|
|
"releases": [
|
|
{ "version": "1.0.0" },
|
|
{ "version": "2.0.0" },
|
|
{ "version": "3.0.0" }
|
|
]
|
|
}`);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.json',
|
|
format: 'json',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return null for plain text file if the body is not what is expected', async () => {
|
|
fs.readLocalFile.mockResolvedValueOnce(null);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.version',
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return releases for plain text file directly exposing in Renovate format', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
version: '2.0.0',
|
|
},
|
|
{
|
|
version: '3.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
fs.readLocalFile.mockResolvedValueOnce(codeBlock`{
|
|
1.0.0
|
|
2.0.0
|
|
3.0.0
|
|
}`);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.version',
|
|
format: 'plain',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return release when templating registryUrl', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
},
|
|
],
|
|
};
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1/myPackage')
|
|
.reply(200, expected);
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate:
|
|
'https://example.com/v1/{{packageName}}',
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return release with templated path', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1')
|
|
.reply(200, {
|
|
myPackage: expected,
|
|
otherPackage: {
|
|
releases: [
|
|
{
|
|
version: 'v2.0.0',
|
|
},
|
|
],
|
|
},
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
transformTemplates: ['{{packageName}}'],
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return release with templated path with multiple layers', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'v1.0.0',
|
|
},
|
|
],
|
|
};
|
|
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/v1')
|
|
.reply(200, {
|
|
groupName: {
|
|
myPackage: expected,
|
|
otherPackage: {
|
|
releases: [
|
|
{
|
|
version: 'v2.0.0',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
});
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/v1',
|
|
transformTemplates: ['groupName.{{packageName}}'],
|
|
},
|
|
},
|
|
});
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases from HTML links', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'package-1.0.tar.gz',
|
|
},
|
|
],
|
|
};
|
|
|
|
const content = html`
|
|
<html>
|
|
<body>
|
|
<a href="package-1.0.tar.gz">package-1.0.tar.gz</a>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/index.html')
|
|
.reply(200, content, {
|
|
'Content-Type': 'text/html',
|
|
});
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/index.html',
|
|
format: 'html',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases from HTML links - local file', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'package-1.0.tar.gz',
|
|
},
|
|
],
|
|
};
|
|
|
|
const content = html`
|
|
<html>
|
|
<body>
|
|
<a href="package-1.0.tar.gz">package-1.0.tar.gz</a>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
fs.readLocalFile.mockResolvedValueOnce(content);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.html',
|
|
format: 'html',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return null for local file read error - HTML format', async () => {
|
|
fs.readLocalFile.mockResolvedValueOnce(null);
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'file://test.html',
|
|
format: 'html',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('return releases from nginx directory listing', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'nginx-0.1.0.tar.gz',
|
|
},
|
|
{
|
|
version: 'nginx-0.1.1.tar.gz',
|
|
},
|
|
{
|
|
version: 'nginx-0.1.11.tar.gz',
|
|
},
|
|
],
|
|
};
|
|
|
|
httpMock
|
|
.scope('http://nginx.org')
|
|
.get('/download/')
|
|
.reply(200, Fixtures.get('nginx-downloads.html'), {
|
|
'Content-Type': 'text/html',
|
|
})
|
|
.get('/download')
|
|
.reply(301, undefined, {
|
|
Location: 'http://nginx.org/download/',
|
|
});
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'http://nginx.org/download',
|
|
format: 'html',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for malformed HTML', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'package-1.0.tar.gz',
|
|
},
|
|
],
|
|
};
|
|
|
|
const content = html`
|
|
<html>
|
|
<body>
|
|
<h1></pre><hr></body><a href="package-1.0.tar.gz">package-1.0.tar.gz</a>
|
|
</html>
|
|
`;
|
|
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/malformed.html')
|
|
.reply(200, content, {
|
|
'Content-Type': 'text/html',
|
|
});
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/malformed.html',
|
|
format: 'html',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
|
|
it('return releases for incomplete HTML', async () => {
|
|
const expected = {
|
|
releases: [
|
|
{
|
|
version: 'package-1.0.tar.gz',
|
|
},
|
|
],
|
|
};
|
|
|
|
const content = html`
|
|
<html>
|
|
<body>
|
|
<a href="package-1.0.tar.gz">package-1.0.tar.gz</a>
|
|
<a href="package-2.0.tar.gz
|
|
`;
|
|
|
|
httpMock
|
|
.scope('https://example.com')
|
|
.get('/incomplete.html')
|
|
.reply(200, content, {
|
|
'Content-Type': 'text/html',
|
|
});
|
|
|
|
const result = await getPkgReleases({
|
|
datasource: `${CustomDatasource.id}.foo`,
|
|
packageName: 'myPackage',
|
|
customDatasources: {
|
|
foo: {
|
|
defaultRegistryUrlTemplate: 'https://example.com/incomplete.html',
|
|
format: 'html',
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(result).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe('getDigest', () => {
|
|
it('returns null as digest should be provided in releases', async () => {
|
|
const digest = await new CustomDatasource().getDigest({
|
|
packageName: 'my-package',
|
|
});
|
|
expect(digest).toBeNull();
|
|
});
|
|
});
|
|
});
|