Skip to content

Commit b78e42f

Browse files
committed
Merge branch 'dev/design-update' of github.com:ooni/probe-android into issues/2594
2 parents 7a2f1d8 + 0060c85 commit b78e42f

File tree

22 files changed

+376
-249
lines changed

22 files changed

+376
-249
lines changed

.github/workflows/firebase-app-distribution.yml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,30 @@ jobs:
99

1010
steps:
1111
- uses: actions/checkout@v4
12-
- name: set up JDK 17
12+
- name: Resolve PR number
13+
uses: jwalton/gh-find-current-pr@v1
14+
id: findPr
15+
with:
16+
# Can be "open", "closed", or "all". Defaults to "open".
17+
state: open
18+
- name: Set up JDK 17
1319
uses: actions/setup-java@v4
1420
with:
1521
java-version: '17'
1622
distribution: 'temurin'
17-
- name: build release
23+
- name: Build `DevFullDebug` variant
24+
if: success() && steps.findPr.outputs.number
1825
run: ./gradlew clean assembleDevFullDebug
19-
- name: upload artifact to Firebase App Distribution
26+
env:
27+
PR_NUMBER: ${{ steps.findPr.outputs.pr }}
28+
- name: Upload artifact to Firebase App Distribution
2029
uses: wzieba/[email protected]
30+
id: uploadArtifact
2131
with:
2232
appId: ${{secrets.FIREBASE_APP_ID}}
2333
serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }}
2434
groups: testers
25-
file: app/build/outputs/apk/devFull/debug/app-dev-full-debug.apk
35+
file: app/build/outputs/apk/devFull/debug/app-dev-full-debug.apk
36+
- name: Write Summary
37+
run: |
38+
echo "View this release in the Firebase console: ${{ steps.uploadArtifact.outputs.FIREBASE_CONSOLE_URI }}" >> $GITHUB_STEP_SUMMARY

