Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ internal class AnalysisScreenPresenterExtension(
}
}

private fun handleSaveInvoicesLocally(
fun handleSaveInvoicesLocally(
mIsInvoiceSavingEnabled: Boolean,
isSavingInvoicesInProgress: Boolean,
resultHolder: ResultHolder,
Expand Down Expand Up @@ -253,7 +253,7 @@ internal class AnalysisScreenPresenterExtension(
if (educationMutex.isLocked) educationMutex.unlock()
}

private fun doWhenEducationFinished(action: () -> Unit) {
fun doWhenEducationFinished(action: () -> Unit) {
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an extra space before fun creating inconsistent indentation. The line should start with 4 spaces (one indentation level) like other methods in this class, not 5 spaces.

Suggested change
fun doWhenEducationFinished(action: () -> Unit) {
fun doWhenEducationFinished(action: () -> Unit) {

Copilot uses AI. Check for mistakes.
CoroutineScope(Dispatchers.IO).launch {
educationMutex.withLock {
withContext(Dispatchers.Main) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import androidx.lifecycle.Lifecycle
import androidx.navigation.Navigation
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.spy
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import net.gini.android.capture.Document
import net.gini.android.capture.GiniCapture
import net.gini.android.capture.analysis.warning.WarningBottomSheet
import net.gini.android.capture.analysis.warning.WarningType
import net.gini.android.capture.document.ImageDocument
import net.gini.android.capture.tracking.AnalysisScreenEvent
import net.gini.android.capture.tracking.Event
Expand Down Expand Up @@ -75,4 +78,60 @@ class AnalysisFragmentTest {
}
}
}
@Test
fun `showWarning displays bottom sheet with correct type and listener`() {
// Given
val eventTracker = spy<EventTracker>()
GiniCapture.newInstance(InstrumentationRegistry.getInstrumentation().context)
.setEventTracker(eventTracker).build()
GiniCapture.getInstance().internal().imageMultiPageDocumentMemoryStore.setMultiPageDocument(mock())

val bundle = Bundle().apply {
putParcelable("GC_ARGS_DOCUMENT", mock<ImageDocument>().apply {
whenever(isReviewable).thenReturn(true)
whenever(type).thenReturn(Document.Type.IMAGE)
})
putString("GC_ARGS_DOCUMENT_ANALYSIS_ERROR_MESSAGE", "")
}

val mockOnProceed = mock<Runnable>()

FragmentScenario.launchInContainer(
fragmentClass = AnalysisFragment::class.java,
fragmentArgs = bundle,
factory = object : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return AnalysisFragment().apply {
setListener(mock())
setBankSDKBridge(mock())
setCancelListener(mock())
}.also { fragment ->
fragment.viewLifecycleOwnerLiveData.observeForever { viewLifecycleOwner ->
if (viewLifecycleOwner != null) {
Navigation.setViewNavController(fragment.requireView(), mock())
}
}
}
}
}
).use { scenario ->
scenario.moveToState(Lifecycle.State.RESUMED)

// When
scenario.onFragment { fragment ->
fragment.showWarning(WarningType.DOCUMENT_MARKED_AS_PAID, mockOnProceed)

// Execute pending transactions to ensure the bottom sheet is added
val fragmentManager = fragment.requireActivity().supportFragmentManager
fragmentManager.executePendingTransactions()

// Then
val warningSheet = fragmentManager.findFragmentByTag("WarningBottomSheet")

assertThat(warningSheet).isNotNull()
assertThat(warningSheet).isInstanceOf(WarningBottomSheet::class.java)
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.argumentCaptor
import com.nhaarman.mockitokotlin2.atLeast
import com.nhaarman.mockitokotlin2.atLeastOnce
import com.nhaarman.mockitokotlin2.doAnswer
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.mock
Expand All @@ -23,6 +24,7 @@ import io.mockk.Runs
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.slot
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import io.mockk.slot is declared but never used in this test file. Consider removing it to keep imports clean.

Suggested change
import io.mockk.slot

Copilot uses AI. Check for mistakes.
import io.mockk.spyk
import io.mockk.verify
import jersey.repackaged.jsr166e.CompletableFuture
Expand All @@ -37,6 +39,7 @@ import net.gini.android.capture.BankSDKProperties
import net.gini.android.capture.Document
import net.gini.android.capture.GiniCapture
import net.gini.android.capture.GiniCaptureHelper
import net.gini.android.capture.analysis.warning.WarningType
import net.gini.android.capture.document.DocumentFactory
import net.gini.android.capture.document.GiniCaptureDocument
import net.gini.android.capture.document.ImageDocument
Expand All @@ -62,6 +65,9 @@ import org.mockito.Mock
import org.mockito.MockitoAnnotations
import java.util.Collections
import java.util.concurrent.CancellationException
import kotlin.invoke
import kotlin.run
import kotlin.text.get
Comment on lines +68 to +70
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imports kotlin.invoke, kotlin.run, and kotlin.text.get appear to be unused in this file. These are typically auto-imported by Kotlin, and explicit imports are unnecessary. Consider removing them to keep the import section clean.

Suggested change
import kotlin.invoke
import kotlin.run
import kotlin.text.get

Copilot uses AI. Check for mistakes.

/**
* Created by Alpar Szotyori on 10.05.2019.
Expand Down Expand Up @@ -924,6 +930,71 @@ class AnalysisScreenPresenterTest {

verify { presenter.proceedWithExtractions(mockResultHolder) }
}
@Test
fun `showAlreadyPaidHint calls handleSaveInvoicesLocally immediately when isSavingInvoicesInProgress is true`() {
val view = mockk<AnalysisScreenContract.View>(relaxed = true)
val presenter = spyk(AnalysisScreenPresenterExtension(view))
val resultHolder = mockk<AnalysisInteractor.ResultHolder>(relaxed = true)
val activity = mockk<Activity>(relaxed = true)

every { presenter.handleSaveInvoicesLocally(any(), any(), any(), any()) } just Runs

presenter.showAlreadyPaidHint(
mIsInvoiceSavingEnabled = true,
isSavingInvoicesInProgress = true,
resultHolder = resultHolder,
activity = activity
)

io.mockk.verify {
presenter.handleSaveInvoicesLocally(
mIsInvoiceSavingEnabled = true,
isSavingInvoicesInProgress = true,
resultHolder = resultHolder,
activity = activity
)
}
}

@Test
fun `showAlreadyPaidHint calls showAlreadyPaidWarning and handleSaveInvoicesLocally when isSavingInvoicesInProgress is false`() {
val view = mock<AnalysisScreenContract.View>()
val presenter = spy(AnalysisScreenPresenterExtension(view))
val resultHolder = mock<AnalysisInteractor.ResultHolder>()
val activity = mock<Activity>()

// Use doAnswer for void methods on spies
doAnswer { invocation ->
val lambda = invocation.getArgument<() -> Unit>(0)
lambda.invoke()
null
}.whenever(presenter).doWhenEducationFinished(any())

// Capture the callback passed to showAlreadyPaidWarning
val callbackCaptor = argumentCaptor<Runnable>()

presenter.showAlreadyPaidHint(
mIsInvoiceSavingEnabled = false,
isSavingInvoicesInProgress = false,
resultHolder = resultHolder,
activity = activity
)

// showAlreadyPaidWarning should be called
verify(view).showAlreadyPaidWarning(eq(WarningType.DOCUMENT_MARKED_AS_PAID), callbackCaptor.capture())

// Simulate user action on the warning
callbackCaptor.firstValue.run()

// handleSaveInvoicesLocally should be called with isSavingInvoicesInProgress = false
verify(presenter).handleSaveInvoicesLocally(
mIsInvoiceSavingEnabled = false,
isSavingInvoicesInProgress = false,
resultHolder = resultHolder,
activity = activity
)
}


@Test
fun `proceedWithExtractions calls onExtractionsAvailable with correct arguments`() {
Expand Down
Loading