renovate/lib/manager/poetry/artifacts.spec.ts
Rhys Arkins 537f534f13
fix(poetry): poetry install constraints quoting (#9012)
* fix(poetry): extract poetry.core.masonry.api

* fix(poetry): quote install requirements individually
2021-03-07 09:17:45 +01:00

222 lines
7.1 KiB
TypeScript

import { exec as _exec } from 'child_process';
import { readFileSync } from 'fs';
import _fs from 'fs-extra';
import { join } from 'upath';
import { envMock, mockExecAll } from '../../../test/exec-util';
import { mocked } from '../../../test/util';
import * as _datasource from '../../datasource';
import { setExecConfig } from '../../util/exec';
import { BinarySource } from '../../util/exec/common';
import * as docker from '../../util/exec/docker';
import * as _env from '../../util/exec/env';
import * as _hostRules from '../../util/host-rules';
import { updateArtifacts } from './artifacts';
const pyproject10toml = readFileSync(
'lib/manager/poetry/__fixtures__/pyproject.10.toml',
'utf8'
);
jest.mock('fs-extra');
jest.mock('child_process');
jest.mock('../../util/exec/env');
jest.mock('../../datasource');
jest.mock('../../util/host-rules');
const fs: jest.Mocked<typeof _fs> = _fs as any;
const exec: jest.Mock<typeof _exec> = _exec as any;
const env = mocked(_env);
const datasource = mocked(_datasource);
const hostRules = mocked(_hostRules);
const config = {
localDir: join('/tmp/github/some/repo'),
};
describe('.updateArtifacts()', () => {
beforeEach(async () => {
jest.resetAllMocks();
env.getChildProcessEnv.mockReturnValue(envMock.basic);
await setExecConfig(config);
docker.resetPrefetchedImages();
});
it('returns null if no poetry.lock found', async () => {
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '',
config,
})
).toBeNull();
});
it('returns null if updatedDeps is empty', async () => {
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps: [],
newPackageFileContent: '',
config,
})
).toBeNull();
});
it('returns null if unchanged', async () => {
fs.readFile.mockReturnValueOnce('Current poetry.lock' as any);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('Current poetry.lock' as any);
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '',
config,
})
).toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('returns updated poetry.lock', async () => {
fs.readFile.mockResolvedValueOnce('[metadata]\n' as never);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('New poetry.lock' as any);
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '{}',
config,
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('passes private credential environment vars', async () => {
fs.readFile.mockResolvedValueOnce(null);
fs.readFile.mockResolvedValueOnce('[metadata]\n' as never);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('New poetry.lock' as any);
hostRules.find.mockReturnValueOnce({
username: 'usernameOne',
password: 'passwordOne',
});
hostRules.find.mockReturnValueOnce({ username: 'usernameTwo' });
hostRules.find.mockReturnValueOnce({ password: 'passwordFour' });
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: pyproject10toml,
config,
})
).not.toBeNull();
expect(hostRules.find.mock.calls).toHaveLength(3);
expect(execSnapshots).toMatchSnapshot();
});
it('returns updated pyproject.lock', async () => {
fs.readFile.mockResolvedValueOnce(null);
fs.readFile.mockResolvedValueOnce('[metadata]\n' as never);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('New poetry.lock' as any);
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '{}',
config,
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('returns updated poetry.lock using docker', async () => {
jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
await setExecConfig({
...config,
binarySource: BinarySource.Docker,
});
fs.readFile.mockResolvedValueOnce('[metadata]\n' as any);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('New poetry.lock' as any);
datasource.getPkgReleases.mockResolvedValueOnce({
releases: [{ version: '2.7.5' }, { version: '3.4.2' }],
});
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '{}',
config: {
...config,
constraints: {
python: '~2.7 || ^3.4',
poetry: 'poetry>=1.1.2 setuptools poetry-dynamic-versioning>1',
},
},
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('returns updated poetry.lock using docker (constraints)', async () => {
jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce();
await setExecConfig({
...config,
binarySource: BinarySource.Docker,
});
fs.readFile.mockResolvedValueOnce(
'[metadata]\npython-versions = "~2.7 || ^3.4"' as any
);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('New poetry.lock' as any);
datasource.getPkgReleases.mockResolvedValueOnce({
releases: [{ version: '2.7.5' }, { version: '3.3.2' }],
});
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '{}',
config: {
...config,
constraints: { poetry: 'poetry>=1.0' },
},
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
it('catches errors', async () => {
fs.readFile.mockResolvedValueOnce('Current poetry.lock' as any);
fs.outputFile.mockImplementationOnce(() => {
throw new Error('not found');
});
const updatedDeps = ['dep1'];
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps,
newPackageFileContent: '{}',
config,
})
).toMatchSnapshot();
});
it('returns updated poetry.lock when doing lockfile maintenance', async () => {
fs.readFile.mockResolvedValueOnce('Old poetry.lock' as any);
const execSnapshots = mockExecAll(exec);
fs.readFile.mockReturnValueOnce('New poetry.lock' as any);
expect(
await updateArtifacts({
packageFileName: 'pyproject.toml',
updatedDeps: [],
newPackageFileContent: '{}',
config: {
...config,
isLockFileMaintenance: true,
},
})
).not.toBeNull();
expect(execSnapshots).toMatchSnapshot();
});
});