Skip to content

Commit 0888d28

Browse files
Merge pull request #99 from contentstack/development
Development
2 parents 1097f41 + 2018270 commit 0888d28

File tree

77 files changed

+28007
-48
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+28007
-48
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# CHANGELOG
22

3+
## Version 4.2.0
4+
5+
### Date: 02-Mar-2026
6+
7+
- Added asset localisation support
8+
39
## Version 4.1.0
410

511
### Date: 15-Sept-2025

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2012 - 2025 Contentstack
3+
Copyright (c) 2012 - 2026 Contentstack
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
buildscript {
22
ext {
3-
jacoco_version = '0.8.8'
3+
jacoco_version = '0.8.12'
44
agp_version = '8.2.1'
55
}
66
repositories {

contentstack/build.gradle

Lines changed: 201 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
plugins {
22
id "com.android.library"
33
id "com.vanniktech.maven.publish" version "0.33.0"
4+
id 'jacoco'
45
}
56

67
ext {
78
PUBLISH_GROUP_ID = 'com.contentstack.sdk'
89
PUBLISH_ARTIFACT_ID = 'android'
9-
PUBLISH_VERSION = '4.1.0'
10+
PUBLISH_VERSION = '4.2.0'
1011
}
1112

1213
android {
1314
namespace "com.contentstack.sdk"
1415
compileSdk 34 // Using latest stable Android SDK version
16+
17+
// SDK compiles to Java 17 for JaCoCo compatibility
18+
// But can be built with Java 21 - tests use Java 17 toolchain
19+
compileOptions {
20+
coreLibraryDesugaringEnabled true
21+
sourceCompatibility JavaVersion.VERSION_17
22+
targetCompatibility JavaVersion.VERSION_17
23+
}
24+
1525
buildFeatures {
1626
buildConfig true
1727
}
@@ -30,10 +40,15 @@ android {
3040
}
3141

3242
testOptions {
33-
unitTests.all {
34-
// jacoco {
35-
// includeNoLocationClasses = true
36-
// }
43+
unitTests {
44+
includeAndroidResources = true
45+
returnDefaultValues = true
46+
all {
47+
jacoco {
48+
includeNoLocationClasses = true
49+
excludes = ['jdk.internal.*']
50+
}
51+
}
3752
}
3853
}
3954
// signing {
@@ -109,18 +124,37 @@ dependencies {
109124
def multidex = "2.0.1"
110125
def volley = "1.2.1"
111126
def junit = "4.13.2"
127+
def mockito = "5.2.0"
128+
def mockitoKotlin = "2.2.0"
112129
configurations.configureEach { resolutionStrategy.force 'com.android.support:support-annotations:23.1.0' }
113130
implementation fileTree(include: ['*.jar'], dir: 'libs')
114131
implementation "com.android.volley:volley:$volley"
115132
implementation "junit:junit:$junit"
116133

117134
// For AGP 7.4+
118135
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
136+
137+
// Unit Testing Dependencies
119138
testImplementation 'junit:junit:4.13.2'
139+
testImplementation "org.mockito:mockito-core:$mockito"
140+
testImplementation "org.mockito:mockito-inline:$mockito"
141+
testImplementation 'org.mockito:mockito-android:5.2.0'
142+
testImplementation 'org.robolectric:robolectric:4.15' // Updated to fix security vulnerabilities
143+
testImplementation 'androidx.test:core:1.5.0'
144+
testImplementation 'androidx.test:runner:1.5.2'
145+
testImplementation 'androidx.test.ext:junit:1.1.5'
146+
testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'
147+
testImplementation 'org.json:json:20231013'
148+
// PowerMock for advanced mocking
149+
testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
150+
testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
151+
testImplementation 'org.powermock:powermock-core:2.0.9'
152+
153+
// Android Test Dependencies
120154
androidTestImplementation 'androidx.test:core:1.5.0'
121-
testImplementation 'org.robolectric:robolectric:4.6.1'
122-
123-
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
155+
androidTestImplementation 'androidx.test:runner:1.5.2'
156+
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
157+
androidTestImplementation('androidx.test.espresso:espresso-core:3.5.1', {
124158
exclude group: 'com.android.support', module: 'support-annotations'
125159
})
126160

@@ -200,22 +234,170 @@ mavenPublishing {
200234
}
201235
}
202236

237+
jacoco {
238+
toolVersion = "0.8.12"
239+
}
240+
203241
tasks.register('jacocoTestReport', JacocoReport) {
204-
dependsOn('testDebugUnitTest', 'createDebugCoverageReport')
242+
dependsOn('testDebugUnitTest')
243+
205244
reports {
245+
xml.required = true
206246
html.required = true
247+
csv.required = false
248+
249+
xml.outputLocation = file("${buildDir}/reports/jacoco/jacocoTestReport/jacocoTestReport.xml")
250+
html.outputLocation = file("${buildDir}/reports/jacoco/jacocoTestReport/html")
207251
}
252+
253+
def excludePatterns = [
254+
'**/R.class',
255+
'**/R$*.class',
256+
'**/BuildConfig.*',
257+
'**/Manifest*.*',
258+
'**/*Test*.*',
259+
'android/**/*.*',
260+
'**/*$ViewInjector*.*',
261+
'**/*$ViewBinder*.*',
262+
'**/Lambda$*.class',
263+
'**/Lambda.class',
264+
'**/*Lambda.class',
265+
'**/*Lambda*.class',
266+
'**/*_MembersInjector.class',
267+
'**/Dagger*Component*.*',
268+
'**/*Module_*Factory.class',
269+
'**/AutoValue_*.*',
270+
'**/*JavascriptBridge.class',
271+
'**/package-info.class',
272+
'**/TestActivity.class',
273+
// External library exclusions
274+
'**/okhttp/**',
275+
'**/okio/**',
276+
'**/txtmark/**',
277+
'**/retrofit2/**',
278+
'**/volley/**',
279+
'**/CSConnectionRequest.class',
280+
// Exclude callback interfaces and their anonymous implementations
281+
'**/SyncResultCallBack.class',
282+
'**/Stack$*.class'
283+
]
284+
285+
sourceDirectories.setFrom(files([
286+
"${project.projectDir}/src/main/java"
287+
]))
288+
289+
classDirectories.setFrom(files([
290+
fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: excludePatterns),
291+
fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: excludePatterns)
292+
]))
293+
294+
executionData.setFrom(fileTree(buildDir).include([
295+
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
296+
"jacoco/testDebugUnitTest.exec"
297+
]))
208298
}
209299

210-
// Configure jacocoTestReport after evaluation when classDirectories is available
211-
project.afterEvaluate {
212-
tasks.named('jacocoTestReport', JacocoReport) {
213-
classDirectories.setFrom(files(classDirectories.files.collect {
214-
fileTree(dir: it, exclude: [
215-
'**com/contentstack/okhttp**',
216-
'**com/contentstack/okio**',
217-
'**com/contentstack/txtmark**'
218-
])
219-
}))
300+
// Combined coverage report for both unit and instrumentation tests
301+
tasks.register('jacocoCombinedReport', JacocoReport) {
302+
// This task can run after both test types complete
303+
// Make it depend on both if they're being run
304+
group = "Reporting"
305+
description = "Generate Jacoco coverage reports for both unit and instrumentation tests"
306+
307+
reports {
308+
xml.required = true
309+
html.required = true
310+
csv.required = false
311+
312+
xml.outputLocation = file("${buildDir}/reports/jacoco/jacocoCombinedReport/jacocoCombinedReport.xml")
313+
html.outputLocation = file("${buildDir}/reports/jacoco/jacocoCombinedReport/html")
220314
}
315+
316+
def excludePatterns = [
317+
'**/R.class',
318+
'**/R$*.class',
319+
'**/BuildConfig.*',
320+
'**/Manifest*.*',
321+
'**/*Test*.*',
322+
'android/**/*.*',
323+
'**/*$ViewInjector*.*',
324+
'**/*$ViewBinder*.*',
325+
'**/Lambda$*.class',
326+
'**/Lambda.class',
327+
'**/*Lambda.class',
328+
'**/*Lambda*.class',
329+
'**/*_MembersInjector.class',
330+
'**/Dagger*Component*.*',
331+
'**/*Module_*Factory.class',
332+
'**/AutoValue_*.*',
333+
'**/*JavascriptBridge.class',
334+
'**/package-info.class',
335+
'**/TestActivity.class',
336+
// External library exclusions
337+
'**/okhttp/**',
338+
'**/okio/**',
339+
'**/txtmark/**',
340+
'**/retrofit2/**',
341+
'**/volley/**',
342+
'**/CSConnectionRequest.class',
343+
// Exclude callback interfaces and their anonymous implementations
344+
'**/SyncResultCallBack.class',
345+
'**/Stack$*.class'
346+
]
347+
348+
sourceDirectories.setFrom(files([
349+
"${project.projectDir}/src/main/java"
350+
]))
351+
352+
classDirectories.setFrom(files([
353+
fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: excludePatterns),
354+
fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: excludePatterns)
355+
]))
356+
357+
// Collect execution data from both unit tests and instrumentation tests
358+
executionData.setFrom(fileTree(buildDir).include([
359+
// Unit test coverage
360+
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
361+
"jacoco/testDebugUnitTest.exec",
362+
// Instrumentation test coverage
363+
"outputs/code_coverage/debugAndroidTest/connected/**/*.ec"
364+
]))
365+
}
366+
367+
tasks.register('jacocoTestCoverageVerification', JacocoCoverageVerification) {
368+
dependsOn('testDebugUnitTest')
369+
370+
def excludePatterns = [
371+
'**/R.class',
372+
'**/R$*.class',
373+
'**/BuildConfig.*',
374+
'**/Manifest*.*',
375+
'**/*Test*.*',
376+
'android/**/*.*',
377+
'**/package-info.class',
378+
'**/TestActivity.class',
379+
'**/CSConnectionRequest.class',
380+
// Exclude callback interfaces and their anonymous implementations
381+
'**/SyncResultCallBack.class',
382+
'**/Stack$*.class'
383+
]
384+
385+
sourceDirectories.setFrom(files([
386+
"${project.projectDir}/src/main/java"
387+
]))
388+
389+
classDirectories.setFrom(files([
390+
fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: excludePatterns),
391+
fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: excludePatterns)
392+
]))
393+
394+
executionData.setFrom(fileTree(buildDir).include([
395+
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
396+
"jacoco/testDebugUnitTest.exec"
397+
]))
398+
}
399+
400+
// Make check task depend on coverage verification
401+
tasks.named('check') {
402+
dependsOn('jacocoTestReport', 'jacocoTestCoverageVerification')
221403
}

