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
13 changes: 9 additions & 4 deletions .github/workflows/apks.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: APKs

# The app's debug APK for arm64-v8a with the stand-in engine, after the stand-in's desktop test and the Kotlin
# protocol tests (against that desktop engine too), and a second time with its libraries extracted at install. Both
# carry OpenSSL for Qt's TLS backend. Android lint runs once the first APK has staged the Qt jars it needs. The APK
# with libmudlet as its engine is built in libmudlet.yml.
# The app's debug APK for arm64-v8a with the stand-in engine, after the stand-in's desktop test, the Kotlin
# protocol tests (against that desktop engine too) and the command suggestions' tests, and a second time with its
# libraries extracted at install. Both carry OpenSSL for Qt's TLS backend. Android lint runs once the first APK has
# staged the Qt jars it needs. The APK with libmudlet as its engine is built in libmudlet.yml.
# ci.yml calls it when a file it builds from changed; a manual run builds them on any branch.
on:
workflow_call:
Expand Down Expand Up @@ -59,6 +59,11 @@ jobs:
QT_QPA_PLATFORM: offscreen
run: native/tests/run_jvm_client_test.sh -PqtRoot="$QT_ROOT" -PandroidAbi=arm64-v8a

# :suggest's tests: ranking, prediction, the saved form and file, the session's timing, hidden input never stored
- name: Kotlin suggestion tests
if: matrix.tests
run: ./gradlew -PqtRoot="$QT_ROOT" :suggest:test

- uses: ./.github/actions/android-openssl
with:
ndk-version: ${{ steps.toolchain.outputs.ndk-version }}
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ name: CI
# What runs for what changed (the filters in "changes" below say it exactly):
# docs, README and the like nothing but this workflow's own small jobs (docs/protocol.md: the APKs, whose
# ProtocolSpecTest reads it)
# Kotlin (app/, engine-service/, protocol/)
# Kotlin (app/, engine-service/, protocol/, suggest/)
# ktlint, the APKs with Android lint, and the emulator suite (smoke test and the
# instrumented tests, on minSdk and the newest API) with libmudlet from its cache
# native/, the shared actions their lint check (clang-format, actionlint), the APKs, the emulator suite, the
Expand Down Expand Up @@ -93,6 +93,7 @@ jobs:
- app/**
- engine-service/**
- protocol/**
- suggest/**
ktlint:
- "**/*.kt"
- "**/*.kts"
Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ What the app is and how it is built is in [`README.md`](README.md) and [`docs/ar
| `app/` | `:app`, the UI process: Kotlin and Compose, no Qt |
| `engine-service/` | `:engine-service`: `EngineService` in the `:engine` process, and the Qt libraries `scripts/build-apk.sh` stages into `engine-service/qtdeploy/` |
| `protocol/` | `:protocol`, plain Kotlin/JVM: the socket protocol and `EngineLink`, with the JVM tests |
| `suggest/` | `:suggest`, plain Kotlin/JVM with no dependencies: the input line's command suggestions and the session that loads, feeds and saves them, with the JVM tests |
| `native/` | C++: the engine host (`enginehost/`), the engine interface (`api/`), the stand-in engine (`standin/`), the host tests (`tests/`); `third_party/` is vendored Lua 5.1.5 |
| `scripts/` | Builds (APK, release, OpenSSL, libmudlet and its dependencies), `check-apk.sh` and `lint.sh` |
| `docs/` | [`architecture.md`](docs/architecture.md), [`protocol.md`](docs/protocol.md), [`ptb.md`](docs/ptb.md), [`decisions/`](docs/decisions), [`foundation-checklist.md`](docs/foundation-checklist.md), [`roadmap.md`](docs/roadmap.md) |
Expand Down Expand Up @@ -65,6 +66,10 @@ The public test builds, their versions and signing, and what the maintainer sets
# :protocol's JVM tests without an engine (EngineLinkJvmTest is then skipped)
./gradlew :protocol:test

# :suggest's tests, with Gradle or with kotlinc and JUnit 4 alone (no Android SDK)
./gradlew :suggest:test
KOTLIN_HOME=path/to/kotlinc JUNIT_JARS=junit-4.13.2.jar:hamcrest-core-1.3.jar suggest/run-tests.sh

# The stand-in engine on the host, then :protocol's tests with the Kotlin client against it
cmake -S native -B native/build-desktop -G Ninja -DCMAKE_PREFIX_PATH=$QT_ROOT/gcc_64
cmake --build native/build-desktop --target engine
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ kotlin {

dependencies {
implementation(project(":protocol"))
implementation(project(":suggest"))
implementation(project(":engine-service"))
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)
Expand Down
17 changes: 17 additions & 0 deletions app/src/androidTest/kotlin/org/mudlet/android/ui/GameScreenTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.mudlet.android.ui

import android.Manifest
import android.os.Build
import android.view.inputmethod.EditorInfo
import androidx.annotation.StringRes
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.semantics.SemanticsActions
Expand Down Expand Up @@ -137,12 +138,28 @@ class GameScreenTest {
compose.onNode(input).assertIsFocused().assert(editableText(""))
}

@Test
fun anEditTheKeyboardSendsJustAfterASendLeavesTheLineEmpty() {
compose.onNode(input).performTextInput("north")
val send = compose.onNode(input).assertIsFocused().fetchSemanticsNode().config[SemanticsActions.OnImeAction].action
compose.runOnUiThread {
val keyboard = checkNotNull(compose.activity.window.decorView.findFocus()?.onCreateInputConnection(EditorInfo())) { "no input connection" }
// In one turn of the main thread, so no frame comes between them: a keyboard's edit that reaches the field
// before it is drawn again, as the keyboard marking the word before the cursor does after a send
checkNotNull(send)()
keyboard.setComposingRegion(0, "north".length)
}
assertEquals("north", session.receive("send").getString("text"))
compose.onNode(input).assert(editableText(""))
}

@Test
fun theHistoryButtonsRecallEarlierCommands() {
for (command in listOf("look", "north")) {
compose.onNode(input).performTextInput(command)
compose.onNode(input).performImeAction()
assertEquals(command, session.receive("send").getString("text"))
compose.onNode(input).assert(editableText(""))
}
compose.onNode(input).performTextInput("draft")

Expand Down
Loading
Loading