mirror of https://github.com/renovatebot/renovate
1112 lines
60 KiB
TypeScript
1112 lines
60 KiB
TypeScript
import is from '@sindresorhus/is';
|
|
import { codeBlock } from 'common-tags';
|
|
import { Fixtures } from '../../../../test/fixtures';
|
|
import { fs, logger } from '../../../../test/util';
|
|
import { parseGradle, parseKotlinSource, parseProps } from './parser';
|
|
import { GRADLE_PLUGINS, REGISTRY_URLS } from './parser/common';
|
|
|
|
jest.mock('../../../util/fs');
|
|
|
|
function mockFs(files: Record<string, string>): void {
|
|
fs.getSiblingFileName.mockImplementation(
|
|
(existingFileNameWithPath: string, otherFileName: string) => {
|
|
return existingFileNameWithPath
|
|
.slice(0, existingFileNameWithPath.lastIndexOf('/') + 1)
|
|
.concat(otherFileName);
|
|
},
|
|
);
|
|
}
|
|
|
|
describe('modules/manager/gradle/parser', () => {
|
|
it('handles end of input', () => {
|
|
expect(parseGradle('version = ').deps).toBeEmpty();
|
|
expect(parseGradle('id "foo.bar" version').deps).toBeEmpty();
|
|
});
|
|
|
|
describe('variables', () => {
|
|
describe('Groovy: single var assignments', () => {
|
|
it.each`
|
|
input | name | value
|
|
${'foo = "1.2.3"'} | ${'foo'} | ${'1.2.3'}
|
|
${'foo.bar = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
|
|
${'foo.bar.baz = "1.2.3"'} | ${'foo.bar.baz'} | ${'1.2.3'}
|
|
${'ext.foobar = "1.2.3"'} | ${'foobar'} | ${'1.2.3'}
|
|
${'foo["bar"] = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
|
|
${'foo["bar"]["baz"] = "1.2.3"'} | ${'foo.bar.baz'} | ${'1.2.3'}
|
|
${'foo["bar"]["baz.qux"] = "1.2.3"'} | ${'foo.bar.baz.qux'} | ${'1.2.3'}
|
|
${'foo.bar["baz"]["qux"] = "1.2.3"'} | ${'foo.bar.baz.qux'} | ${'1.2.3'}
|
|
${'ext["foo"] = "1.2.3"'} | ${'foo'} | ${'1.2.3'}
|
|
${'ext["foo"]["bar"] = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
|
|
${'extra["foo"] = "1.2.3"'} | ${'foo'} | ${'1.2.3'}
|
|
${'project.foobar = "1.2.3"'} | ${'foobar'} | ${'1.2.3'}
|
|
${'project.ext.foo.bar = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
|
|
${'rootProject.foobar = "1.2.3"'} | ${'foobar'} | ${'1.2.3'}
|
|
${'rootProject.foo.bar = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
|
|
`('$input', ({ input, name, value }) => {
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toContainKey(name);
|
|
expect(vars[name]).toMatchObject({ key: name, value });
|
|
});
|
|
});
|
|
|
|
describe('Groovy: single var assignments (non-match)', () => {
|
|
it.each`
|
|
input
|
|
${'foo[["bar"]] = "baz"'}
|
|
${'foo["bar", "invalid"] = "1.2.3"'}
|
|
${'foo.bar["baz", "invalid"] = "1.2.3"'}
|
|
`('$input', ({ input }) => {
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toBeEmpty();
|
|
});
|
|
});
|
|
|
|
describe('Groovy: multi var assignments', () => {
|
|
it('simple map', () => {
|
|
const input = codeBlock`
|
|
ext {
|
|
versions = [
|
|
spotbugs_annotations : '4.5.3',
|
|
core : '1.7.0',
|
|
]
|
|
|
|
ignored = [ 'asdf' ]
|
|
|
|
libraries = [:]
|
|
libraries += [
|
|
guava: "com.google.guava:guava:31.1-jre",
|
|
detekt: '1.18.1',
|
|
core2: versions.core
|
|
]
|
|
}
|
|
`;
|
|
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toMatchObject({
|
|
'versions.spotbugs_annotations': {
|
|
key: 'versions.spotbugs_annotations',
|
|
value: '4.5.3',
|
|
},
|
|
'versions.core': {
|
|
key: 'versions.core',
|
|
value: '1.7.0',
|
|
},
|
|
'libraries.guava': {
|
|
key: 'libraries.guava',
|
|
value: 'com.google.guava:guava:31.1-jre',
|
|
},
|
|
'libraries.detekt': {
|
|
key: 'libraries.detekt',
|
|
value: '1.18.1',
|
|
},
|
|
'libraries.core2': {
|
|
key: 'versions.core',
|
|
value: '1.7.0',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('nested map', () => {
|
|
const input = codeBlock`
|
|
project.ext.versions = [
|
|
some: invalidsymbol,
|
|
android: [
|
|
buildTools: '30.0.3'
|
|
],
|
|
kotlin: '1.4.30',
|
|
androidx: [
|
|
paging: '2.1.2',
|
|
kotlin: [
|
|
stdlib: '1.4.20',
|
|
coroutines: '1.3.7',
|
|
],
|
|
],
|
|
espresso: '3.2.0'
|
|
]
|
|
`;
|
|
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toMatchObject({
|
|
'versions.android.buildTools': {
|
|
key: 'versions.android.buildTools',
|
|
value: '30.0.3',
|
|
},
|
|
'versions.kotlin': {
|
|
key: 'versions.kotlin',
|
|
value: '1.4.30',
|
|
},
|
|
'versions.androidx.paging': {
|
|
key: 'versions.androidx.paging',
|
|
value: '2.1.2',
|
|
},
|
|
'versions.androidx.kotlin.stdlib': {
|
|
key: 'versions.androidx.kotlin.stdlib',
|
|
value: '1.4.20',
|
|
},
|
|
'versions.androidx.kotlin.coroutines': {
|
|
key: 'versions.androidx.kotlin.coroutines',
|
|
value: '1.3.7',
|
|
},
|
|
'versions.espresso': {
|
|
key: 'versions.espresso',
|
|
value: '3.2.0',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('map with interpolated dependency strings', () => {
|
|
const input = codeBlock`
|
|
def slfj4Version = "2.0.0"
|
|
def lifecycle_version = "2.5.1"
|
|
libraries = [
|
|
jcl: "org.slf4j:jcl-over-slf4j:\${slfj4Version}",
|
|
releaseCoroutines: "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.26.1-eap13"
|
|
api: "org.slf4j:slf4j-api:$slfj4Version",
|
|
lifecycle: [
|
|
"androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version",
|
|
"androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
|
|
]
|
|
]
|
|
foo = [ group: "org.slf4j", name: "slf4j-ext", version: slfj4Version ]
|
|
`;
|
|
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([
|
|
{
|
|
depName: 'org.slf4j:jcl-over-slf4j',
|
|
groupName: 'slfj4Version',
|
|
currentValue: '2.0.0',
|
|
},
|
|
{
|
|
depName: 'org.jetbrains.kotlinx:kotlinx-coroutines-core',
|
|
groupName: 'libraries.releaseCoroutines',
|
|
currentValue: '0.26.1-eap13',
|
|
},
|
|
{
|
|
depName: 'org.slf4j:slf4j-api',
|
|
groupName: 'slfj4Version',
|
|
currentValue: '2.0.0',
|
|
},
|
|
{
|
|
depName: 'androidx.lifecycle:lifecycle-runtime-ktx',
|
|
groupName: 'lifecycle_version',
|
|
currentValue: '2.5.1',
|
|
},
|
|
{
|
|
depName: 'androidx.lifecycle:lifecycle-viewmodel-ktx',
|
|
groupName: 'lifecycle_version',
|
|
currentValue: '2.5.1',
|
|
},
|
|
{
|
|
depName: 'org.slf4j:slf4j-ext',
|
|
groupName: 'slfj4Version',
|
|
currentValue: '2.0.0',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('Kotlin: single var assignments', () => {
|
|
it.each`
|
|
input | name | value
|
|
${'set("foo", "1.2.3")'} | ${'foo'} | ${'1.2.3'}
|
|
${'version("foo", "1.2.3")'} | ${'foo'} | ${'1.2.3'}
|
|
`('$input', ({ input, name, value }) => {
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toContainKey(name);
|
|
expect(vars[name]).toMatchObject({ key: name, value });
|
|
});
|
|
});
|
|
|
|
describe('Kotlin: single var assignments (non-match)', () => {
|
|
it.each`
|
|
input
|
|
${'set(["foo", "bar"])'}
|
|
${'set("foo", "bar", "baz", "qux"])'}
|
|
`('$input', ({ input }) => {
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toBeEmpty();
|
|
});
|
|
});
|
|
|
|
describe('Kotlin: single extra var assignments', () => {
|
|
it.each`
|
|
input | name | value
|
|
${'val foo by extra("1.2.3")'} | ${'foo'} | ${'1.2.3'}
|
|
${'val foo by extra { "1.2.3" }'} | ${'foo'} | ${'1.2.3'}
|
|
${'val foo: String by extra { "1.2.3" }'} | ${'foo'} | ${'1.2.3'}
|
|
`('$input', ({ input, name, value }) => {
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toContainKey(name);
|
|
expect(vars[name]).toMatchObject({ key: name, value });
|
|
});
|
|
});
|
|
|
|
describe('Kotlin: multi var assignments', () => {
|
|
it('simple map', () => {
|
|
const input =
|
|
'val versions = mapOf("foo1" to "bar1", "foo2" to "bar2", "foo3" to "bar3")';
|
|
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toMatchObject({
|
|
'versions.foo1': {
|
|
key: 'versions.foo1',
|
|
value: 'bar1',
|
|
},
|
|
'versions.foo2': {
|
|
key: 'versions.foo2',
|
|
value: 'bar2',
|
|
},
|
|
'versions.foo3': {
|
|
key: 'versions.foo3',
|
|
value: 'bar3',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('nested map', () => {
|
|
const input = codeBlock`
|
|
val junitPlatformVersion: String by extra { "1.0.1" }
|
|
ext["deps"] = mapOf(
|
|
"support" to mapOf(
|
|
"appCompat" to "com.android.support:appcompat-v7:26.0.2",
|
|
"invalid" to whatever,
|
|
"junit" to mapOf(
|
|
"jupiter" to "5.0.1",
|
|
"platform" to "1.0.1",
|
|
)
|
|
"design" to "com.android.support:design:26.0.2"
|
|
),
|
|
"support2" to mapOfInvalid(
|
|
"design2" to "com.android.support:design:26.0.2"
|
|
),
|
|
"picasso" to "com.squareup.picasso:picasso:2.5.2",
|
|
"junit-platform-runner" to junitPlatformVersion
|
|
)
|
|
`;
|
|
|
|
const { vars } = parseGradle(input);
|
|
expect(vars).toMatchObject({
|
|
'deps.support.appCompat': {
|
|
key: 'deps.support.appCompat',
|
|
value: 'com.android.support:appcompat-v7:26.0.2',
|
|
},
|
|
'deps.support.junit.jupiter': {
|
|
key: 'deps.support.junit.jupiter',
|
|
value: '5.0.1',
|
|
},
|
|
'deps.support.junit.platform': {
|
|
key: 'deps.support.junit.platform',
|
|
value: '1.0.1',
|
|
},
|
|
'deps.support.design': {
|
|
key: 'deps.support.design',
|
|
value: 'com.android.support:design:26.0.2',
|
|
},
|
|
'deps.picasso': {
|
|
key: 'deps.picasso',
|
|
value: 'com.squareup.picasso:picasso:2.5.2',
|
|
},
|
|
'deps.junit-platform-runner': {
|
|
key: 'junitPlatformVersion',
|
|
value: '1.0.1',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('map with interpolated dependency strings', () => {
|
|
const input = codeBlock`
|
|
val slfj4Version = "2.0.0"
|
|
libraries = mapOf(
|
|
"jcl" to "org.slf4j:jcl-over-slf4j:\${slfj4Version}",
|
|
"releaseCoroutines" to "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.26.1-eap13"
|
|
"api" to "org.slf4j:slf4j-api:$slfj4Version",
|
|
)
|
|
`;
|
|
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([
|
|
{
|
|
depName: 'org.slf4j:jcl-over-slf4j',
|
|
groupName: 'slfj4Version',
|
|
currentValue: '2.0.0',
|
|
},
|
|
{
|
|
depName: 'org.jetbrains.kotlinx:kotlinx-coroutines-core',
|
|
groupName: 'libraries.releaseCoroutines',
|
|
currentValue: '0.26.1-eap13',
|
|
},
|
|
{
|
|
depName: 'org.slf4j:slf4j-api',
|
|
groupName: 'slfj4Version',
|
|
currentValue: '2.0.0',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('dependencies', () => {
|
|
describe('simple dependency strings', () => {
|
|
it.each`
|
|
input | output
|
|
${'"foo:bar:1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'"foo:bar:1.2.3@zip"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'zip' }}
|
|
${'"foo:bar1:1"'} | ${{ depName: 'foo:bar1', currentValue: '1', managerData: { fileReplacePosition: 10 } }}
|
|
${'"foo:bar:x86@x86"'} | ${{ depName: 'foo:bar', currentValue: 'x86', managerData: { fileReplacePosition: 9 } }}
|
|
${'foo.bar = "foo:bar:1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
`('$input', ({ input, output }) => {
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([output]);
|
|
});
|
|
});
|
|
|
|
describe('interpolated dependency strings', () => {
|
|
it.each`
|
|
def | str | output
|
|
${'foo = "1.2.3"'} | ${'"foo:bar:$foo@@@"'} | ${null}
|
|
${''} | ${'"foo:bar:$baz"'} | ${null}
|
|
${'foo = "1"; bar = "2"; baz = "3"'} | ${'"foo:bar:$foo.$bar.$baz"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', skipReason: 'contains-variable' }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:$baz"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'foo.bar = "1.2.3"'} | ${'"foo:bar:$foo.bar"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'foo.bar' }}
|
|
${'foo = "1.2.3"'} | ${'"foo:bar_$foo:4.5.6"'} | ${{ depName: 'foo:bar_1.2.3', managerData: { fileReplacePosition: 28 } }}
|
|
${'foo = "bar"'} | ${'"foo:${foo}1:1"'} | ${{ depName: 'foo:bar1', currentValue: '1', managerData: { fileReplacePosition: 25 } }}
|
|
${'bar = "bar:1.2.3"'} | ${'"foo:$bar"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', skipReason: 'contains-variable' }}
|
|
${'baz = "1.2.3"'} | ${'foobar = "foo:bar:$baz"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'foo = "${bar}"; baz = "1.2.3"'} | ${'"foo:bar:${baz}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:${ext[\'baz\']}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:${ext.baz}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:${project.ext[\'baz\']}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'a = "foo"; b = "bar"; c="1.2.3"'} | ${'"${a}:${b}:${property("c")}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'c' }}
|
|
${'a = "foo"; b = "bar"; c="1.2.3"'} | ${'"${a}:${b}:${properties["c"]}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'c' }}
|
|
`('$def | $str', ({ def, str, output }) => {
|
|
const { deps } = parseGradle([def, str].join('\n'));
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
|
|
describe('concatenated dependency strings', () => {
|
|
it.each`
|
|
def | str | output
|
|
${''} | ${'"foo:bar" + ":1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 15 } }}
|
|
${''} | ${'"foo:bar:" + "1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 15 } }}
|
|
${''} | ${'"foo:bar:" + "1.2.3@zip"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'zip', managerData: { fileReplacePosition: 15 } }}
|
|
${''} | ${'"foo:" + "bar:1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 15 } }}
|
|
${''} | ${'"foo:bar:1." + "2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', skipReason: 'contains-variable' }}
|
|
${''} | ${'"foo:bar1.2.3:" + "1.2.3"'} | ${{ depName: 'foo:bar1.2.3', currentValue: '1.2.3', managerData: { fileReplacePosition: 20 } }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:" + baz'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 7 } }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:" + property("baz")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 7 } }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:" + baz + "456"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3456', skipReason: 'contains-variable' }}
|
|
${'baz = "1.2.3"'} | ${'"foo:bar:" + baz + "@zip"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'zip', managerData: { fileReplacePosition: 7 } }}
|
|
${'foo.bar = "bar:"; baz = "1.2.3"'} | ${'"foo:" + foo.bar + "${baz}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 25 } }}
|
|
${'foo.bar = "bar"; baz = "1.2.3"'} | ${'"foo:bar_${foo.bar}:" + baz'} | ${{ depName: 'foo:bar_bar', currentValue: '1.2.3', managerData: { fileReplacePosition: 24 } }}
|
|
`('$def | $str', ({ def, str, output }) => {
|
|
const { deps } = parseGradle([def, str].join('\n'));
|
|
expect(deps).toMatchObject([output]);
|
|
});
|
|
});
|
|
|
|
describe('property accessors', () => {
|
|
it.each`
|
|
accessor
|
|
${'property'}
|
|
${'getProperty'}
|
|
${'ext.getProperty'}
|
|
${'extra.get'}
|
|
${'project.property'}
|
|
${'project.getProperty'}
|
|
${'project.ext.getProperty'}
|
|
${'project.ext.get'}
|
|
${'project.extra.get'}
|
|
${'rootProject.property'}
|
|
${'rootProject.getProperty'}
|
|
${'rootProject.ext.getProperty'}
|
|
${'rootProject.extra.get'}
|
|
`('$accessor', ({ accessor }) => {
|
|
const input = `
|
|
baz = "1.2.3"
|
|
api("foo:bar:$\{${String(accessor)}("baz") as String}")
|
|
`;
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([
|
|
{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' },
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('kotlin() short notation dependencies', () => {
|
|
const output = {
|
|
depName: 'foo',
|
|
packageName: 'org.jetbrains.kotlin:kotlin-foo',
|
|
currentValue: '1.2.3',
|
|
};
|
|
|
|
it.each`
|
|
def | str | output
|
|
${''} | ${'kotlin("foo", "1.2.3")'} | ${output}
|
|
${''} | ${'kotlin("foo", version = "1.2.3")'} | ${output}
|
|
${'some = "foo"'} | ${'kotlin(some, version = "1.2.3")'} | ${output}
|
|
${'some = "foo"'} | ${'kotlin("${some}", "1.2.3")'} | ${output}
|
|
${'baz = "1.2.3"'} | ${'kotlin("foo", baz)'} | ${{ ...output, groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'kotlin("foo", version = baz)'} | ${output}
|
|
${'baz = "1.2.3"'} | ${'kotlin("foo", property("baz"))'} | ${output}
|
|
${'baz = "1.2.3"'} | ${'kotlin("foo", "${baz}456")'} | ${{ skipReason: 'unspecified-version' }}
|
|
${'baz = "1.2.3"'} | ${'kotlin("foo", baz + "456")'} | ${{ skipReason: 'unspecified-version' }}
|
|
${''} | ${'kotlin("foo", some)'} | ${null}
|
|
${''} | ${'kotlin(["foo", "1.2.3"])'} | ${null}
|
|
${''} | ${'kotlin("foo", "1.2.3", "4.5.6")'} | ${null}
|
|
${''} | ${'kotlin("foo", "1.2.3@@@")'} | ${null}
|
|
`('$def | $str', ({ def, str, output }) => {
|
|
const { deps } = parseGradle([def, str].join('\n'));
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
|
|
describe('map notation dependencies', () => {
|
|
it.each`
|
|
def | str | output
|
|
${''} | ${'group: "foo", name: "bar", version: "1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${''} | ${'group: "foo", name: "bar", version: baz'} | ${null}
|
|
${''} | ${'group: "foo", name: "bar", version: "1.2.3@@@"'} | ${null}
|
|
${'baz = "1.2.3"'} | ${'group: "foo", name: "bar", version: baz'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'some = "foo"'} | ${'group: property("some"), name: property("some"), version: "1.2.3"'} | ${{ depName: 'foo:foo', currentValue: '1.2.3' }}
|
|
${'some = "foo"'} | ${'group: some, name: some, version: "1.2.3"'} | ${{ depName: 'foo:foo', currentValue: '1.2.3' }}
|
|
${'some = "foo"'} | ${'group: "${some}", name: "${some}", version: "1.2.3"'} | ${{ depName: 'foo:foo', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'group: "foo", name: "bar", version: "${baz}"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'group: "foo", name: "bar", version: "${baz}456"'} | ${{ depName: 'foo:bar', skipReason: 'unspecified-version' }}
|
|
${''} | ${'(group: "foo", name: "bar", version: "1.2.3", classifier: "sources")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${''} | ${'(group: "foo", name: "bar", version: "1.2.3") {exclude module: "spring-jcl"}'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${''} | ${"implementation platform(group: 'foo', name: 'bar', version: '1.2.3')"} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${''} | ${'(group = "foo", name = "bar", version = "1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'(group = "foo", name = "bar", version = baz)'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'some = "foo"'} | ${'(group = some, name = some, version = "1.2.3")'} | ${{ depName: 'foo:foo', currentValue: '1.2.3' }}
|
|
${'some = "foo"'} | ${'(group = "${some}", name = "${some}", version = "1.2.3")'} | ${{ depName: 'foo:foo', currentValue: '1.2.3' }}
|
|
${'some = "foo"'} | ${'(group = "${some}" + some, name = some + "bar" + some, version = "1.2.3")'} | ${{ depName: 'foofoo:foobarfoo', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'(group = "foo", name = "bar", version = "${baz}")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'(group = "foo", name = "bar", version = "${baz}456")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3456', skipReason: 'unspecified-version' }}
|
|
${'baz = "1.2.3"'} | ${'(group = "foo", name = "bar", version = baz + "456")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3456', skipReason: 'unspecified-version' }}
|
|
${''} | ${'(group = "foo", name = "bar", version = "1.2.3", changing: true)'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
`('$def | $str', ({ def, str, output }) => {
|
|
const { deps } = parseGradle([def, str].join('\n'));
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
|
|
describe('dependencySet dependencies', () => {
|
|
it('simple dependencySet', () => {
|
|
const input = codeBlock`
|
|
ext.activemq_version = "5.8.0"
|
|
dependencySet(group: 'org.apache.activemq', version: activemq_version) {
|
|
entry 'activemq-broker'
|
|
entry('activemq-kahadb-store') {
|
|
exclude group: "org.springframework", name: "spring-context"
|
|
}
|
|
entry 'activemq-stomp'
|
|
}
|
|
`;
|
|
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([
|
|
{
|
|
depName: 'org.apache.activemq:activemq-broker',
|
|
currentValue: '5.8.0',
|
|
groupName: 'activemq_version',
|
|
},
|
|
{
|
|
depName: 'org.apache.activemq:activemq-kahadb-store',
|
|
currentValue: '5.8.0',
|
|
groupName: 'activemq_version',
|
|
},
|
|
{
|
|
depName: 'org.apache.activemq:activemq-stomp',
|
|
currentValue: '5.8.0',
|
|
groupName: 'activemq_version',
|
|
},
|
|
]);
|
|
});
|
|
|
|
describe('dependencySet variants', () => {
|
|
const validOutput = [
|
|
{
|
|
depName: 'foo:bar1',
|
|
currentValue: '1.2.3',
|
|
groupName: 'foo:1.2.3',
|
|
},
|
|
{
|
|
depName: 'foo:bar2',
|
|
currentValue: '1.2.3',
|
|
groupName: 'foo:1.2.3',
|
|
},
|
|
];
|
|
const validOutput1 = validOutput.map((dep) => {
|
|
return { ...dep, groupName: 'baz' };
|
|
});
|
|
|
|
it.each`
|
|
def | str | output
|
|
${''} | ${'dependencySet([group: "foo", version: "1.2.3"]) { entry "bar1" }'} | ${{}}
|
|
${''} | ${'dependencySet(group: "foo", version: "1.2.3", group: "foo", version: "1.2.3") { entry "bar1" }'} | ${{}}
|
|
${''} | ${'dependencySet(group: "foo", version: "1.2.3") { { entry "bar1" } }'} | ${{}}
|
|
${''} | ${'dependencySet(group: "foo", version: "1.2.3") { entry(["bar1"]) }'} | ${{}}
|
|
${''} | ${'dependencySet(group: "foo", version: "1.2.3") { entry("bar", "baz") }'} | ${{}}
|
|
${''} | ${'dependencySet(group: "${nonexistingvar}", version: "1.2.3") { entry "bar1"; entry "bar2" }'} | ${{}}
|
|
${''} | ${'dependencySet(group: "foo", version: "1.2.3") { entry "bar1"; entry "bar2" }'} | ${validOutput}
|
|
${''} | ${'dependencySet(group: "foo", version: "1.2.3") { entry "bar1"; entry ("bar2") }'} | ${validOutput}
|
|
${'baz = "1.2.3"'} | ${'dependencySet(group: "foo", version: baz) { entry "bar1"; entry ("bar2") }'} | ${validOutput1}
|
|
${'baz = "1.2.3"'} | ${'dependencySet(group: "foo", version: "${baz}") { entry "bar1"; entry ("bar2") }'} | ${validOutput1}
|
|
${'baz = "1.2.3"'} | ${'dependencySet(group: "foo", version: property("baz")) { entry "bar1"; entry ("bar2") }'} | ${validOutput1}
|
|
${'some = "foo"; other = "bar1"'} | ${'dependencySet(group: some, version: "1.2.3") { entry other; entry "bar2" }'} | ${validOutput}
|
|
${'some = "foo"; baz = "1.2.3"'} | ${'dependencySet(group: some, version: "${baz}456") { entry "bar1"; entry "bar2" }'} | ${{}}
|
|
${'some = "foo"; other = "bar1"'} | ${'dependencySet(group: some, version: "1.2.3") { entry(other); entry "bar2" }'} | ${validOutput}
|
|
${'some = "foo"; other = "bar1"'} | ${'dependencySet(group: "${some}", version: "1.2.3") { entry "${other}"; entry "bar2" }'} | ${validOutput}
|
|
${'some = "foo"; other = "bar1"'} | ${'dependencySet(group: "${some}", version: "1.2.3") { entry("${other}"); entry "bar2" }'} | ${validOutput}
|
|
${''} | ${'dependencySet(group = "foo", version = "1.2.3") { entry "bar1"; entry "bar2" }'} | ${validOutput}
|
|
`('$def | $str', ({ def, str, output }) => {
|
|
const { deps } = parseGradle([def, str].join('\n'));
|
|
expect(deps).toMatchObject(output);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('plugins', () => {
|
|
it.each`
|
|
def | input | output
|
|
${''} | ${'id "foo.bar" version "1.2.3"'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'id("foo.bar").version("1.2.3")'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'id(["foo.bar"]) version "1.2.3"'} | ${null}
|
|
${''} | ${'id("foo", "bar") version "1.2.3"'} | ${null}
|
|
${''} | ${'id "foo".version("1.2.3")'} | ${null}
|
|
${''} | ${'id("foo.bar") version("1.2.3")'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'id("foo.bar") version "1.2.3"'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'id "foo.bar" version "$baz"'} | ${{ depName: 'foo.bar', skipReason: 'unspecified-version', currentValue: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'id "foo.bar" version "$baz"'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'id("foo.bar") version "$baz"'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'id "foo.bar" version "x${ab}cd"'} | ${{ depName: 'foo.bar', skipReason: 'unspecified-version' }}
|
|
${''} | ${'id("foo.bar") version "$baz"'} | ${{ depName: 'foo.bar', skipReason: 'unspecified-version', currentValue: 'baz' }}
|
|
${''} | ${'id("foo.bar") version "x${ab}cd"'} | ${{ depName: 'foo.bar', skipReason: 'unspecified-version' }}
|
|
${''} | ${'id("foo.bar") version "1" + "2.3"'} | ${{ depName: 'foo.bar', skipReason: 'unspecified-version' }}
|
|
${''} | ${'id("foo.bar") version property("qux")'} | ${{ depName: 'foo.bar', skipReason: 'unspecified-version' }}
|
|
${'baz = "1.2.3"'} | ${'id("foo.bar") version property("baz")'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'id "foo.bar" version baz'} | ${{ depName: 'foo.bar', currentValue: 'baz', skipReason: 'unspecified-version' }}
|
|
${'baz = "1.2.3"'} | ${'id "foo.bar" version baz'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'id("foo.bar") version baz'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'id("foo.bar").version(baz)'} | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
|
|
${''} | ${'kotlin("jvm") version "1.3.71"'} | ${{ depName: 'org.jetbrains.kotlin.jvm', packageName: 'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin', currentValue: '1.3.71' }}
|
|
${'baz = "1.3.71"'} | ${'kotlin("jvm") version baz'} | ${{ depName: 'org.jetbrains.kotlin.jvm', packageName: 'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin', currentValue: '1.3.71', groupName: 'baz' }}
|
|
`('$def | $input', ({ def, input, output }) => {
|
|
const { deps } = parseGradle([def, input].join('\n'));
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('registries', () => {
|
|
describe('predefined registries', () => {
|
|
it.each`
|
|
input | output
|
|
${'mavenCentral()'} | ${REGISTRY_URLS.mavenCentral}
|
|
${'google()'} | ${REGISTRY_URLS.google}
|
|
${'google { content { includeGroup "foo" } }'} | ${REGISTRY_URLS.google}
|
|
${'gradlePluginPortal()'} | ${REGISTRY_URLS.gradlePluginPortal}
|
|
${'jcenter()'} | ${REGISTRY_URLS.jcenter}
|
|
`('$input', ({ input, output }) => {
|
|
const { urls } = parseGradle(input);
|
|
expect(urls).toMatchObject([{ registryUrl: output }]);
|
|
});
|
|
});
|
|
|
|
describe('custom registries', () => {
|
|
it.each`
|
|
def | input | url
|
|
${''} | ${'maven("")'} | ${null}
|
|
${''} | ${'maven(["https://foo.bar/baz/qux"])'} | ${null}
|
|
${''} | ${'maven("foo", "bar")'} | ${null}
|
|
${''} | ${'maven("https://foo.bar/baz")'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven("${base}/baz")'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven(base)'} | ${'https://foo.bar'}
|
|
${''} | ${'maven(url = "https://foo.bar/baz")'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven(url = uri("https://foo.bar/baz"))'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven(uri("https://foo.bar/baz"))'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven(uri("${base}/baz"))'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven(uri(property("base")))'} | ${'https://foo.bar'}
|
|
${'base="https://foo.bar"'} | ${'maven(uri(base))'} | ${'https://foo.bar'}
|
|
${'base="https://foo.bar"'} | ${'maven(uri(base + "/baz"))'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven(uri(["https://foo.bar/baz"]))'} | ${null}
|
|
${''} | ${'maven { ["https://foo.bar/baz"] }'} | ${null}
|
|
${''} | ${'maven { url "https://foo.bar/baz" }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url base + "/baz" }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url "${base}/baz" }'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven { url uri("https://foo.bar/baz") }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url uri("${base}/baz") }'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven { url = "https://foo.bar/baz" }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url = "${base}/baz" }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url = property("base") }'} | ${'https://foo.bar'}
|
|
${'base="https://foo.bar"'} | ${'maven { url = base }'} | ${'https://foo.bar'}
|
|
${''} | ${'maven { url = uri("https://foo.bar/baz") }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url = uri("${base}/baz") }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { url = uri(base) }'} | ${'https://foo.bar'}
|
|
${''} | ${'maven { uri(["https://foo.bar/baz"]) }'} | ${null}
|
|
${'base="https://foo.bar"'} | ${'maven { name "baz"\nurl = "${base}/${name}" }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { name "${base}" + "/baz"\nurl = "${name}" + "/qux" }'} | ${'https://foo.bar/baz/qux'}
|
|
${'base="https://foo.bar"'} | ${'maven { name = "baz"\nurl = "${base}/${name}" }'} | ${'https://foo.bar/baz'}
|
|
${'some="baz"'} | ${'maven { name = "${some}"\nurl = "https://foo.bar/${name}" }'} | ${'https://foo.bar/baz'}
|
|
${'some="foo.bar/baz"'} | ${'maven { name = property("some")\nurl = "https://${name}" }'} | ${'https://foo.bar/baz'}
|
|
${'some="baz"'} | ${'maven { name = some\nurl = "https://foo.bar/${name}" }'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven { setUrl("https://foo.bar/baz") }'} | ${'https://foo.bar/baz'}
|
|
${''} | ${'maven { setUrl(uri("https://foo.bar/baz")) }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { setUrl("${base}/baz") }'} | ${'https://foo.bar/baz'}
|
|
${'base="https://foo.bar"'} | ${'maven { setUrl(project.property("base")) }'} | ${'https://foo.bar'}
|
|
${'base="https://foo.bar"'} | ${'maven { setUrl(base) }'} | ${'https://foo.bar'}
|
|
${''} | ${'maven { setUrl(["https://foo.bar/baz"]) }'} | ${null}
|
|
${''} | ${'maven { setUrl("foo", "bar") }'} | ${null}
|
|
${'base="https://foo.bar"'} | ${'publishing { repositories { maven("${base}/baz") } }'} | ${null}
|
|
`('$def | $input', ({ def, input, url }) => {
|
|
const expected = url ? [{ registryUrl: url }] : [];
|
|
const { urls } = parseGradle([def, input].join('\n'));
|
|
expect(urls).toMatchObject(expected);
|
|
});
|
|
});
|
|
|
|
it('pluginManagement', () => {
|
|
const input = codeBlock`
|
|
pluginManagement {
|
|
def fooVersion = "1.2.3"
|
|
repositories {
|
|
mavenLocal()
|
|
maven { url = "https://foo.bar/plugins" }
|
|
gradlePluginPortal()
|
|
}
|
|
plugins {
|
|
id("foo.bar") version "$fooVersion"
|
|
}
|
|
}
|
|
dependencyResolutionManagement {
|
|
repositories {
|
|
maven { url = "https://foo.bar/deps" }
|
|
mavenCentral()
|
|
}
|
|
}
|
|
`;
|
|
|
|
const { deps, urls } = parseGradle(input);
|
|
expect(deps).toMatchObject([
|
|
{
|
|
depType: 'plugin',
|
|
depName: 'foo.bar',
|
|
currentValue: '1.2.3',
|
|
},
|
|
]);
|
|
expect(urls).toMatchObject([
|
|
{
|
|
registryUrl: 'https://foo.bar/plugins',
|
|
scope: 'plugin',
|
|
},
|
|
{
|
|
registryUrl: REGISTRY_URLS.gradlePluginPortal,
|
|
scope: 'plugin',
|
|
},
|
|
{
|
|
registryUrl: 'https://foo.bar/deps',
|
|
scope: 'dep',
|
|
},
|
|
{
|
|
registryUrl: REGISTRY_URLS.mavenCentral,
|
|
scope: 'dep',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('version catalog', () => {
|
|
it.each`
|
|
def | str | output
|
|
${''} | ${'library("foo.bar", "foo", "bar").version("1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'library("foo.bar", "foo", "bar").version(baz)'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'library("foo.bar", "foo", "bar").version("${baz}")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'library("foo.bar", "foo", "bar").version(property("baz"))'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'library("foo.bar", "foo", "bar").version("${baz}xy")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3xy', skipReason: 'unspecified-version' }}
|
|
${'baz = "1.2.3"'} | ${'library("foo.bar", "foo", "bar").version(baz + ".45")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3.45', skipReason: 'unspecified-version' }}
|
|
${'group = "foo"; artifact = "bar"'} | ${'library("foo.bar", group, artifact).version("1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'f = "foo"; b = "bar"'} | ${'library("foo.bar", "${f}", "${b}").version("1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'f = "foo"; b = "bar"; v = "1.2.3"'} | ${'library("foo.bar", property("f"), "${b}").version(v)'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'f = "foo"; b = "bar"'} | ${'library("foo.bar", "${f}" + f, "${b}").version("1.2.3")'} | ${{ depName: 'foofoo:bar', currentValue: '1.2.3' }}
|
|
${'version("baz", "1.2.3")'} | ${'library("foo.bar", "foo", "bar").versionRef("baz")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'library("foo-bar_baz-qux", "foo", "bar")'} | ${'"${libs.foo.bar.baz.qux}:1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${''} | ${'library(["foo.bar", "foo", "bar"]).version("1.2.3")'} | ${null}
|
|
${''} | ${'library("foo", "bar", "baz", "qux").version("1.2.3")'} | ${null}
|
|
${''} | ${'library("foo.bar", "foo", "bar").version("1.2.3", "4.5.6")'} | ${null}
|
|
${''} | ${'library("foo", bar, "baz").version("1.2.3")'} | ${null}
|
|
${''} | ${'plugin("foo.bar", "foo")'} | ${null}
|
|
${''} | ${'plugin("foo.bar", "foo").version("1.2.3")'} | ${{ depName: 'foo', currentValue: '1.2.3' }}
|
|
${''} | ${'alias("foo.bar").to("foo", "bar").version("1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'version("baz", "1.2.3")'} | ${'alias("foo.bar").to("foo", "bar").versionRef("baz")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'version("baz", "1.2.3")'} | ${'alias("foo.bar").to("foo", "bar").version("${baz}")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'f = "foo"; b = "bar"; v = "1.2.3"'} | ${'alias("foo.bar").to(f, b).version(v)'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'f = "foo"; b = "bar"; v = "1.2.3"'} | ${'alias("foo.bar").to(f + b, b + f).version(v)'} | ${{ depName: 'foobar:barfoo', currentValue: '1.2.3' }}
|
|
${'f = "foo"; b = "bar"; v = "1.2.3"'} | ${'alias("foo.bar").to("${f}", "${b}").version("$v")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${''} | ${'alias(["foo.bar"]).to("foo", "bar").version("1.2.3")'} | ${null}
|
|
`('$def | $str', ({ def, str, output }) => {
|
|
const input = [def, str].join('\n');
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
|
|
describe('heuristic dependency matching', () => {
|
|
it.each`
|
|
input | output
|
|
${'("foo", "bar", "1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'("foo", "bar", "1.2.3", "4.5.6")'} | ${null}
|
|
${'(["foo", "bar", "1.2.3"])'} | ${null}
|
|
${'someMethod("foo", "bar", "1.2.3")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
|
|
${'listOf("foo", "bar", "baz")'} | ${null}
|
|
`('$input', ({ input, output }) => {
|
|
const { deps } = parseGradle(input);
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
|
|
describe('calculations', () => {
|
|
it('calculates offset', () => {
|
|
const content = "'foo:bar:1.2.3'";
|
|
const { deps } = parseGradle(content);
|
|
const [res] = deps;
|
|
const idx = content
|
|
// TODO #22198
|
|
.slice(res.managerData!.fileReplacePosition)
|
|
.indexOf('1.2.3');
|
|
expect(idx).toBe(0);
|
|
});
|
|
|
|
it('parses fixture from "gradle" manager', () => {
|
|
const content = Fixtures.get('build.gradle.example1');
|
|
const { deps } = parseGradle(content, {}, 'build.gradle');
|
|
const replacementIndices = deps.map(({ managerData, currentValue }) =>
|
|
// TODO #22198
|
|
content.slice(managerData!.fileReplacePosition).indexOf(currentValue!),
|
|
);
|
|
expect(replacementIndices.every((idx) => idx === 0)).toBeTrue();
|
|
expect(deps).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe('gradle.properties', () => {
|
|
it.each`
|
|
input | key | value | fileReplacePosition
|
|
${'foo=bar'} | ${'foo'} | ${'bar'} | ${4}
|
|
${' foo = bar '} | ${'foo'} | ${'bar'} | ${7}
|
|
${'foo.bar=baz'} | ${'foo.bar'} | ${'baz'} | ${8}
|
|
${'foo.bar:baz'} | ${'foo.bar'} | ${'baz'} | ${8}
|
|
${'foo.bar baz'} | ${'foo.bar'} | ${'baz'} | ${8}
|
|
`('$input', ({ input, key, value, fileReplacePosition }) => {
|
|
expect(parseProps(input)).toMatchObject({
|
|
vars: { [key]: { key, value, fileReplacePosition } },
|
|
});
|
|
});
|
|
|
|
it('handles multi-line file', () => {
|
|
expect(parseProps('foo=foo\nbar=bar')).toMatchObject({
|
|
vars: {
|
|
foo: { key: 'foo', value: 'foo', fileReplacePosition: 4 },
|
|
bar: { key: 'bar', value: 'bar', fileReplacePosition: 12 },
|
|
},
|
|
deps: [],
|
|
});
|
|
});
|
|
|
|
it('attaches packageFile', () => {
|
|
expect(
|
|
parseProps('foo = bar', 'foo/bar/gradle.properties'),
|
|
).toMatchObject({
|
|
vars: { foo: { packageFile: 'foo/bar/gradle.properties' } },
|
|
});
|
|
});
|
|
|
|
it('parses dependencies', () => {
|
|
const res = parseProps('dep = foo:bar:1.2.3');
|
|
|
|
expect(res).toMatchObject({
|
|
deps: [
|
|
{
|
|
currentValue: '1.2.3',
|
|
depName: 'foo:bar',
|
|
managerData: { fileReplacePosition: 14 },
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('apply from', () => {
|
|
const key = 'version';
|
|
const value = '1.2.3';
|
|
const validOutput = {
|
|
version: {
|
|
key,
|
|
value,
|
|
fileReplacePosition: 11,
|
|
packageFile: 'foo/bar.gradle',
|
|
},
|
|
};
|
|
|
|
const fileContents = {
|
|
'foo/bar.gradle': key + ' = "' + value + '"',
|
|
};
|
|
|
|
it.each`
|
|
def | input | output
|
|
${''} | ${'apply from: ""'} | ${{}}
|
|
${''} | ${'apply from: "foo/invalid.gradle"'} | ${{}}
|
|
${''} | ${'apply from: "${base}"'} | ${{}}
|
|
${''} | ${'apply from: "foo/invalid.non-gradle"'} | ${{}}
|
|
${''} | ${'apply from: "https://someurl.com/file.gradle"'} | ${{}}
|
|
${''} | ${'apply from: "foo/bar.gradle"'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply from: "${base}/bar.gradle"'} | ${validOutput}
|
|
${'path="foo/bar.gradle"'} | ${'apply from: path'} | ${validOutput}
|
|
${'path="bar.gradle"'} | ${'apply from: "foo/" + path'} | ${validOutput}
|
|
${'path="foo/bar.gradle"'} | ${'apply from: property("path")'} | ${validOutput}
|
|
${''} | ${'apply from: file("foo/bar.gradle")'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply from: file("${base}/bar.gradle")'} | ${validOutput}
|
|
${''} | ${'apply from: project.file("foo/bar.gradle")'} | ${validOutput}
|
|
${''} | ${'apply from: rootProject.file("foo/bar.gradle")'} | ${validOutput}
|
|
${''} | ${'apply from: new File("foo/bar.gradle")'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply from: new File("${base}/bar.gradle")'} | ${validOutput}
|
|
${''} | ${'apply from: new File("foo", "bar.gradle")'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply from: new File(base, "bar.gradle")'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply from: new File("${base}", "bar.gradle")'} | ${validOutput}
|
|
${'path="bar.gradle"'} | ${'apply from: new File("foo", "${path}")'} | ${validOutput}
|
|
${'e="o"; b="gradle" '} | ${'apply from: new File("f" + e + e, "bar." + b)'} | ${validOutput}
|
|
${'a="bar"; b="gradle"'} | ${'apply from: new File("foo", a + "." + "${b}")'} | ${validOutput}
|
|
${'path="bar.gradle"'} | ${'apply from: new File("foo", property("path"))'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply from: new File(property("base"), "bar.gradle")'} | ${validOutput}
|
|
${''} | ${'apply(from = "foo/bar.gradle"))'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply(from = "${base}/bar.gradle"))'} | ${validOutput}
|
|
${''} | ${'apply(from = File("foo/bar.gradle"))'} | ${validOutput}
|
|
${''} | ${'apply(from = File("foo", "bar", "baz"))'} | ${{}}
|
|
${''} | ${'apply(from = File(["${somedir}/foo.gradle"]))'} | ${{}}
|
|
${'base="foo"'} | ${'apply(from = File("${base}/bar.gradle"))'} | ${validOutput}
|
|
${''} | ${'apply(from = File("foo", "bar.gradle"))'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply(from = File(base, "bar.gradle"))'} | ${validOutput}
|
|
${'base="foo"'} | ${'apply(from = File("${base}", "bar.gradle"))'} | ${validOutput}
|
|
`('$def | $input', ({ def, input, output }) => {
|
|
mockFs(fileContents);
|
|
const { vars } = parseGradle(
|
|
[def, input].join('\n'),
|
|
{},
|
|
'',
|
|
fileContents,
|
|
);
|
|
expect(vars).toMatchObject(output);
|
|
});
|
|
|
|
it('recursion check', () => {
|
|
const { vars } = parseGradle(
|
|
'apply from: "foo/bar.gradle"',
|
|
{},
|
|
'',
|
|
fileContents,
|
|
3,
|
|
);
|
|
expect(logger.logger.debug).toHaveBeenCalledWith(
|
|
'Max recursion depth reached in script file: foo/bar.gradle',
|
|
);
|
|
expect(vars).toBeEmpty();
|
|
});
|
|
});
|
|
|
|
describe('implicit gradle plugins', () => {
|
|
it.each`
|
|
def | input | output
|
|
${'baz = "1.2.3"'} | ${'checkstyle { toolVersion = "${baz}" }'} | ${{ depName: 'checkstyle', packageName: GRADLE_PLUGINS['checkstyle'][1], currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'checkstyle { toolVersion "${baz}" }'} | ${{ depName: 'checkstyle', packageName: GRADLE_PLUGINS['checkstyle'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'codenarc { toolVersion = "1.2.3" }'} | ${{ depName: 'codenarc', packageName: GRADLE_PLUGINS['codenarc'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'detekt { toolVersion = "1.2.3" }'} | ${{ depName: 'detekt', packageName: GRADLE_PLUGINS['detekt'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'findbugs { toolVersion = "1.2.3" }'} | ${{ depName: 'findbugs', packageName: GRADLE_PLUGINS['findbugs'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'googleJavaFormat { toolVersion = "1.2.3" }'} | ${{ depName: 'googleJavaFormat', packageName: GRADLE_PLUGINS['googleJavaFormat'][1], currentValue: '1.2.3' }}
|
|
${'baz = "1.2.3"'} | ${'jacoco { toolVersion = baz }'} | ${{ depName: 'jacoco', packageName: GRADLE_PLUGINS['jacoco'][1], currentValue: '1.2.3', groupName: 'baz' }}
|
|
${'baz = "1.2.3"'} | ${'jacoco { toolVersion = property("baz") }'} | ${{ depName: 'jacoco', packageName: GRADLE_PLUGINS['jacoco'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'lombok { version = "1.2.3" }'} | ${{ depName: 'lombok', packageName: GRADLE_PLUGINS['lombok'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'lombok { version.set("1.2.3") }'} | ${{ depName: 'lombok', packageName: GRADLE_PLUGINS['lombok'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'lombok { version.value("1.2.3") }'} | ${{ depName: 'lombok', packageName: GRADLE_PLUGINS['lombok'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'pmd { toolVersion = "1.2.3" }'} | ${{ depName: 'pmd', packageName: GRADLE_PLUGINS['pmd'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'pmd { toolVersion.set("1.2.3") }'} | ${{ depName: 'pmd', packageName: GRADLE_PLUGINS['pmd'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'pmd { toolVersion.value("1.2.3") }'} | ${{ depName: 'pmd', packageName: GRADLE_PLUGINS['pmd'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'pmd { foo = "bar"; toolVersion = "1.2.3" }'} | ${{ depName: 'pmd', packageName: GRADLE_PLUGINS['pmd'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'spotbugs { toolVersion = "1.2.3" }'} | ${{ depName: 'spotbugs', packageName: GRADLE_PLUGINS['spotbugs'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'pmd { toolVersion = "@@@" }'} | ${null}
|
|
${''} | ${'pmd { toolVersion = "${baz}" }'} | ${null}
|
|
${'baz = "1.2.3"'} | ${'pmd { toolVersion = "${baz}.456" }'} | ${{ depName: 'pmd', currentValue: '1.2.3.456', skipReason: 'unspecified-version' }}
|
|
${'baz = "1.2.3"'} | ${'pmd { toolVersion = baz + ".456" }'} | ${{ depName: 'pmd', currentValue: '1.2.3.456', skipReason: 'unspecified-version' }}
|
|
${''} | ${'pmd { [toolVersion = "6.36.0"] }'} | ${null}
|
|
${''} | ${'unknown { toolVersion = "1.2.3" }'} | ${null}
|
|
${''} | ${'composeOptions { kotlinCompilerExtensionVersion = "1.2.3" }'} | ${{ depName: 'composeOptions', packageName: GRADLE_PLUGINS['composeOptions'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'jmh { jmhVersion = "1.2.3" }'} | ${{ depName: 'jmh', packageName: GRADLE_PLUGINS['jmh'][1], currentValue: '1.2.3' }}
|
|
${''} | ${'micronaut { version = "1.2.3" }'} | ${{ depName: 'micronaut', packageName: GRADLE_PLUGINS['micronaut'][1], currentValue: '1.2.3' }}
|
|
`('$def | $input', ({ def, input, output }) => {
|
|
const { deps } = parseGradle([def, input].join('\n'));
|
|
expect(deps).toMatchObject([output].filter(is.truthy));
|
|
});
|
|
});
|
|
|
|
describe('Kotlin object notation', () => {
|
|
it('simple objects', () => {
|
|
const input = codeBlock`
|
|
object Versions {
|
|
const val baz = "1.2.3"
|
|
}
|
|
|
|
object Libraries {
|
|
val deps = mapOf("api" to "org.slf4j:slf4j-api:\${Versions.baz}")
|
|
val deps2 = listOf(
|
|
"androidx.appcompat:appcompat:4.5.6",
|
|
"androidx.core:core-ktx:\${Versions.baz}",
|
|
listOf("androidx.webkit:webkit:\${Versions.baz}")
|
|
)
|
|
val dep: String = "foo:bar:" + Versions.baz
|
|
}
|
|
`;
|
|
|
|
const res = parseKotlinSource(input);
|
|
expect(res).toMatchObject({
|
|
vars: {
|
|
'Versions.baz': {
|
|
key: 'Versions.baz',
|
|
value: '1.2.3',
|
|
},
|
|
},
|
|
deps: [
|
|
{
|
|
depName: 'org.slf4j:slf4j-api',
|
|
groupName: 'Versions.baz',
|
|
currentValue: '1.2.3',
|
|
},
|
|
{
|
|
depName: 'androidx.appcompat:appcompat',
|
|
currentValue: '4.5.6',
|
|
},
|
|
{
|
|
depName: 'androidx.core:core-ktx',
|
|
groupName: 'Versions.baz',
|
|
currentValue: '1.2.3',
|
|
},
|
|
{
|
|
depName: 'androidx.webkit:webkit',
|
|
groupName: 'Versions.baz',
|
|
currentValue: '1.2.3',
|
|
},
|
|
{
|
|
depName: 'foo:bar',
|
|
groupName: 'Versions.baz',
|
|
currentValue: '1.2.3',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('nested objects', () => {
|
|
const input = codeBlock`
|
|
object Deps {
|
|
const val kotlinVersion = "1.5.31"
|
|
|
|
object Kotlin {
|
|
val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:\${Deps.kotlinVersion}"
|
|
}
|
|
|
|
object Test {
|
|
private const val version = "1.3.0-rc01"
|
|
const val core = "androidx.test:core:\${Deps.Test.version}"
|
|
|
|
object Espresso {
|
|
object Release {
|
|
private const val version = "3.3.0-rc01"
|
|
const val espressoCore = "androidx.test.espresso:espresso-core:$version"
|
|
}
|
|
}
|
|
|
|
object Androidx {
|
|
const val coreKtx = "androidx.test:core-ktx:$version"
|
|
}
|
|
}
|
|
}
|
|
`;
|
|
|
|
const res = parseKotlinSource(input);
|
|
expect(res).toMatchObject({
|
|
vars: {
|
|
'Deps.kotlinVersion': {
|
|
key: 'Deps.kotlinVersion',
|
|
value: '1.5.31',
|
|
},
|
|
'Deps.Test.version': {
|
|
key: 'Deps.Test.version',
|
|
value: '1.3.0-rc01',
|
|
},
|
|
'Deps.Test.Espresso.Release.version': {
|
|
key: 'Deps.Test.Espresso.Release.version',
|
|
value: '3.3.0-rc01',
|
|
},
|
|
},
|
|
deps: [
|
|
{
|
|
depName: 'org.jetbrains.kotlin:kotlin-stdlib-jdk7',
|
|
currentValue: '1.5.31',
|
|
groupName: 'Deps.kotlinVersion',
|
|
},
|
|
{
|
|
depName: 'androidx.test:core',
|
|
currentValue: '1.3.0-rc01',
|
|
groupName: 'Deps.Test.version',
|
|
},
|
|
{
|
|
depName: 'androidx.test.espresso:espresso-core',
|
|
currentValue: '3.3.0-rc01',
|
|
groupName: 'Deps.Test.Espresso.Release.version',
|
|
},
|
|
{
|
|
depName: 'androidx.test:core-ktx',
|
|
currentValue: '1.3.0-rc01',
|
|
groupName: 'Deps.Test.version',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it('imported objects', () => {
|
|
const input = codeBlock`
|
|
object ModuleConfiguration {
|
|
object Build {
|
|
object Database {
|
|
const val h2Version = "2.0.206"
|
|
}
|
|
}
|
|
}
|
|
`;
|
|
|
|
const gradleKtsInput = codeBlock`
|
|
import ModuleConfiguration.Build.Database
|
|
dependencies {
|
|
runtimeOnly("com.h2database:h2:\${Database.h2Version}")
|
|
}
|
|
`;
|
|
|
|
const { vars } = parseKotlinSource(input);
|
|
const res = parseGradle(gradleKtsInput, vars);
|
|
expect(res).toMatchObject({
|
|
vars: {
|
|
'ModuleConfiguration.Build.Database.h2Version': {
|
|
key: 'ModuleConfiguration.Build.Database.h2Version',
|
|
value: '2.0.206',
|
|
},
|
|
},
|
|
deps: [
|
|
{
|
|
depName: 'com.h2database:h2',
|
|
currentValue: '2.0.206',
|
|
groupName: 'ModuleConfiguration.Build.Database.h2Version',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
});
|