mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-02 02:29:51 +00:00
2fc46bdcfa
* test(manager): replace file snapshots with explicit assertions * test(manager): replace inline snapshots with explicit assertions * test(manager): assert on relevant sections instead of full bodies * test(manager): drop assertions implied by full equality * test(manager): address review feedback * test(manager): assert depType and versioning in the regex matcher
333 lines
11 KiB
TypeScript
333 lines
11 KiB
TypeScript
import { codeBlock } from 'common-tags';
|
|
import { Fixtures } from '~test/fixtures.ts';
|
|
import { GlobalConfig } from '../../../config/global.ts';
|
|
import { extractPackageFile } from './index.ts';
|
|
|
|
const requirements1 = Fixtures.get('requirements1.txt');
|
|
const requirements2 = Fixtures.get('requirements2.txt');
|
|
const requirements3 = Fixtures.get('requirements3.txt');
|
|
const requirements4 = Fixtures.get('requirements4.txt');
|
|
const requirements5 = Fixtures.get('requirements5.txt');
|
|
const requirements6 = Fixtures.get('requirements6.txt');
|
|
const requirements7 = Fixtures.get('requirements7.txt');
|
|
const requirements8 = Fixtures.get('requirements8.txt');
|
|
const requirementsWithEnvMarkers = Fixtures.get('requirements-env-markers.txt');
|
|
const requirementsGitPackages = Fixtures.get('requirements-git-packages.txt');
|
|
|
|
describe('modules/manager/pip_requirements/extract', () => {
|
|
beforeEach(() => {
|
|
vi.stubEnv('PIP_TEST_TOKEN', undefined);
|
|
GlobalConfig.reset();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.stubEnv('PIP_TEST_TOKEN', undefined);
|
|
GlobalConfig.reset();
|
|
});
|
|
|
|
describe('extractPackageFile()', () => {
|
|
beforeEach(() => {
|
|
vi.stubEnv('PIP_INDEX_URL', undefined);
|
|
});
|
|
|
|
it('returns null for empty', () => {
|
|
expect(extractPackageFile('nothing here')).toBeNull();
|
|
});
|
|
|
|
it('extracts dependencies', () => {
|
|
const res = extractPackageFile(requirements1);
|
|
expect(res?.deps).toMatchObject([
|
|
{ currentValue: '==0.3.1', depName: 'some-package' },
|
|
{ currentValue: '==1.0.0', depName: 'some-other-package' },
|
|
{ depName: 'sphinx' },
|
|
{
|
|
currentValue: '==1.9',
|
|
depName: 'not_semver',
|
|
packageName: 'not-semver',
|
|
},
|
|
]);
|
|
expect(res?.registryUrls).toEqual(['http://example.com/private-pypi/']);
|
|
});
|
|
|
|
it('extracts dependencies with --index-url short code', () => {
|
|
const requirements = codeBlock`
|
|
-i http://example.com/private-pypi/
|
|
some-package==0.3.1
|
|
`;
|
|
|
|
const res = extractPackageFile(requirements);
|
|
|
|
expect(res).toMatchObject({
|
|
deps: [
|
|
{
|
|
currentValue: '==0.3.1',
|
|
currentVersion: '0.3.1',
|
|
datasource: 'pypi',
|
|
depName: 'some-package',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts --requirement short code option', () => {
|
|
const requirements = codeBlock`
|
|
-r base.txt
|
|
some-package==0.3.1
|
|
`;
|
|
|
|
const res = extractPackageFile(requirements);
|
|
|
|
expect(res).toHaveProperty('managerData', {
|
|
requirementsFiles: ['base.txt'],
|
|
});
|
|
});
|
|
|
|
it('extracts --constraints short code option', () => {
|
|
const requirements = codeBlock`
|
|
-c constrain.txt
|
|
some-package==0.3.1
|
|
`;
|
|
|
|
const res = extractPackageFile(requirements);
|
|
|
|
expect(res).toHaveProperty('managerData', {
|
|
constraintsFiles: ['constrain.txt'],
|
|
});
|
|
});
|
|
|
|
it('extracts multiple dependencies', () => {
|
|
const res = extractPackageFile(requirements2)?.deps;
|
|
expect(res).toMatchObject([
|
|
{ currentValue: '==1', depName: 'Django' },
|
|
{ currentValue: '==0.6.27', depName: 'distribute' },
|
|
{ currentValue: '==0.2', depName: 'dj-database-url' },
|
|
{ currentValue: '==2.4.5', depName: 'psycopg2' },
|
|
{ currentValue: '==0.1.2', depName: 'wsgiref' },
|
|
]);
|
|
});
|
|
|
|
it('handles comments and commands', () => {
|
|
const res = extractPackageFile(requirements3)?.deps;
|
|
expect(res).toMatchObject([
|
|
{ currentValue: '==1.11.23', depName: 'Django' },
|
|
{
|
|
currentValue: '==0.6.27',
|
|
depName: 'distribute',
|
|
skipReason: 'ignored',
|
|
},
|
|
{ currentValue: '==0.2', depName: 'dj-database-url' },
|
|
{ currentValue: '==2.4.5', depName: 'psycopg2' },
|
|
{ currentValue: '==0.1.2', depName: 'wsgiref' },
|
|
]);
|
|
});
|
|
|
|
it('handles extras and complex index url', () => {
|
|
const res = extractPackageFile(requirements4);
|
|
expect(res?.deps).toMatchObject([
|
|
{ currentValue: '==2.0.12', depName: 'Django' },
|
|
{ currentValue: '==4.1.1', depName: 'celery' },
|
|
{ currentValue: '== 3.2.1', depName: 'foo' },
|
|
]);
|
|
expect(res?.registryUrls).toEqual([
|
|
'https://artifactory.company.com/artifactory/api/pypi/python/simple',
|
|
]);
|
|
});
|
|
|
|
it('handles extra index url', () => {
|
|
const res = extractPackageFile(requirements5);
|
|
expect(res?.deps).toMatchObject([
|
|
{ currentValue: '==2.0.12', depName: 'Django' },
|
|
{ currentValue: '==4.1.1', depName: 'celery' },
|
|
{ currentValue: '== 3.2.1', depName: 'foo' },
|
|
{ currentValue: '==0.3.1', depName: 'some-package' },
|
|
{ currentValue: '==1.0.0', depName: 'some-other-package' },
|
|
{ currentValue: '==1.9', depName: 'not_semver' },
|
|
]);
|
|
expect(res?.registryUrls).toEqual([
|
|
'https://artifactory.company.com/artifactory/api/pypi/python/simple',
|
|
]);
|
|
expect(res?.additionalRegistryUrls).toEqual([
|
|
'http://example.com/private-pypi/',
|
|
]);
|
|
});
|
|
|
|
it('handles extra index url and defaults without index to config', () => {
|
|
const res = extractPackageFile(requirements6);
|
|
expect(res?.registryUrls).toBeUndefined();
|
|
expect(res?.additionalRegistryUrls).toEqual([
|
|
'http://example.com/private-pypi/',
|
|
]);
|
|
expect(res?.deps).toHaveLength(6);
|
|
});
|
|
|
|
it('handles extra index url and defaults without index to pypi', () => {
|
|
const res = extractPackageFile(requirements6);
|
|
expect(res?.registryUrls).toBeUndefined();
|
|
expect(res?.additionalRegistryUrls).toEqual([
|
|
'http://example.com/private-pypi/',
|
|
]);
|
|
expect(res?.deps).toHaveLength(6);
|
|
});
|
|
|
|
it('handles extra spaces around pinned dependency equal signs', () => {
|
|
const res = extractPackageFile(requirements4);
|
|
expect(res?.deps[2]).toMatchObject({
|
|
currentValue: '== 3.2.1',
|
|
currentVersion: '3.2.1',
|
|
depName: 'foo',
|
|
});
|
|
|
|
expect(res?.deps[0].currentValue).toStartWith('==');
|
|
expect(res?.deps[0].currentVersion).toStartWith('2.0.12');
|
|
expect(res?.deps[1].currentValue).toStartWith('==');
|
|
expect(res?.deps[1].currentVersion).toStartWith('4.1.1');
|
|
|
|
expect(res?.deps).toHaveLength(3);
|
|
});
|
|
|
|
it('should not replace env vars in low trust mode', () => {
|
|
vi.stubEnv('PIP_TEST_TOKEN', 'its-a-secret');
|
|
const res = extractPackageFile(requirements7);
|
|
expect(res?.additionalRegistryUrls).toEqual([
|
|
'http://$PIP_TEST_TOKEN:example.com/private-pypi/',
|
|
'http://${PIP_TEST_TOKEN}:example.com/private-pypi/',
|
|
'http://$PIP_TEST_TOKEN:example.com/private-pypi/',
|
|
'http://${PIP_TEST_TOKEN1}:example.com/private-pypi/',
|
|
]);
|
|
});
|
|
|
|
it('should replace env vars in high trust mode', () => {
|
|
vi.stubEnv('PIP_TEST_TOKEN', 'its-a-secret');
|
|
GlobalConfig.set({ exposeAllEnv: true });
|
|
const res = extractPackageFile(requirements7);
|
|
expect(res?.additionalRegistryUrls).toEqual([
|
|
'http://its-a-secret:example.com/private-pypi/',
|
|
'http://its-a-secret:example.com/private-pypi/',
|
|
'http://its-a-secret:example.com/private-pypi/',
|
|
'http://${PIP_TEST_TOKEN1}:example.com/private-pypi/',
|
|
]);
|
|
});
|
|
|
|
it('should handle hashes', () => {
|
|
const res = extractPackageFile(requirements8);
|
|
expect(res?.deps).toMatchObject([
|
|
{ currentValue: '==1.9.1', depName: 'Django' },
|
|
{ currentValue: '==0.22.1', depName: 'bgg' },
|
|
{ currentValue: '==2016.1.8', depName: 'html2text' },
|
|
]);
|
|
});
|
|
|
|
it('should handle package with extras and no version specifiers', () => {
|
|
const res = extractPackageFile('Django[argon2]');
|
|
expect(res).toMatchObject({
|
|
deps: [
|
|
{
|
|
currentValue: undefined,
|
|
datasource: 'pypi',
|
|
depName: 'Django',
|
|
packageName: 'django',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should handle dependency and ignore env markers', () => {
|
|
const res = extractPackageFile(requirementsWithEnvMarkers);
|
|
expect(res).toEqual({
|
|
deps: [
|
|
{
|
|
currentValue: '==20.3.0',
|
|
currentVersion: '20.3.0',
|
|
datasource: 'pypi',
|
|
depName: 'attrs',
|
|
packageName: 'attrs',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should handle git packages', () => {
|
|
const res = extractPackageFile(requirementsGitPackages);
|
|
expect(res?.deps).toHaveLength(5);
|
|
expect(res).toEqual({
|
|
deps: [
|
|
{
|
|
depName: 'python-pip-setup-test',
|
|
currentValue: 'v1.1.0',
|
|
currentVersion: 'v1.1.0',
|
|
packageName: 'git@github.com:rwxd/python-pip-setup-test.git',
|
|
datasource: 'git-tags',
|
|
},
|
|
{
|
|
depName: 'test_package',
|
|
currentValue: '1.0.0',
|
|
currentVersion: '1.0.0',
|
|
packageName: 'git@github.com:rwxd/test_package',
|
|
datasource: 'git-tags',
|
|
},
|
|
{
|
|
depName: 'python-package',
|
|
currentValue: 'abcde',
|
|
currentVersion: 'abcde',
|
|
packageName: 'git@gitlab.company.com:rwxd/python-package.git',
|
|
datasource: 'git-tags',
|
|
},
|
|
{
|
|
depName: 'python-pip-setup-test',
|
|
currentValue: 'v0.9.0',
|
|
currentVersion: 'v0.9.0',
|
|
packageName:
|
|
'https://peter@github.com/rwxd/python-pip-setup-test.git',
|
|
datasource: 'git-tags',
|
|
},
|
|
{
|
|
depName: 'python-pip-setup-test',
|
|
currentValue: 'v0.9.0',
|
|
currentVersion: 'v0.9.0',
|
|
packageName: 'https://github.com/rwxd/python-pip-setup-test.git',
|
|
datasource: 'git-tags',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('extracts a file with only --index-url flags', () => {
|
|
const res = extractPackageFile('--index-url https://example.com/pypi');
|
|
expect(res).toMatchObject({
|
|
deps: [],
|
|
registryUrls: ['https://example.com/pypi'],
|
|
});
|
|
});
|
|
|
|
it('extracts a file with only --extra-index-url flags', () => {
|
|
const res = extractPackageFile(
|
|
'--extra-index-url https://example.com/pypi',
|
|
);
|
|
expect(res).toMatchObject({
|
|
deps: [],
|
|
additionalRegistryUrls: ['https://example.com/pypi'],
|
|
});
|
|
});
|
|
|
|
it('extracts a file with only -r flags', () => {
|
|
const res = extractPackageFile('-r requirements-other.txt');
|
|
expect(res).toMatchObject({
|
|
deps: [],
|
|
managerData: {
|
|
requirementsFiles: ['requirements-other.txt'],
|
|
},
|
|
});
|
|
});
|
|
|
|
it('extracts a file with only -c flags', () => {
|
|
const res = extractPackageFile('-c constraints.txt');
|
|
expect(res).toMatchObject({
|
|
deps: [],
|
|
managerData: {
|
|
constraintsFiles: ['constraints.txt'],
|
|
},
|
|
});
|
|
});
|
|
});
|
|
});
|