Skip to content

Commit c5171b4

Browse files
committed
Scan implementation using Scanbot, test cases added and Scan Event tracking.
Scanbot migration 1.89.0 -> 4.0.0 NMC-3671 -- e2ee folder selection if e2ee is already setup NMC-3670 -- crash fix while saving into e2ee folder without e2ee setup NMC-3699 & NMC-3701 -- fix e2ee folder path NMC-3702 -- create sub-folder and open them properly for e2ee folders NMC-3966 -- Scanbot migration 4.0.0 to 6.2.0 NMC-4079 -- fix android 15 keyboard overlaps on password input field. NMC-3512 -- show correct scan path in toolbar after scanning NMC-4725 -- migrate to 7.1.1 from 6.2.0 NMC-4766 -- fix updating scan path after successful folder creation
1 parent a1d3e20 commit c5171b4

File tree

83 files changed

+4782
-32
lines changed

Some content is hidden

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

83 files changed

+4782
-32
lines changed

app/build.gradle

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ apply plugin: "pmd"
4343
apply from: "$rootProject.projectDir/jacoco.gradle"
4444
apply plugin: "com.github.spotbugs"
4545
apply plugin: "io.gitlab.arturbosch.detekt"
46+
// apply scanbot SDK for NMC
47+
apply from: "$rootProject.projectDir/nmc_scan-dependencies.gradle"
4648