contentstack/src/androidTest/java/com/contentstack/sdk/AssetTestCase.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ public void onCompletion(ResponseType responseType, Error error) {
124124
latch.await(5, TimeUnit.SECONDS);
125125
}
126126

127+
@Test
128+
public void test_setLocale_fetch() throws InterruptedException {
129+
final CountDownLatch latch = new CountDownLatch(1);
130+
final Asset asset = stack.asset(assetUid);
131+
asset.setLocale("en-us");
132+
asset.fetch(new FetchResultCallback() {
133+
@Override
134+
public void onCompletion(ResponseType responseType, Error error) {
135+
assertNotNull(asset.getAssetUid());
136+
latch.countDown();
137+
}
138+
});
139+
latch.await(5, TimeUnit.SECONDS);
140+
assertEquals("Query was not completed in time", 0, latch.getCount());
141+
}
142+
127143
@Test
128144
public void test_include_branch() {
129145
final Asset asset = stack.asset(assetUid);

contentstack/src/main/java/com/contentstack/sdk/Asset.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,4 +616,22 @@ public Asset includeBranch() {
616616
return this;
617617
}
618618

619+
/**
620+
* <p>
621+
* <br><br><b>Example :</b><br>
622+
* <pre class="prettyprint">
623+
* Asset asset = asset.setLocale("en-hi");
624+
* </pre>
625+
* </p>
626+
*/
627+
public Asset setLocale(String locale) {
628+
if (locale != null) {
629+
try {
630+
urlQueries.put("locale", locale);
631+
} catch (JSONException e) {
632+
Log.e(TAG, e.getLocalizedMessage());
633+
}
634+
}
635+
return this;
636+
}
619637
}

contentstack/src/main/java/com/contentstack/sdk/TestActivity.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

contentstack/src/test/java/com/contentstack/sdk/ExampleUnitTest.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)