Skip to content

Commit

Permalink
Merge pull request #7 from rasyid7/baseBranch
Browse files Browse the repository at this point in the history
Base branch
  • Loading branch information
rasyid7 authored Dec 9, 2024
2 parents f79dcb7 + 7a6c470 commit 8bafd0d
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
.idea/

# Ignore Gradle project-specific cache directory
.gradle
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

Maestro is the easiest way to automate UI testing for your mobile app.

> [!NOTE]
>
> **Full documentation for Maestro can be found at [maestro.mobile.dev](https://maestro.mobile.dev)**
>
> Since this is forked REPO, to install this maestro, please use
>
> `curl -Ls "https://raw.githubusercontent.com/rasyid7/maestro/main/scripts/install.sh" | bash`
<img src="https://user-images.githubusercontent.com/847683/187275009-ddbdf963-ce1d-4e07-ac08-b10f145e8894.gif" />

## Why Maestro?
Expand Down
14 changes: 4 additions & 10 deletions maestro-cli/src/main/java/maestro/cli/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,10 @@ fun main(args: Array<String>) {
if (newVersion != null) {
Updates.fetchChangelogAsync()
System.err.println()
val changelog = Updates.getChangelog()
val anchor = newVersion.toString().replace(".", "")
System.err.println(listOf(
"A new version of the Maestro CLI is available ($newVersion).\n",
"See what's new:",
"https://github.com/mobile-dev-inc/maestro/blob/main/CHANGELOG.md#$anchor",
ChangeLogUtils.print(changelog),
"Upgrade command:",
"curl -Ls \"https://get.maestro.mobile.dev\" | bash",
).joinToString("\n").box())
System.err.println(
("A new version of the Maestro CLI is available ($newVersion). Upgrade command:\n" +
"curl -Ls \"https://raw.githubusercontent.com/rasyid7/maestro/main/scripts/install.sh\" | bash").box()
)
}

if (commandLine.isVersionHelpRequested) {
Expand Down
2 changes: 1 addition & 1 deletion maestro-cli/src/main/java/maestro/cli/api/ApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class ApiClient(
fun getLatestCliVersion(): CliVersion {
val request = Request.Builder()
.header("X-FRESH-INSTALL", if (!Analytics.hasRunBefore) "true" else "false")
.url("$baseUrl/maestro/version")
.url("https://raw.githubusercontent.com/rasyid7/maestro/main/version")
.get()
.build()

Expand Down
14 changes: 13 additions & 1 deletion maestro-client/src/main/java/maestro/Maestro.kt
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ class Maestro(
) {
LOGGER.info("Tapping on element: ${tapRepeat ?: ""} $element")

val hierarchyBeforeTap = waitForAppToSettle(initialHierarchy, appId, waitToSettleTimeoutMs) ?: initialHierarchy
val hierarchyBeforeTap = initialHierarchy

val center = (
hierarchyBeforeTap
Expand Down Expand Up @@ -354,6 +354,12 @@ class Maestro(
} else {
driver.tap(Point(x, y))
}

if (waitToSettleTimeoutMs != null && waitToSettleTimeoutMs < 150) {
LOGGER.info("waitToSettleTimeoutMs is less than 150, skip get hierarchy")
return
}

val hierarchyAfterTap = waitForAppToSettle(waitToSettleTimeoutMs = waitToSettleTimeoutMs)

if (hierarchyBeforeTap != hierarchyAfterTap) {
Expand Down Expand Up @@ -582,6 +588,12 @@ class Maestro(
ScreenshotUtils.waitUntilScreenIsStatic(timeout, SCREENSHOT_DIFF_THRESHOLD, driver)
}

fun sleep(time: Long?) {
val time = time ?: ANIMATION_TIMEOUT_MS
LOGGER.info("Sleep for $time ms")
Thread.sleep(time)
}

fun setProxy(
host: String = SocketUtils.localIp(),
port: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ sealed interface Command {
fun visible(): Boolean = true

val label: String?

val optional: Boolean
}

Expand Down Expand Up @@ -903,6 +903,21 @@ data class WaitForAnimationToEndCommand(
}
}

data class SleepCommand(
val time: Long?,
override val label: String? = null,
override val optional: Boolean = false,
) : Command {

override fun description(): String {
return label ?: "Sleep for $time ms"
}

override fun evaluateScripts(jsEngine: JsEngine): Command {
return this
}
}

data class EvalScriptCommand(
val scriptString: String,
override val label: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ data class MaestroCommand(
val setAirplaneModeCommand: SetAirplaneModeCommand? = null,
val toggleAirplaneModeCommand: ToggleAirplaneModeCommand? = null,
val retryCommand: RetryCommand? = null,
val sleepCommand: SleepCommand? = null,
) {

constructor(command: Command) : this(
Expand Down Expand Up @@ -111,7 +112,8 @@ data class MaestroCommand(
addMediaCommand = command as? AddMediaCommand,
setAirplaneModeCommand = command as? SetAirplaneModeCommand,
toggleAirplaneModeCommand = command as? ToggleAirplaneModeCommand,
retryCommand = command as? RetryCommand
retryCommand = command as? RetryCommand,
sleepCommand = command as? SleepCommand,
)

fun asCommand(): Command? = when {
Expand Down Expand Up @@ -155,6 +157,7 @@ data class MaestroCommand(
setAirplaneModeCommand != null -> setAirplaneModeCommand
toggleAirplaneModeCommand != null -> toggleAirplaneModeCommand
retryCommand != null -> retryCommand
sleepCommand != null -> sleepCommand
else -> null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ class Orchestra(
is SetAirplaneModeCommand -> setAirplaneMode(command)
is ToggleAirplaneModeCommand -> toggleAirplaneMode()
is RetryCommand -> retryCommand(command, config)
is SleepCommand -> sleepCommand(command)
else -> true
}.also { mutating ->
if (mutating) {
Expand Down Expand Up @@ -442,6 +443,11 @@ class Orchestra(
return true
}

private fun sleepCommand(command: SleepCommand): Boolean {
maestro.sleep(command.time)
return true
}

private fun defineVariablesCommand(command: DefineVariablesCommand): Boolean {
command.env.forEach { (name, value) ->
jsEngine.putEnv(name, value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,17 @@ object WorkspaceExecutionPlanner {
val config = configPerFlowFile[it]
val tags = config?.tags ?: emptyList()

(allIncludeTags.isEmpty() || tags.any(allIncludeTags::contains))
(allIncludeTags.isEmpty() || allIncludeTags.all { includeTag -> tags.contains(includeTag) })
&& (allExcludeTags.isEmpty() || !tags.any(allExcludeTags::contains))
}

println("")
println("Number flows to run: ${allFlows.size}")
println("Flows to run:")
for (flow in allFlows) {
println(" * ${flow.fileName.toString().substringBeforeLast(".")}")
}

if (allFlows.isEmpty()) {
val message = """
|Include / Exclude tags did not match any Flows:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ data class YamlFluentCommand(
val setAirplaneMode: YamlSetAirplaneMode? = null,
val toggleAirplaneMode: YamlToggleAirplaneMode? = null,
val retry: YamlRetryCommand? = null,
val sleep: YamlSleepCommand? = null,
) {

@SuppressWarnings("ComplexMethod")
Expand Down Expand Up @@ -257,6 +258,14 @@ data class YamlFluentCommand(
}
setAirplaneMode != null -> listOf(MaestroCommand(SetAirplaneModeCommand(setAirplaneMode.value, setAirplaneMode.label, setAirplaneMode.optional)))
toggleAirplaneMode != null -> listOf(MaestroCommand(ToggleAirplaneModeCommand(toggleAirplaneMode.label, toggleAirplaneMode.optional)))
sleep != null -> listOf(
MaestroCommand(
SleepCommand(
time = sleep.time,
label = sleep.label
)
)
)
else -> throw SyntaxError("Invalid command: No mapping provided for $this")
}
}
Expand Down Expand Up @@ -777,6 +786,10 @@ data class YamlFluentCommand(
assertNoDefectsWithAI = YamlAssertNoDefectsWithAI()
)

"sleep" -> YamlFluentCommand(
sleep = YamlSleepCommand(time = null)
)

else -> throw SyntaxError("Invalid command: \"$stringCommand\"")
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package maestro.orchestra.yaml

import com.fasterxml.jackson.annotation.JsonCreator

data class YamlSleepCommand(
val time: Long?,
val label: String? = null,
) {
companion object {
@JvmStatic
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
fun create(time: Long): YamlSleepCommand {
return YamlSleepCommand(time = time)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,33 @@ internal class MaestroCommandSerializationTest {
.isEqualTo(command)
}

@Test
fun `serialize SleepCommand`() {
// given
val command = MaestroCommand(
SleepCommand(time = 1000)
)

// when
val serializedCommandJson = command.toJson()
val deserializedCommand = objectMapper.readValue(serializedCommandJson, MaestroCommand::class.java)

// then
@Language("json")
val expectedJson = """
{
"sleepCommand" : {
"time" : 1000,
"optional" : false
}
}
""".trimIndent()
assertThat(serializedCommandJson)
.isEqualTo(expectedJson)
assertThat(deserializedCommand)
.isEqualTo(command)
}

private fun MaestroCommand.toJson(): String =
objectMapper
.writerWithDefaultPrettyPrinter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ internal class WorkspaceExecutionPlannerTest {
// When
val plan = WorkspaceExecutionPlanner.plan(
input = paths("/workspaces/010_global_include_tags"),
includeTags = listOf("featureB"),
includeTags = listOf("featureA"),
excludeTags = listOf(),
config = null,
)
Expand All @@ -258,7 +258,6 @@ internal class WorkspaceExecutionPlannerTest {
assertThat(plan.flowsToRun).containsExactly(
path("/workspaces/010_global_include_tags/flowA.yaml"),
path("/workspaces/010_global_include_tags/flowA_subflow.yaml"),
path("/workspaces/010_global_include_tags/flowB.yaml"),
)
}

Expand Down
4 changes: 2 additions & 2 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ mkdir -p "$maestro_tmp_folder"


if [ -z "$MAESTRO_VERSION" ]; then
download_url="https://github.com/mobile-dev-inc/maestro/releases/latest/download/maestro.zip"
download_url="https://github.com/rasyid7/maestro/releases/latest/download/maestro.zip"
else
download_url="https://github.com/mobile-dev-inc/maestro/releases/download/cli-$MAESTRO_VERSION/maestro.zip"
download_url="https://github.com/rasyid7/maestro/releases/download/cli-$MAESTRO_VERSION/maestro.zip"
fi

maestro_zip_file="${maestro_tmp_folder}/maestro.zip"
Expand Down

0 comments on commit 8bafd0d

Please sign in to comment.