4749
// needed to make renovate run without shot, as shot requires Android SDK
4850
// https://github.com/pedrovgs/Shot/issues/300
@@ -214,6 +216,7 @@ android {
214216
resources {
215217
excludes += "META-INF/LICENSE*"
216218
excludes += "META-INF/versions/9/OSGI-INF/MANIFEST*"
219+
excludes += "META-INF/DEPENDENCIES"
217220
pickFirst "MANIFEST.MF" // workaround for duplicated manifest on some dependencies
218221
}
219222
}
@@ -383,10 +386,11 @@ dependencies {
383386
implementation libs.emoji.google
384387
// endregion
385388

389+
// NextCloud scan is not required in NMC
386390
// region AppScan, document scanner not available on FDroid (generic) due to OpenCV binaries
387-
gplayImplementation project(":appscan")
388-
huaweiImplementation project(":appscan")
389-
qaImplementation project(":appscan")
391+
// gplayImplementation project(":appscan")
392+
// huaweiImplementation project(":appscan")
393+
// qaImplementation project(":appscan")
390394
// endregion
391395

392396
// region SpotBugs
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.nmc.android.scans
2+
3+
import android.Manifest
4+
import androidx.test.espresso.Espresso
5+
import androidx.test.espresso.action.ViewActions
6+
import androidx.test.espresso.matcher.ViewMatchers
7+
import androidx.test.ext.junit.rules.ActivityScenarioRule
8+
import androidx.test.ext.junit.runners.AndroidJUnit4
9+
import androidx.test.filters.LargeTest
10+
import androidx.test.rule.GrantPermissionRule
11+
import com.owncloud.android.AbstractIT
12+
import com.owncloud.android.R
13+
import junit.framework.TestCase
14+
import org.junit.Rule
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
18+
@RunWith(AndroidJUnit4::class)
19+
@LargeTest
20+
/*
21+
* Scan test to test the max number of possible scans till device throws exception or unexpected error occurs
22+
*/
23+
class ScanActivityMultipleTest : AbstractIT() {
24+
@get:Rule
25+
val activityRule = ActivityScenarioRule(ScanActivity::class.java)
26+
27+
@get:Rule
28+
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.CAMERA)
29+
30+
private var docScanCount = 0
31+
32+
@Test
33+
fun runAllScanTests() {
34+
captureAndVerifyDocScan()
35+
for (i in 0 until MAX_NUMBER_OF_SCAN) {
36+
println("Scan no: $docScanCount")
37+
verifyScanMoreDocument()
38+
}
39+
}
40+
41+
private fun captureAndVerifyDocScan() {
42+
Espresso.onView(ViewMatchers.withId(R.id.shutterButton)).perform(ViewActions.click())
43+
shortSleep()
44+
shortSleep()
45+
shortSleep()
46+
shortSleep()
47+
docScanCount++
48+
TestCase.assertEquals(docScanCount, ScanActivity.originalScannedImages.size)
49+
}
50+
51+
private fun verifyScanMoreDocument() {
52+
Espresso.onView(ViewMatchers.withId(R.id.scanMoreButton)).perform(ViewActions.click())
53+
captureAndVerifyDocScan()
54+
}
55+
56+
companion object {
57+
/**
58+
* variable to define max number of scans to test
59+
*/
60+
private const val MAX_NUMBER_OF_SCAN = 40
61+
}
62+
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
package com.nmc.android.scans
2+
3+
import android.Manifest
4+
import androidx.test.espresso.Espresso
5+
import androidx.test.espresso.action.ViewActions
6+
import androidx.test.espresso.assertion.ViewAssertions
7+
import androidx.test.espresso.matcher.RootMatchers
8+
import androidx.test.espresso.matcher.ViewMatchers
9+
import androidx.test.ext.junit.rules.ActivityScenarioRule
10+
import androidx.test.ext.junit.runners.AndroidJUnit4
11+
import androidx.test.filters.LargeTest
12+
import androidx.test.rule.GrantPermissionRule
13+
import com.owncloud.android.AbstractIT
14+
import com.owncloud.android.R
15+
import junit.framework.TestCase
16+
import org.hamcrest.core.IsNot
17+
import org.junit.Rule
18+
import org.junit.Test
19+
import org.junit.runner.RunWith
20+
21+
@RunWith(AndroidJUnit4::class)
22+
@LargeTest
23+
/*
24+
*Scan test to test the full flow of document scan from Scanning to Save page.
25+
*/
26+
class ScanActivityTest : AbstractIT() {
27+
@get:Rule
28+
val activityRule = ActivityScenarioRule(ScanActivity::class.java)
29+
30+
@get:Rule
31+
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.CAMERA)
32+
33+
private var docScanCount = 0
34+
35+
/*
36+
* running all test in one test will create a flow from scanning to saving the scans
37+
*/
38+
@Test
39+
fun runAllScanTests() {
40+
verifyIfToolbarHidden()
41+
verifyIfScanFragmentReplaced()
42+
verifyToggleAutomatic()
43+
verifyToggleFlash()
44+
captureAndVerifyDocScan()
45+
verifyScanMoreDocument()
46+
verifyApplyFilter()
47+
verifyRotateDocument()
48+
verifyImageCrop()
49+
verifyImageDeletion()
50+
verifySaveScannedDocs()
51+
verifyPasswordSwitch()
52+
verifyPdfPasswordSwitchToggle()
53+
}
54+
55+
private fun verifyIfToolbarHidden() {
56+
Espresso.onView(ViewMatchers.withId(R.id.toolbar))
57+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isDisplayed())))
58+
}
59+
60+
private fun verifyIfScanFragmentReplaced() {
61+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_automatic))
62+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
63+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_flash))
64+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
65+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_cancel))
66+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
67+
Espresso.onView(ViewMatchers.withId(R.id.shutterButton))
68+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
69+
}
70+
71+
private fun verifyToggleAutomatic() {
72+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_automatic)).perform(ViewActions.click())
73+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_automatic)).check(
74+
ViewAssertions.matches(
75+
ViewMatchers.hasTextColor(
76+
R.color.grey_60
77+
)
78+
)
79+
)
80+
81+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_automatic)).perform(ViewActions.click())
82+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_automatic)).check(
83+
ViewAssertions.matches(
84+
ViewMatchers.hasTextColor(
85+
R.color.primary
86+
)
87+
)
88+
)
89+
}
90+
91+
private fun verifyToggleFlash() {
92+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_flash)).perform(ViewActions.click())
93+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_flash)).check(
94+
ViewAssertions.matches(
95+
ViewMatchers.hasTextColor(
96+
R.color.primary
97+
)
98+
)
99+
)
100+
101+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_flash)).perform(ViewActions.click())
102+
Espresso.onView(ViewMatchers.withId(R.id.scan_doc_btn_flash)).check(
103+
ViewAssertions.matches(
104+
ViewMatchers.hasTextColor(
105+
R.color.grey_60
106+
)
107+
)
108+
)
109+
}
110+
111+
private fun captureAndVerifyDocScan() {
112+
Espresso.onView(ViewMatchers.withId(R.id.shutterButton)).perform(ViewActions.click())
113+
shortSleep()
114+
shortSleep()
115+
shortSleep()
116+
docScanCount++
117+
TestCase.assertEquals(docScanCount, ScanActivity.originalScannedImages.size)
118+
}
119+
120+
private fun verifyScanMoreDocument() {
121+
Espresso.onView(ViewMatchers.withId(R.id.scanMoreButton)).perform(ViewActions.click())
122+
captureAndVerifyDocScan()
123+
}
124+
125+
private fun verifyApplyFilter() {
126+
Espresso.onView(ViewMatchers.withId(R.id.filterDocButton)).perform(ViewActions.click())
127+
128+
Espresso.onView(ViewMatchers.withText(R.string.edit_scan_filter_dialog_title))
129+
.inRoot(RootMatchers.isDialog())
130+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
131+
132+
Espresso.onView(ViewMatchers.withText(R.string.edit_scan_filter_b_n_w))
133+
.inRoot(RootMatchers.isDialog())
134+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
135+
.perform(ViewActions.click())
136+
137+
shortSleep()
138+
shortSleep()
139+
shortSleep()
140+
}
141+
142+
private fun verifyRotateDocument() {
143+
Espresso.onView(ViewMatchers.withId(R.id.rotateDocButton)).perform(ViewActions.click())
144+
}
145+
146+
private fun verifyImageCrop() {
147+
Espresso.onView(ViewMatchers.withId(R.id.cropDocButton)).perform(ViewActions.click())
148+
149+
Espresso.onView(ViewMatchers.withId(R.id.crop_polygon_view))
150+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
151+
Espresso.onView(ViewMatchers.withId(R.id.crop_btn_reset_borders))
152+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
153+
154+
Espresso.onView(ViewMatchers.withId(R.id.action_save)).perform(ViewActions.click())
155+
}
156+
157+
private fun verifyImageDeletion() {
158+
Espresso.onView(ViewMatchers.withId(R.id.deleteDocButton)).perform(ViewActions.click())
159+
docScanCount--
160+
TestCase.assertEquals(docScanCount, ScanActivity.originalScannedImages.size)
161+
}
162+
163+
private fun verifySaveScannedDocs() {
164+
Espresso.onView(ViewMatchers.withId(R.id.action_save)).perform(ViewActions.click())
165+
166+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_filename_input))
167+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
168+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_location_input))
169+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
170+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_nested_scroll_view)).perform(ViewActions.swipeUp())
171+
172+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_pdf_checkbox))
173+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
174+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_png_checkbox))
175+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
176+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_jpg_checkbox))
177+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
178+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_with_txt_recognition_pdf_checkbox))
179+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
180+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_with_txt_recognition_txt_checkbox))
181+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
182+
183+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_pdf_checkbox)).check(
184+
ViewAssertions.matches(
185+
IsNot.not(ViewMatchers.isChecked())
186+
)
187+
)
188+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_png_checkbox)).check(
189+
ViewAssertions.matches(
190+
IsNot.not(ViewMatchers.isChecked())
191+
)
192+
)
193+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_jpg_checkbox)).check(
194+
ViewAssertions.matches(
195+
IsNot.not(ViewMatchers.isChecked())
196+
)
197+
)
198+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_with_txt_recognition_pdf_checkbox))
199+
.check(ViewAssertions.matches(ViewMatchers.isChecked()))
200+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_with_txt_recognition_txt_checkbox)).check(
201+
ViewAssertions.matches(
202+
IsNot.not(ViewMatchers.isChecked())
203+
)
204+
)
205+
206+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
207+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
208+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
209+
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
210+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
211+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isChecked())))
212+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_text_input))
213+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isDisplayed())))
214+
215+
Espresso.onView(ViewMatchers.withId(R.id.save_scan_btn_cancel))
216+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
217+
Espresso.onView(ViewMatchers.withId(R.id.save_scan_btn_save))
218+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
219+
}
220+
221+
private fun verifyPasswordSwitch() {
222+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_with_txt_recognition_pdf_checkbox))
223+
.perform(ViewActions.click())
224+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
225+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isEnabled())))
226+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
227+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isChecked())))
228+
229+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_without_txt_recognition_pdf_checkbox))
230+
.perform(ViewActions.click())
231+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
232+
.check(ViewAssertions.matches(ViewMatchers.isEnabled()))
233+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch))
234+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isChecked())))
235+
}
236+
237+
private fun verifyPdfPasswordSwitchToggle() {
238+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch)).perform(ViewActions.click())
239+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_text_input))
240+
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
241+
242+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_switch)).perform(ViewActions.click())
243+
Espresso.onView(ViewMatchers.withId(R.id.scan_save_pdf_password_text_input))
244+
.check(ViewAssertions.matches(IsNot.not(ViewMatchers.isDisplayed())))
245+
}
246+
}

0 commit comments

Comments
 (0)