Skip to content

Commit 62cfb4d

Browse files
authored
Add exact targeting for Gradle (#85)
* Working on exact * Working on exact gradle targeting #69 * Tests for #69
1 parent 834415a commit 62cfb4d

File tree

8 files changed

+909
-217
lines changed

8 files changed

+909
-217
lines changed

package-lock.json

Lines changed: 590 additions & 201 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/common/test/fixtures/ios-and-android/android/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ allprojects {
2323
}
2424
}
2525

26+
dependencies {
27+
}
28+
2629
task clean(type: Delete) {
2730
delete rootProject.buildDir
2831
}

packages/configure/src/definitions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export interface AndroidGradleOperation extends Operation {
2222
file: string;
2323
target: any;
2424
insert?: string | any[];
25-
replace?: string | any[];
25+
replace?: string | any;
26+
exact?: boolean;
2627
}[];
2728
}
2829

packages/configure/src/operations/android/gradle.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ export default async function execute(ctx: Context, op: Operation) {
1313
}
1414

1515
if (entry.replace) {
16-
await gradleFile.replaceProperties(entry.target, entry.replace);
16+
await gradleFile.replaceProperties(entry.target, entry.replace, entry.exact);
1717
} else if (typeof entry.insert === 'string') {
18-
await gradleFile.insertFragment(entry.target, entry.insert);
18+
await gradleFile.insertFragment(entry.target, entry.insert, entry.exact);
1919
} else if (Array.isArray(entry.insert)) {
20-
await gradleFile.insertProperties(entry.target, entry.insert);
20+
await gradleFile.insertProperties(entry.target, entry.insert, entry.exact);
2121
} else {
2222
throw new Error(`Invalid \'insert\' type for gradle operation. Must be a string or array of objects: ${JSON.stringify(entry.insert, null, 2)}`);
2323
}
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import { copy } from '@ionic/utils-fs';
2+
import { GradleFile } from '@trapezedev/project/dist/android/gradle-file';
3+
import { join } from 'path';
4+
import tempy from 'tempy';
5+
6+
import { Context, loadContext } from '../../src/ctx';
7+
import { AndroidGradleOperation, Operation } from '../../src/definitions';
8+
import Op from '../../src/operations/android/gradle';
9+
10+
const makeOp = (name: string, value: any): Operation => ({
11+
id: `android.${name}`,
12+
platform: 'android',
13+
name,
14+
value,
15+
iosTarget: null,
16+
iosBuild: null,
17+
displayText: expect.anything(),
18+
});
19+
20+
describe('op: android.gralde', () => {
21+
let dir: string;
22+
let ctx: Context;
23+
24+
beforeEach(async () => {
25+
dir = tempy.directory();
26+
27+
await copy('../common/test/fixtures/ios-and-android', dir);
28+
29+
ctx = await loadContext(dir);
30+
ctx.args.quiet = true;
31+
});
32+
33+
it('Should replace', async () => {
34+
const op: AndroidGradleOperation = makeOp('gradle', [
35+
{
36+
file: 'app/build.gradle',
37+
target: {
38+
android: {
39+
buildTypes: {
40+
implementation: {}
41+
}
42+
}
43+
},
44+
replace: {
45+
implementation: "'test-implementation'"
46+
}
47+
},
48+
]);
49+
50+
await Op(ctx, op as Operation);
51+
52+
const file = ctx.project.vfs.get<GradleFile>(join(dir, 'android/app/build.gradle'));
53+
expect(file?.getData()?.getDocument()?.trim()).toEqual(`
54+
apply plugin: 'com.android.application'
55+
56+
android {
57+
compileSdkVersion rootProject.ext.compileSdkVersion
58+
defaultConfig {
59+
applicationId "io.ionic.starter"
60+
minSdkVersion rootProject.ext.minSdkVersion
61+
targetSdkVersion rootProject.ext.targetSdkVersion
62+
versionCode 56
63+
versionName "1.2.3"
64+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
65+
aaptOptions {
66+
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
67+
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
68+
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
69+
}
70+
}
71+
buildTypes {
72+
release {
73+
minifyEnabled false
74+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
75+
}
76+
implementation 'test-implementation'
77+
}
78+
}
79+
80+
repositories {
81+
flatDir{
82+
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
83+
}
84+
}
85+
86+
dependencies {
87+
implementation fileTree(include: ['*.jar'], dir: 'libs')
88+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
89+
implementation project(':capacitor-android')
90+
testImplementation "junit:junit:$junitVersion"
91+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
92+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
93+
implementation project(':capacitor-cordova-android-plugins')
94+
}
95+
96+
apply from: 'capacitor.build.gradle'
97+
98+
try {
99+
def servicesJSON = file('google-services.json')
100+
if (servicesJSON.text) {
101+
apply plugin: 'com.google.gms.google-services'
102+
}
103+
} catch(Exception e) {
104+
logger.warn("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
105+
}`.trim()
106+
);
107+
});
108+
109+
it('Should non-exact insert', async () => {
110+
const op: AndroidGradleOperation = makeOp('gradle', [
111+
{
112+
file: 'build.gradle',
113+
target: {
114+
dependencies: {}
115+
},
116+
insert: [{
117+
implementation: "'test-implementation'"
118+
}]
119+
},
120+
]);
121+
122+
await Op(ctx, op as Operation);
123+
124+
const file = ctx.project.vfs.get<GradleFile>(join(dir, 'android/build.gradle'));
125+
expect(file?.getData()?.getDocument()?.trim()).toEqual(`
126+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
127+
128+
buildscript {
129+
repositories {
130+
google()
131+
jcenter()
132+
}
133+
dependencies {
134+
classpath 'com.android.tools.build:gradle:4.2.1'
135+
classpath 'com.google.gms:google-services:4.3.5'
136+
137+
// NOTE: Do not place your application dependencies here; they belong
138+
// in the individual module build.gradle files
139+
implementation 'test-implementation'
140+
}
141+
}
142+
143+
apply from: "variables.gradle"
144+
145+
allprojects {
146+
repositories {
147+
google()
148+
jcenter()
149+
}
150+
}
151+
152+
dependencies {
153+
}
154+
155+
task clean(type: Delete) {
156+
delete rootProject.buildDir
157+
}
158+
`.trim()
159+
);
160+
});
161+
162+
it('Should exact insert', async () => {
163+
const op: AndroidGradleOperation = makeOp('gradle', [
164+
{
165+
file: 'build.gradle',
166+
target: {
167+
dependencies: {}
168+
},
169+
insert: [{
170+
implementation: "'test-implementation'"
171+
}],
172+
exact: true
173+
},
174+
]);
175+
176+
await Op(ctx, op as Operation);
177+
178+
const file = ctx.project.vfs.get<GradleFile>(join(dir, 'android/build.gradle'));
179+
expect(file?.getData()?.getDocument()?.trim()).toEqual(`
180+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
181+
182+
buildscript {
183+
repositories {
184+
google()
185+
jcenter()
186+
}
187+
dependencies {
188+
classpath 'com.android.tools.build:gradle:4.2.1'
189+
classpath 'com.google.gms:google-services:4.3.5'
190+
191+
// NOTE: Do not place your application dependencies here; they belong
192+
// in the individual module build.gradle files
193+
}
194+
}
195+
196+
apply from: "variables.gradle"
197+
198+
allprojects {
199+
repositories {
200+
google()
201+
jcenter()
202+
}
203+
}
204+
205+
dependencies {
206+
implementation 'test-implementation'
207+
}
208+
209+
task clean(type: Delete) {
210+
delete rootProject.buildDir
211+
}
212+
`.trim()
213+
);
214+
});
215+
});
0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)