Skip to content
Merged
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 @@ -22,6 +22,7 @@ package maestro.orchestra
import maestro.KeyCode
import maestro.Point
import maestro.orchestra.util.Env.injectEnv
import maestro.orchestra.util.InputRandomTextHelper

sealed interface Command {

Expand Down Expand Up @@ -381,6 +382,37 @@ class ClearKeychainCommand : Command {

}

enum class InputRandomType {
NUMBER, TEXT, TEXT_EMAIL_ADDRESS, TEXT_PERSON_NAME,
}

data class InputRandomCommand(
val inputType: InputRandomType? = InputRandomType.TEXT,
val length: Int? = 8,
) : Command {

fun genRandomString(): String {
val lengthNonNull = length ?: 8
val finalLength = if (lengthNonNull <= 0) 8 else lengthNonNull

return when (inputType) {
InputRandomType.NUMBER -> InputRandomTextHelper.getRandomNumber(finalLength)
InputRandomType.TEXT -> InputRandomTextHelper.getRandomText(finalLength)
InputRandomType.TEXT_EMAIL_ADDRESS -> InputRandomTextHelper.randomEmail()
InputRandomType.TEXT_PERSON_NAME -> InputRandomTextHelper.randomPersonName()
else -> InputRandomTextHelper.getRandomText(finalLength)
}
}

override fun description(): String {
return "Input text random $inputType"
}

override fun injectEnv(env: Map<String, String>): InputRandomCommand {
return this
}
}

data class RunFlowCommand(
val commands: List<MaestroCommand>,
val condition: Condition? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ data class MaestroCommand(
val backPressCommand: BackPressCommand? = null,
val assertCommand: AssertCommand? = null,
val inputTextCommand: InputTextCommand? = null,
val inputRandomTextCommand: InputRandomCommand? = null,
val launchAppCommand: LaunchAppCommand? = null,
val applyConfigurationCommand: ApplyConfigurationCommand? = null,
val openLinkCommand: OpenLinkCommand? = null,
Expand All @@ -56,6 +57,7 @@ data class MaestroCommand(
backPressCommand = command as? BackPressCommand,
assertCommand = command as? AssertCommand,
inputTextCommand = command as? InputTextCommand,
inputRandomTextCommand = command as? InputRandomCommand,
launchAppCommand = command as? LaunchAppCommand,
applyConfigurationCommand = command as? ApplyConfigurationCommand,
openLinkCommand = command as? OpenLinkCommand,
Expand All @@ -79,6 +81,7 @@ data class MaestroCommand(
backPressCommand != null -> backPressCommand
assertCommand != null -> assertCommand
inputTextCommand != null -> inputTextCommand
inputRandomTextCommand != null -> inputRandomTextCommand
launchAppCommand != null -> launchAppCommand
applyConfigurationCommand != null -> applyConfigurationCommand
openLinkCommand != null -> openLinkCommand
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package maestro.orchestra.util

object InputRandomTextHelper {
private const val CHARSET_TEXT = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz0123456789"
private const val CHARSET_NUMBER = "0123456789"
private const val CHARSET_NUMBER_WITHOUT_ZERO = "123456789"
private val LIST_POPULAR_LAST_NAME = arrayOf("Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez")
private val LIST_POPULAR_FIST_NAME = arrayOf(
"Liam",
"Olivia",
"Noah",
"Emma",
"Oliver",
"Charlotte",
"Elijah",
"Amelia",
"James",
"Ava",
"William",
"Sophia",
"Benjamin",
"Isabella",
"Lucas",
"Mia",
"Henry",
"Evelyn",
"Theodore",
"Harper"
)
private val LIST_POPULAR_EMAIL_DOMAIN = arrayOf("gmail.com", "yahoo.com", "hotmail.com", "aol.com", "msn.com", "outlook.com")

/**
* Returns random person name format: FistName LastName
*/
fun randomPersonName() = String.format(
"%s %s",
LIST_POPULAR_FIST_NAME.random(), LIST_POPULAR_LAST_NAME.random()
)

/**
* Returns random email address with format: fistName_lastName_randomTex@emailDomain
*/
fun randomEmail() = String.format(
"%s_%s_%s@%s",
LIST_POPULAR_FIST_NAME.random(),
LIST_POPULAR_LAST_NAME.random(),
getRandomText(length = 4),
LIST_POPULAR_EMAIL_DOMAIN.random(),
).lowercase()

/**
* Returns random number with [length].
*/
fun getRandomNumber(length: Int): String {
val randomNum = (1..length)
.map { CHARSET_NUMBER.random() }
.joinToString("")
return if (randomNum.startsWith("0")) {
CHARSET_NUMBER_WITHOUT_ZERO.random() + randomNum.substring(1)
} else randomNum
}

/**
* Returns random text with [length].
*/
fun getRandomText(length: Int): String {
return (1..length)
.map { CHARSET_TEXT.random() }
.joinToString("")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class Orchestra(
is SwipeCommand -> swipeCommand(command)
is AssertCommand -> assertCommand(command)
is InputTextCommand -> inputTextCommand(command)
is InputRandomCommand -> inputTextRandomCommand(command)
is LaunchAppCommand -> launchAppCommand(command)
is OpenLinkCommand -> openLinkCommand(command)
is PressKeyCommand -> pressKeyCommand(command)
Expand Down Expand Up @@ -260,6 +261,10 @@ class Orchestra(
maestro.inputText(command.text)
}

private fun inputTextRandomCommand(command: InputRandomCommand) {
inputTextCommand(InputTextCommand(text = command.genRandomString()))
}

private fun assertCommand(command: AssertCommand) {
command.visible?.let { assertVisible(it, command.timeout) }
command.notVisible?.let { assertNotVisible(it, command.timeout) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import maestro.orchestra.EraseTextCommand
import maestro.orchestra.HideKeyboardCommand
import maestro.orchestra.ClipboardPasteCommand
import maestro.orchestra.InputTextCommand
import maestro.orchestra.InputRandomCommand
import maestro.orchestra.InputRandomType
import maestro.orchestra.LaunchAppCommand
import maestro.orchestra.MaestroCommand
import maestro.orchestra.OpenLinkCommand
Expand All @@ -57,6 +59,10 @@ data class YamlFluentCommand(
val assertNotVisible: YamlElementSelectorUnion? = null,
val action: String? = null,
val inputText: String? = null,
val inputRandomText: YamlInputRandomText? = null,
val inputRandomNumber: YamlInputRandomNumber? = null,
val inputRandomEmail: YamlInputRandomEmail? = null,
val inputRandomPersonName: YamlInputRandomPersonName? = null,
val launchApp: YamlLaunchApp? = null,
val swipe: YamlElementSelectorUnion? = null,
val openLink: String? = null,
Expand All @@ -79,6 +85,10 @@ data class YamlFluentCommand(
assertVisible != null -> listOf(MaestroCommand(AssertCommand(visible = toElementSelector(assertVisible))))
assertNotVisible != null -> listOf(MaestroCommand(AssertCommand(notVisible = toElementSelector(assertNotVisible))))
inputText != null -> listOf(MaestroCommand(InputTextCommand(inputText)))
inputRandomText != null -> listOf(MaestroCommand(InputRandomCommand(inputType = InputRandomType.TEXT, length = inputRandomText.length)))
inputRandomNumber != null -> listOf(MaestroCommand(InputRandomCommand(inputType = InputRandomType.NUMBER, length = inputRandomNumber.length)))
inputRandomEmail != null -> listOf(MaestroCommand(InputRandomCommand(inputType = InputRandomType.TEXT_EMAIL_ADDRESS)))
inputRandomPersonName != null -> listOf(MaestroCommand(InputRandomCommand(inputType = InputRandomType.TEXT_PERSON_NAME)))
swipe != null -> listOf(swipeCommand(swipe))
openLink != null -> listOf(MaestroCommand(OpenLinkCommand(openLink)))
pressKey != null -> listOf(MaestroCommand(PressKeyCommand(code = KeyCode.getByName(pressKey) ?: throw SyntaxError("Unknown key name: $pressKey"))))
Expand Down Expand Up @@ -364,6 +374,26 @@ data class YamlFluentCommand(
eraseText = YamlEraseText(charactersToErase = 50)
)

"inputRandomText" -> YamlFluentCommand(
inputRandomText = YamlInputRandomText(length = 8),
)

"inputRandomText" -> YamlFluentCommand(
inputRandomText = YamlInputRandomText(length = 8),
)

"inputRandomNumber" -> YamlFluentCommand(
inputRandomNumber = YamlInputRandomNumber(length = 8),
)

"inputRandomEmail" -> YamlFluentCommand(
inputRandomEmail = YamlInputRandomEmail(),
)

"inputRandomPersonName" -> YamlFluentCommand(
inputRandomPersonName = YamlInputRandomPersonName(),
)

"back" -> YamlFluentCommand(
action = "back"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
*
* Copyright (c) 2022 mobile.dev inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/

package maestro.orchestra.yaml

data class YamlInputRandomText(
val length: Int?,
)

data class YamlInputRandomNumber(
val length: Int?,
)

class YamlInputRandomEmail

class YamlInputRandomPersonName
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,114 @@ internal class MaestroCommandSerializationTest {
.isEqualTo(command)
}

@Test
fun `serialize InputRandomCommand with text`() {
// given
val command = MaestroCommand(
InputRandomCommand(InputRandomType.TEXT, 2)
)

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

// then
@Language("json")
val expectedJson = """
{
"inputRandomTextCommand" : {
"inputType" : "TEXT",
"length" : 2
}
}
""".trimIndent()
assertThat(serializedCommandJson)
.isEqualTo(expectedJson)
assertThat(deserializedCommand)
.isEqualTo(command)
}

@Test
fun `serialize InputRandomCommand with number`() {
// given
val command = MaestroCommand(
InputRandomCommand(InputRandomType.NUMBER, 3)
)

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

// then
@Language("json")
val expectedJson = """
{
"inputRandomTextCommand" : {
"inputType" : "NUMBER",
"length" : 3
}
}
""".trimIndent()
assertThat(serializedCommandJson)
.isEqualTo(expectedJson)
assertThat(deserializedCommand)
.isEqualTo(command)
}

@Test
fun `serialize InputRandomCommand with email`() {
// given
val command = MaestroCommand(
InputRandomCommand(InputRandomType.TEXT_EMAIL_ADDRESS)
)

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

// then
@Language("json")
val expectedJson = """
{
"inputRandomTextCommand" : {
"inputType" : "TEXT_EMAIL_ADDRESS",
"length" : 8
}
}
""".trimIndent()
assertThat(serializedCommandJson)
.isEqualTo(expectedJson)
assertThat(deserializedCommand)
.isEqualTo(command)
}

@Test
fun `serialize InputRandomCommand with person name`() {
// given
val command = MaestroCommand(
InputRandomCommand(InputRandomType.TEXT_PERSON_NAME)
)

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

// then
@Language("json")
val expectedJson = """
{
"inputRandomTextCommand" : {
"inputType" : "TEXT_PERSON_NAME",
"length" : 8
}
}
""".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 @@ -254,6 +254,14 @@ class FakeDriver : Driver {
}
}

fun assertAnyEvent(condition: ((event: Event) -> Boolean)) {
assertThat(events.any { condition(it) }).isTrue()
}

fun assertAllEvent(condition: ((event: Event) -> Boolean)) {
assertThat(events.all { condition(it) }).isTrue()
}

fun assertNoInteraction() {
if (events.isNotEmpty()) {
throw AssertionError("Expected no interaction, but got: $events")
Expand Down
Loading