Automation e2e test with maestro
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
flows:
|
||||
- flows/*
|
||||
|
||||
executionOrder:
|
||||
continueOnFailure: false
|
||||
flowsOrder:
|
||||
- login
|
||||
@@ -0,0 +1,10 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
- runFlow:
|
||||
file: ../subflows/launch-app.yaml
|
||||
|
||||
- runFlow:
|
||||
file: ../subflows/login-steps.yaml
|
||||
|
||||
- runFlow:
|
||||
file: ../subflows/communicate-steps.yaml
|
||||
@@ -0,0 +1,6 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
- runFlow:
|
||||
file: ../subflows/launch-app.yaml
|
||||
- runFlow:
|
||||
file: ../subflows/login-steps.yaml
|
||||
@@ -0,0 +1,6 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
#- runFlow:
|
||||
# file: ../subflows/launch-app.yaml
|
||||
- runFlow:
|
||||
file: ../subflows/communicate-steps.yaml
|
||||
@@ -0,0 +1,32 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
- tapOn: "Scanner"
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: "3006"
|
||||
timeout: 30000 # 30s
|
||||
- tapOn:
|
||||
text: "3006"
|
||||
delay: 1500
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 1000
|
||||
|
||||
# In case of empty work order
|
||||
# ---------------------------
|
||||
#- tapOn:
|
||||
# text: "Back"
|
||||
# delay: 500
|
||||
#
|
||||
#- assertVisible: "Scanner"
|
||||
#- waitForAnimationToEnd:
|
||||
# timeout: 1000
|
||||
#- extendedWaitUntil:
|
||||
# visible:
|
||||
# text: "3006"
|
||||
# timeout: 30000 # 30s
|
||||
|
||||
# In case of work orders
|
||||
# --------------------------
|
||||
- tapOn: "Manual Command"
|
||||
- inputText: "ACCEPT_WO;NG"
|
||||
- tapOn: "Send"
|
||||
@@ -0,0 +1,16 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
- runFlow:
|
||||
file: ../subflows/launch-app.yaml
|
||||
|
||||
- runFlow:
|
||||
when:
|
||||
visible: "Enable"
|
||||
commands:
|
||||
- tapOn: "Enable"
|
||||
|
||||
- runFlow:
|
||||
when:
|
||||
visible: "Cho phép"
|
||||
commands:
|
||||
- tapOn: "Cho phép"
|
||||
@@ -0,0 +1,6 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
- launchApp:
|
||||
clearState: true
|
||||
- waitForAnimationToEnd:
|
||||
timeout: 3000
|
||||
@@ -0,0 +1,24 @@
|
||||
appId: com.digitoolsolutions.app.torquevaultkmp
|
||||
---
|
||||
#- longPressOn: "Username"
|
||||
#- tapOn:
|
||||
# text: "Select All"
|
||||
# optional: true
|
||||
#- tapOn:
|
||||
# text: "Chọn tất cả"
|
||||
# optional: true
|
||||
#- eraseText: 1
|
||||
#- inputText: "admin"
|
||||
#- tapOn: "App Logo"
|
||||
#- longPressOn: "Password"
|
||||
#- tapOn:
|
||||
# text: "Select All"
|
||||
# optional: true
|
||||
#- tapOn:
|
||||
# text: "Chọn tất cả"
|
||||
# optional: true
|
||||
#- eraseText: 1
|
||||
#- inputText: "admin"
|
||||
#- tapOn: "App Logo"
|
||||
- tapOn: "Sign In"
|
||||
- assertVisible: "Home"
|
||||
@@ -89,7 +89,7 @@ android {
|
||||
applicationId = "com.digitoolsolutions.app.torquevaultkmp"
|
||||
minSdk = libs.versions.android.minSdk.get().toInt()
|
||||
targetSdk = libs.versions.android.targetSdk.get().toInt()
|
||||
versionCode = 2
|
||||
versionCode = 3
|
||||
versionName = "1.0.2"
|
||||
}
|
||||
packaging {
|
||||
|
||||
+33
-29
@@ -253,6 +253,9 @@ class ScannerViewModel(
|
||||
val adv = bleManager.getAdvertisement(deviceId)
|
||||
if (adv != null) {
|
||||
connect(adv)
|
||||
// Remove advertisement from list
|
||||
advertisementMap.remove(deviceId)
|
||||
updateDeviceList()
|
||||
} else {
|
||||
Napier.e("Cannot connect: Advertisement not found for $deviceId")
|
||||
}
|
||||
@@ -369,22 +372,22 @@ class ScannerViewModel(
|
||||
_connectedDevices.value -= deviceIdentifier
|
||||
}
|
||||
}
|
||||
private fun fetchWorkOrders(peripheral: Peripheral, woID: String = "0", action: String = "next") {
|
||||
private fun fetchWorkOrders(peripheral: Peripheral, command: Helper.Command, woID: String = "0", action: String = "next") {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val orders = scannerRepository.getAbleWorkOrders(woID = woID, action = action)
|
||||
_workOrders.value = orders
|
||||
sendWorkOrdersToDevice(peripheral,orders)
|
||||
sendWorkOrdersToDevice(peripheral, command.name, orders)
|
||||
} catch (e: Exception) {
|
||||
Napier.e("Failed to load work orders", e)
|
||||
logRepository.appendLog(title = "HTTP", content = "${e.message}".substringBefore("[url="))
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun sendWorkOrdersToDevice(peripheral: Peripheral, workOrders: List<WorkOrder>) {
|
||||
private fun sendWorkOrdersToDevice(peripheral: Peripheral, command: String, workOrders: List<WorkOrder>) {
|
||||
viewModelScope.launch {
|
||||
if (workOrders.isEmpty()) {
|
||||
sendCommand(peripheral, Helper.CMD_EMPTY_WO)
|
||||
sendCommand(peripheral, Helper.CMD_EMPTY_WO(command))
|
||||
return@launch
|
||||
}
|
||||
val formatted = workOrders.joinToString(separator = "\n") { wo ->
|
||||
@@ -398,7 +401,7 @@ class ScannerViewModel(
|
||||
}
|
||||
private fun acceptWorkOrder(peripheral: Peripheral, type: Int, woId: String, deviceIdentifier: String) {
|
||||
viewModelScope.launch {
|
||||
var command = Helper.CMD_RES_OK(Helper.Command.ACCEPT_WO.name)
|
||||
var command = Helper.CMD_RES_NG(Helper.Command.ACCEPT_WO.name)
|
||||
try {
|
||||
val res = scannerRepository.confirmWorkOrder(woId, deviceIdentifier, type)
|
||||
if (res)
|
||||
@@ -427,39 +430,40 @@ class ScannerViewModel(
|
||||
)
|
||||
Napier.d(">>>>> DTO $dto")
|
||||
viewModelScope.launch {
|
||||
var command = Helper.CMD_RES_NG(Helper.Command.FINISH_WO.name)
|
||||
when (val act = bleData.firstOrNull()) {
|
||||
Helper.TorqueAction.TORQUE -> {
|
||||
try {
|
||||
scannerRepository.sendMeasurementResult(woId, dto)
|
||||
} catch (e: Exception) {
|
||||
val res = scannerRepository.sendMeasurementResult(woId, dto)
|
||||
if (res.isSuccess) {
|
||||
command = Helper.CMD_RES_OK(Helper.Command.FINISH_WO.name)
|
||||
} else {
|
||||
val e = res.exceptionOrNull()
|
||||
Napier.e("An error occurred while sending the measurement", e, tag = "ScannerViewModel")
|
||||
logRepository.appendLog(title = "HTTP", content = "${e.message}".substringBefore("[url="))
|
||||
} finally {
|
||||
// Currently, always send UPLOADED_WO regardless of success or failure
|
||||
sendCommand(peripheral, Helper.CMD_RES_OK(Helper.Command.FINISH_WO.name))
|
||||
logRepository.appendLog(title = "HTTP", content = "${e?.message}".substringBefore("[url="))
|
||||
}
|
||||
sendCommand(peripheral, command)
|
||||
}
|
||||
Helper.TorqueAction.RE_TORQUE -> {
|
||||
try {
|
||||
scannerRepository.sendMeasurementResult(woId, dto, true)
|
||||
} catch (e: Exception) {
|
||||
val res = scannerRepository.sendMeasurementResult(woId, dto, true)
|
||||
if (res.isSuccess) {
|
||||
command = Helper.CMD_RES_OK(Helper.Command.FINISH_WO.name)
|
||||
} else {
|
||||
val e = res.exceptionOrNull()
|
||||
Napier.e("An error occurred while sending the re-measurement", e, tag = "ScannerViewModel")
|
||||
logRepository.appendLog(title = "HTTP", content = "${e.message}".substringBefore("[url="))
|
||||
} finally {
|
||||
// Currently, always send UPLOADED_WO regardless of success or failure
|
||||
sendCommand(peripheral, Helper.CMD_RES_OK(Helper.Command.FINISH_WO.name))
|
||||
logRepository.appendLog(title = "HTTP", content = "${e?.message}".substringBefore("[url="))
|
||||
}
|
||||
sendCommand(peripheral, command)
|
||||
}
|
||||
Helper.TorqueAction.CANCEL -> {
|
||||
try {
|
||||
scannerRepository.sendCancelWorkOrder(woId, dto)
|
||||
} catch (e: Exception) {
|
||||
val res = scannerRepository.sendCancelWorkOrder(woId, dto)
|
||||
if (res.isSuccess) {
|
||||
command = Helper.CMD_RES_OK(Helper.Command.FINISH_WO.name)
|
||||
} else {
|
||||
val e = res.exceptionOrNull()
|
||||
Napier.e("An error occurred while cancel work order", e, tag = "ScannerViewModel")
|
||||
logRepository.appendLog(title = "HTTP", content = "${e.message}".substringBefore("[url="))
|
||||
} finally {
|
||||
// Currently, always send UPLOADED_WO regardless of success or failure
|
||||
sendCommand(peripheral, Helper.CMD_RES_OK(Helper.Command.FINISH_WO.name))
|
||||
logRepository.appendLog(title = "HTTP", content = "${e?.message}".substringBefore("[url="))
|
||||
}
|
||||
sendCommand(peripheral, command)
|
||||
}
|
||||
else -> Napier.w(">>>>> Unknown action: $act")
|
||||
}
|
||||
@@ -476,9 +480,9 @@ class ScannerViewModel(
|
||||
val woId = decoded.woId
|
||||
val data = decoded.data
|
||||
when (cmd) {
|
||||
Helper.Command.START_WO -> fetchWorkOrders(peripheral)
|
||||
Helper.Command.NEXT_WO -> fetchWorkOrders(peripheral, woId, "next")
|
||||
Helper.Command.PREVIOUS_WO -> fetchWorkOrders(peripheral, woId, "back")
|
||||
Helper.Command.START_WO -> fetchWorkOrders(peripheral, Helper.Command.START_WO)
|
||||
Helper.Command.NEXT_WO -> fetchWorkOrders(peripheral, Helper.Command.NEXT_WO, woId, "next")
|
||||
Helper.Command.PREVIOUS_WO -> fetchWorkOrders(peripheral, Helper.Command.PREVIOUS_WO, woId, "back")
|
||||
Helper.Command.ACCEPT_WO -> acceptWorkOrder(peripheral, type.code, woId, deviceIdentifier)
|
||||
Helper.Command.FINISH_WO -> {
|
||||
finishWorkOrder(peripheral, type.code, woId, data, deviceIdentifier)
|
||||
|
||||
+3
-4
@@ -8,11 +8,10 @@ object Helper {
|
||||
const val START_CHARACTER ="$"
|
||||
const val END_LINE_FEED = "#\n"
|
||||
const val SECURITY_CRC16 = "00cr16"
|
||||
|
||||
/** Command sent to indicate no work orders are available. */
|
||||
const val CMD_EMPTY_WO = "START_WO;empty"
|
||||
|
||||
const val WO_RES = "WO_RES"
|
||||
|
||||
/** Generates empty response for a specific command. */
|
||||
val CMD_EMPTY_WO: (String) -> String = {cmd -> "$cmd;empty"}
|
||||
/** Generates a success response for a specific command. */
|
||||
val CMD_RES_OK: (String) -> String = { cmd -> "$cmd;OK" }
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ class UartCommunicationTest {
|
||||
assertEquals("cr16", decoded.crc16)
|
||||
|
||||
// --- STEP 2: App prepares response (Empty Case) ---
|
||||
val emptyCase = Helper.buildUartCommand(Helper.CMD_EMPTY_WO)
|
||||
val emptyCase = Helper.buildUartCommand(Helper.CMD_EMPTY_WO("START_WO"))
|
||||
assertEquals($$"$START_WO;empty\n00cr16#\n", emptyCase)
|
||||
|
||||
// --- STEP 3: App prepares response (Multiple WO Case) ---
|
||||
|
||||
Reference in New Issue
Block a user