app/build.gradle

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ android {
1313
applicationId 'org.openobservatory.ooniprobe'
1414
minSdk libs.versions.minSdk.get().toInteger()
1515
targetSdk libs.versions.targetSdk.get().toInteger()
16-
versionName '3.8.5.1'
17-
versionCode 108
16+
versionName '3.8.6'
17+
versionCode 110
1818
testInstrumentationRunner "org.openobservatory.ooniprobe.TestAndroidJUnitRunner"
1919
buildConfigField 'String', 'OONI_API_BASE_URL', '"https://api.ooni.io/"'
2020
buildConfigField 'String', 'NOTIFICATION_SERVER', '"https://countly.ooni.io"'
@@ -55,8 +55,8 @@ android {
5555
dev {
5656
dimension 'testing'
5757
applicationIdSuffix '.dev'
58-
versionNameSuffix "-beta.1"
59-
versionCode versionCodeDate()
58+
versionNameSuffix resolveVersionSuffix('beta')
59+
versionCode resolveVersionCode()
6060
buildConfigField 'String', 'BASE_SOFTWARE_NAME', '"ooniprobe-android-dev"'
6161
resValue "string", "APP_ID", 'org.openobservatory.ooniprobe.dev'
6262
resValue "string", "APP_NAME", "OONI Dev"
@@ -65,8 +65,8 @@ android {
6565
experimental {
6666
dimension 'testing'
6767
applicationIdSuffix '.experimental'
68-
versionNameSuffix "-experimental.1"
69-
versionCode versionCodeDate()
68+
versionNameSuffix resolveVersionSuffix('experimental')
69+
versionCode resolveVersionCode()
7070
buildConfigField 'String', 'BASE_SOFTWARE_NAME', '"ooniprobe-android-experimental"'
7171
resValue "string", "APP_ID", 'org.openobservatory.ooniprobe.experimental'
7272
resValue "string", "APP_NAME", "OONI Exp"
@@ -144,7 +144,7 @@ dependencies {
144144
fullImplementation libs.google.play.core
145145

146146
// Dependency Injection
147-
implementation libs.google.dagger
147+
implementation libs.google.dagger.lib
148148
kapt libs.google.dagger.compiler
149149

150150
// Logger
@@ -178,10 +178,20 @@ dependencies {
178178
kaptAndroidTest libs.google.dagger.compiler
179179
}
180180

181-
static def versionCodeDate() {
181+
static def resolveVersionCode() {
182+
if(System.getenv("PR_NUMBER") != null) {
183+
return System.getenv("PR_NUMBER").toInteger()
184+
}
182185
return new Date().format("yyyyMMdd").toInteger()
183186
}
184187

188+
static def resolveVersionSuffix(String variant) {
189+
if(System.getenv("PR_NUMBER") != null){
190+
return "-${variant}.${System.getenv("PR_NUMBER")}"
191+
}
192+
return "-${variant}.1"
193+
}
194+
185195
if (!getGradle().getStartParameter().getTaskRequests()
186196
.toString().contains("Fdroid")){
187197
apply plugin: 'com.google.gms.google-services'

app/src/androidTest/java/org/openobservatory/ooniprobe/ui/resultdetails/CircumventionTest.java

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -109,41 +109,4 @@ public void testBlockedTor() {
109109
onView(withId(R.id.authorities)).check(matches(withText(formattedAuthorities)));
110110
assertMeasurementRuntimeAndNetwork(measurement, testResult.network);
111111
}
112-
113-
@Test
114-
public void testSuccessfulRiseUpVPN() {
115-
// Arrange
116-
Result testResult = ResultFactory.createAndSave(OONITests.CIRCUMVENTION.toOONIDescriptor(c), 3, 0);
117-
Measurement measurement = testResult.getMeasurement("riseupvpn");
118-
119-
// Act
120-
launchDetails(testResult.id);
121-
onView(withText("RiseupVPN Test")).check(matches(isDisplayed())).perform(click());
122-
123-
// Assert
124-
assertMeasurementOutcome(true);
125-
onView(withId(R.id.bootstrap_value)).check(matches(withText(TEST_RESULTS_AVAILABLE)));
126-
onView(withId(R.id.openvpn_value)).check(matches(withText(TEST_RESULTS_AVAILABLE)));
127-
onView(withId(R.id.bridges_value)).check(matches(withText(TEST_RESULTS_AVAILABLE)));
128-
assertMeasurementRuntimeAndNetwork(measurement, testResult.network);
129-
}
130-
131-
@Test
132-
public void testBlockedRiseUpVPN() {
133-
// Arrange
134-
Result testResult = ResultFactory.createAndSave(OONITests.CIRCUMVENTION.toOONIDescriptor(c), 0, 3);
135-
Measurement measurement = testResult.getMeasurement("riseupvpn");
136-
137-
// Act
138-
launchDetails(testResult.id);
139-
onView(withText("RiseupVPN Test")).check(matches(isDisplayed())).perform(click());
140-
141-
// Assert
142-
assertMeasurementOutcome(false);
143-
onView(withId(R.id.bootstrap_value)).check(matches(withText("Blocked")));
144-
onView(withId(R.id.openvpn_value)).check(matches(withText("1 blocked")));
145-
onView(withId(R.id.bridges_value)).check(matches(withText("1 blocked")));
146-
assertMeasurementRuntimeAndNetwork(measurement, testResult.network);
147-
}
148-
149112
}

app/src/androidTest/java/org/openobservatory/ooniprobe/ui/resultdetails/PerformanceTest.java

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
package org.openobservatory.ooniprobe.ui.resultdetails;
22

3+
import static androidx.test.espresso.Espresso.onData;
4+
import static androidx.test.espresso.Espresso.onView;
5+
import static androidx.test.espresso.action.ViewActions.click;
6+
import static androidx.test.espresso.action.ViewActions.swipeLeft;
7+
import static androidx.test.espresso.assertion.ViewAssertions.matches;
8+
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
9+
import static androidx.test.espresso.matcher.ViewMatchers.withId;
10+
import static androidx.test.espresso.matcher.ViewMatchers.withText;
11+
import static org.hamcrest.Matchers.allOf;
12+
import static org.hamcrest.Matchers.anything;
13+
import static org.hamcrest.Matchers.containsString;
14+
15+
import androidx.test.espresso.assertion.ViewAssertions;
316
import androidx.test.ext.junit.runners.AndroidJUnit4;
417

518
import com.schibsted.spain.barista.rule.flaky.AllowFlaky;
@@ -20,19 +33,6 @@
2033
import org.openobservatory.ooniprobe.test.test.Ndt;
2134
import org.openobservatory.ooniprobe.utils.FormattingUtils;
2235

23-
import static androidx.test.espresso.Espresso.onView;
24-
import static androidx.test.espresso.action.ViewActions.click;
25-
import static androidx.test.espresso.action.ViewActions.swipeLeft;
26-
import static androidx.test.espresso.assertion.ViewAssertions.matches;
27-
import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
28-
import static androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition;
29-
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
30-
import static androidx.test.espresso.matcher.ViewMatchers.withId;
31-
import static androidx.test.espresso.matcher.ViewMatchers.withText;
32-
import static org.hamcrest.Matchers.allOf;
33-
import static org.hamcrest.Matchers.containsString;
34-
import static org.openobservatory.ooniprobe.ui.utils.RecyclerViewMatcher.withRecyclerView;
35-
3636
@RunWith(AndroidJUnit4.class)
3737
public class PerformanceTest extends MeasurementAbstractTest {
3838

@@ -112,35 +112,34 @@ public void testListOfMeasurements() {
112112
launchDetails(testResult.id);
113113

114114
// Assert
115-
onView(withId(R.id.recyclerView))
116-
.perform(scrollToPosition(0));
117-
118-
onView(withRecyclerView(R.id.recyclerView)
119-
.atPositionOnView(0, R.id.data1))
120-
.check(matches(withText(download + " " + downloadUnity)));
121-
onView(withRecyclerView(R.id.recyclerView)
122-
.atPositionOnView(0, R.id.data2))
123-
.check(matches(withText(upload + " " + uploadUnity)));
124-
125-
onView(withId(R.id.recyclerView))
126-
.perform(scrollToPosition(1));
127-
128-
onView(withRecyclerView(R.id.recyclerView)
129-
.atPositionOnView(1, R.id.data1))
115+
onData(anything())
116+
.inAdapterView(withId(R.id.recyclerView))
117+
.atPosition(0)
118+
.onChildView(withId(R.id.data1))
119+
.check(ViewAssertions.matches(withText(download + " " + downloadUnity)));
120+
121+
onData(anything())
122+
.inAdapterView(withId(R.id.recyclerView))
123+
.atPosition(0)
124+
.onChildView(withId(R.id.data2))
125+
.check(matches(withText(upload + " " + uploadUnity)));
126+
127+
onData(anything())
128+
.inAdapterView(withId(R.id.recyclerView))
129+
.atPosition(1)
130+
.onChildView(withId(R.id.data1))
130131
.check(matches(withText(videoQuality)));
131132

132-
onView(withId(R.id.recyclerView))
133-
.perform(scrollToPosition(2));
134-
135-
onView(withRecyclerView(R.id.recyclerView)
136-
.atPositionOnView(2, R.id.data1))
133+
onData(anything())
134+
.inAdapterView(withId(R.id.recyclerView))
135+
.atPosition(2)
136+
.onChildView(withId(R.id.data1))
137137
.check(matches(withText(notDetected)));
138138

139-
onView(withId(R.id.recyclerView))
140-
.perform(scrollToPosition(3));
141-
142-
onView(withRecyclerView(R.id.recyclerView)
143-
.atPositionOnView(3, R.id.data1))
139+
onData(anything())
140+
.inAdapterView(withId(R.id.recyclerView))
141+
.atPosition(3)
142+
.onChildView(withId(R.id.data1))
144143
.check(matches(withText(notDetected)));
145144
}
146145

@@ -174,7 +173,7 @@ public void testNDT() {
174173

175174
// Act
176175
launchDetails(testResult.id);
177-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(0, click()));
176+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(0).perform(click());
178177

179178
// Assert
180179
onView(withText(download + downloadUnity)).check(matches(isDisplayed()));
@@ -202,7 +201,7 @@ public void testStreaming() {
202201

203202
// Act
204203
launchDetails(testResult.id);
205-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(1, click()));
204+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(1).perform(click());
206205

207206
// Assert
208207
onView(withText(containsString(videoQuality))).check(matches(isDisplayed()));
@@ -219,7 +218,7 @@ public void testRequestLine() {
219218

220219
// Act
221220
launchDetails(testResult.id);
222-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(2, click()));
221+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(2).perform(click());
223222

224223
// Assert
225224
onView(withText(getResourceString(R.string.TestResults_Details_Middleboxes_HTTPInvalidRequestLine_NotFound_Hero_Title))).check(matches(isDisplayed()));
@@ -234,7 +233,7 @@ public void testRequestLineDetection() {
234233

235234
// Act
236235
launchDetails(testResult.id);
237-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(2, click()));
236+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(2).perform(click());
238237

239238
// Assert
240239
onView(withText(getResourceString(R.string.TestResults_Details_Middleboxes_HTTPInvalidRequestLine_Found_Hero_Title))).check(matches(isDisplayed()));
@@ -249,7 +248,7 @@ public void testFieldManipulation() {
249248

250249
// Act
251250
launchDetails(testResult.id);
252-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(3, click()));
251+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(3).perform(click());
253252

254253
// Assert
255254
onView(withText(getResourceString(R.string.TestResults_Details_Middleboxes_HTTPHeaderFieldManipulation_NotFound_Hero_Title))).check(matches(isDisplayed()));
@@ -264,7 +263,7 @@ public void testFieldManipulationDetection() {
264263

265264
// Act
266265
launchDetails(testResult.id);
267-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(3, click()));
266+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(3).perform(click());
268267

269268
// Assert
270269
onView(withText(getResourceString(R.string.TestResults_Details_Middleboxes_HTTPHeaderFieldManipulation_Found_Hero_Title))).check(matches(isDisplayed()));

app/src/androidTest/java/org/openobservatory/ooniprobe/ui/resultdetails/WebsitesTest.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020
import java.util.concurrent.TimeUnit;
2121

22+
import static androidx.test.espresso.Espresso.onData;
2223
import static androidx.test.espresso.Espresso.onView;
2324
import static androidx.test.espresso.action.ViewActions.click;
2425
import static androidx.test.espresso.assertion.ViewAssertions.matches;
@@ -28,6 +29,7 @@
2829
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
2930
import static androidx.test.espresso.matcher.ViewMatchers.withId;
3031
import static androidx.test.espresso.matcher.ViewMatchers.withText;
32+
import static org.hamcrest.Matchers.anything;
3133
import static org.hamcrest.Matchers.containsString;
3234
import static org.openobservatory.ooniprobe.ui.utils.RecyclerViewMatcher.withRecyclerView;
3335
import static org.openobservatory.ooniprobe.ui.utils.ViewMatchers.waitPartialText;
@@ -65,12 +67,11 @@ public void checkListOfMeasurementsTest() {
6567

6668
// Assert
6769
for (int i = 0; i < measurements.size(); i++) {
68-
onView(withId(R.id.recyclerView))
69-
.perform(scrollToPosition(i));
70-
71-
onView(withRecyclerView(R.id.recyclerView)
72-
.atPositionOnView(i, R.id.text))
73-
.check(matches(withText(containsString(measurements.get(i).getUrlString()))));
70+
onData(anything())
71+
.inAdapterView(withId(R.id.recyclerView))
72+
.atPosition(i)
73+
.onChildView(withId(R.id.text))
74+
.check(matches(withText(containsString(measurements.get(i).getUrlString()))));
7475
}
7576

7677
}
@@ -84,7 +85,7 @@ public void testSucceed() {
8485

8586
// Act
8687
launchDetails(testResult.id);
87-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(0, click()));
88+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(0).perform(click());
8889

8990
// Assert
9091
onView(withText(headerOutcome)).check(matches(isDisplayed()));
@@ -100,7 +101,7 @@ public void testBlocked() {
100101

101102
// Act
102103
launchDetails(testResult.id);
103-
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(0, click()));
104+
onData(anything()).inAdapterView(withId(R.id.recyclerView)).atPosition(0).perform(click());
104105

105106
// Assert
106107
onView(withText(headerOutcome)).check(matches(isDisplayed()));

app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.openobservatory.ooniprobe.activity.overview.OverviewViewModel.SELECT_ALL;
44
import static org.openobservatory.ooniprobe.activity.overview.OverviewViewModel.SELECT_NONE;
55
import static org.openobservatory.ooniprobe.activity.overview.OverviewViewModel.SELECT_SOME;
6+
import static org.openobservatory.ooniprobe.common.PreferenceManagerExtensionKt.resolveStatus;
67

78
import android.content.Context;
89
import android.content.Intent;
@@ -83,8 +84,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
8384
setThemeColor(descriptor.getColor());
8485
binding.icon.setImageResource(descriptor.getDisplayIcon(this));
8586
binding.customUrl.setVisibility(descriptor.getName().equals(OONITests.WEBSITES.getLabel()) ? View.VISIBLE : View.GONE);
86-
Markwon markwon = Markwon.builder(this).usePlugin(new ReadMorePlugin(getString(R.string.OONIRun_ReadMore), getString(R.string.OONIRun_ReadLess))).build();
87-
if (descriptor.getName().equals(OONITests.EXPERIMENTAL.name())) {
87+
Markwon markwon = Markwon.builder(this)
88+
.usePlugin(new ReadMorePlugin(getString(R.string.OONIRun_ReadMore), getString(R.string.OONIRun_ReadLess), 400))
89+
.build();
90+
if (Objects.equals(descriptor.getName(), OONITests.EXPERIMENTAL.name())) {
8891
markwon.setMarkdown(binding.desc, descriptor.getDescription());
8992
if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) {
9093
binding.desc.setTextDirection(View.TEXT_DIRECTION_RTL);
@@ -133,14 +136,17 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
133136
}
134137
});
135138

136-
if (adapter.isSelectedAllItems()) {
137-
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_CHECKED);
138-
} else if (adapter.isNotSelectedAnyGroupItem()) {
139-
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_UNCHECKED);
139+
if (descriptor.getName().equals(OONITests.EXPERIMENTAL.getLabel())) {
140+
binding.switchTests.setChecked(resolveStatus(preferenceManager, descriptor.getName(), descriptor.preferencePrefix(), true));
140141
} else {
141-
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_INDETERMINATE);
142+
if (adapter.isSelectedAllItems()) {
143+
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_CHECKED);
144+
} else if (adapter.isNotSelectedAnyGroupItem()) {
145+
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_UNCHECKED);
146+
} else {
147+
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_INDETERMINATE);
148+
}
142149
}
143-
binding.switchTests.setEnabled(descriptor.hasPreferencePrefix());
144150
// Expand all groups
145151
for (int i = 0; i < adapter.getGroupCount(); i++) {
146152
binding.expandableListView.expandGroup(i);

0 commit comments

Comments
 (0)