Skip to content

Commit

Permalink
Merge pull request #71 from opatry/uitest
Browse files Browse the repository at this point in the history
Compose UI tests
  • Loading branch information
opatry authored Oct 17, 2024
2 parents d96a6ed + b2b47c5 commit 8a4dd4c
Show file tree
Hide file tree
Showing 15 changed files with 1,298 additions and 41 deletions.
15 changes: 10 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: ☕ Setup JDK 21
- name: ☕ Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '21'
java-version: '17'
distribution: 'adopt'

- name: 🐘 Setup Gradle
Expand Down Expand Up @@ -120,17 +120,22 @@ jobs:
# `test` to trigger as much Jvm tests as possible
# `:tasks-app-android:testStoreReleaseUnitTest` to restrict to only specific flavor(store)+variant(release) for `:tasks-app-android` module.
# `jvmTest` to execute Compose UI tests on Jvm
# `-x :tasks-app-shared:testReleaseUnitTest` until Compose UI tests work on Android (using Robolectric)
# `-x :tasks-app-android:test` to remove all tests from `:tasks-app-android` module not being covered by `:tasks-app-android:testStoreReleaseUnitTest`.
# `-x testDebugUnitTest` to avoid triggering tests both in debug & release build.
# `-x :tasks-app-android:build` to avoid triggering useless build tasks (typically for unused flavors).
# Only rely on dependencies of `:tasks-app-android:testStoreReleaseUnitTest`.
- name: ✅ Test
run: |
./gradlew --no-daemon test :tasks-app-android:testStoreReleaseUnitTest \
-x :tasks-app-android:test -x testDebugUnitTest -x :tasks-app-android:build
./gradlew --no-daemon test :tasks-app-android:testStoreReleaseUnitTest jvmTest \
-x :tasks-app-android:test -x testDebugUnitTest -x :tasks-app-android:build -x :tasks-app-shared:testReleaseUnitTest
- name: 🗒️ Publish Test Reports
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
detailed_summary: true
require_passed_tests: true
require_tests: true
report_paths: '**/build/test-results/**/TEST-*.xml'
4 changes: 2 additions & 2 deletions .github/workflows/play-store-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: ☕ Setup JDK 21
- name: ☕ Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '21'
java-version: '17'
distribution: 'adopt'

- name: 🐘 Setup Gradle
Expand Down
22 changes: 21 additions & 1 deletion tasks-app-shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import org.jetbrains.compose.ExperimentalComposeLibrary
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree


plugins {
alias(libs.plugins.jetbrains.kotlin.multiplatform)
Expand All @@ -39,7 +43,12 @@ compose.resources {

kotlin {
jvm()
androidTarget()

androidTarget {
// useful to allow using commonTest in Android instrumentation tests
@OptIn(ExperimentalKotlinGradlePluginApi::class)
instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test)
}

jvmToolchain(17)

Expand Down Expand Up @@ -87,6 +96,17 @@ kotlin {

implementation(projects.lucideIcons)
}

commonTest.dependencies {
implementation(kotlin("test"))

@OptIn(ExperimentalComposeLibrary::class)
implementation(compose.uiTest)
}

jvmTest.dependencies {
implementation(compose.desktop.currentOs)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,16 @@
<string name="task_list_pane_completed_section_title_with_count">Terminées (%1$s)</string>
<string name="task_list_pane_delete_task_icon_content_desc">Supprimer la tâche</string>
<string name="task_list_pane_task_options_icon_content_desc">Options de la tâche</string>

<string name="task_due_date_label_days_ago">Il y a %1$s jours</string>
<string name="task_due_date_label_weeks_ago">Il y a %1$s semaines</string>
<plurals name="task_due_date_label_days_ago">
<item quantity="zero">Aujourd'hui</item>
<item quantity="one">Hier</item>
<item quantity="other">Il y a %1$s jours</item>
</plurals>
<plurals name="task_due_date_label_weeks_ago">
<item quantity="zero">Aujourd'hui</item>
<item quantity="one">La semaine dernière</item>
<item quantity="other">Il y a %1$s semaines</item>
</plurals>
<string name="task_due_date_label_yesterday">Hier</string>
<string name="task_due_date_label_today">Aujourd'hui</string>
<string name="task_due_date_label_tomorrow">Demain</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@
<string name="task_list_pane_delete_task_icon_content_desc">Delete task</string>
<string name="task_list_pane_task_options_icon_content_desc">Task options</string>

<string name="task_due_date_label_days_ago">%1$s days ago</string>
<string name="task_due_date_label_weeks_ago">%1$s weeks ago</string>
<plurals name="task_due_date_label_days_ago">
<item quantity="zero">Today</item>
<item quantity="one">Yesterday</item>
<item quantity="other">%1$s days ago</item>
</plurals>
<plurals name="task_due_date_label_weeks_ago">
<item quantity="zero">Today</item>
<item quantity="one">Last week</item>
<item quantity="other">%1$s weeks ago</item>
</plurals>
<string name="task_due_date_label_yesterday">Yesterday</string>
<string name="task_due_date_label_today">Today</string>
<string name="task_due_date_label_tomorrow">Tomorrow</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,17 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.ADD_SUBTASK
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.DELETE
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.INDENT
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.MOVE_TO_LIST
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.MOVE_TO_NEW_LIST
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.MOVE_TO_TOP
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.TASK_MENU
import net.opatry.tasks.app.ui.component.TaskMenuTestTag.UNINDENT
import net.opatry.tasks.app.ui.model.TaskListUIModel
import net.opatry.tasks.app.ui.model.TaskUIModel
import net.opatry.tasks.resources.Res
Expand All @@ -49,6 +59,17 @@ import net.opatry.tasks.resources.task_menu_new_list
import net.opatry.tasks.resources.task_menu_unindent
import org.jetbrains.compose.resources.stringResource

object TaskMenuTestTag {
const val TASK_MENU = "TASK_MENU"
const val ADD_SUBTASK = "TASK_MENU_ADD_SUBTASK"
const val MOVE_TO_TOP = "MOVE_TO_TOP"
const val UNINDENT = "UNINDENT"
const val INDENT = "INDENT"
const val MOVE_TO_LIST = "MOVE_TO_LIST"
const val MOVE_TO_NEW_LIST = "MOVE_TO_NEW_LIST"
const val DELETE = "DELETE"
}

sealed class TaskAction {
data object ToggleCompletion : TaskAction()
data object Edit : TaskAction()
Expand All @@ -73,14 +94,16 @@ fun TaskMenu(

DropdownMenu(
expanded = expanded,
onDismissRequest = { onAction(null) }
onDismissRequest = { onAction(null) },
modifier = Modifier.testTag(TASK_MENU)
) {
if (task.canMoveToTop) {
DropdownMenuItem(
text = {
RowWithIcon(stringResource(Res.string.task_menu_move_to_top))
},
onClick = { onAction(TaskAction.MoveToTop) },
modifier = Modifier.testTag(MOVE_TO_TOP),
enabled = false
)
}
Expand All @@ -91,6 +114,7 @@ fun TaskMenu(
RowWithIcon(stringResource(Res.string.task_menu_add_subtask), LucideIcons.SquareStack)
},
onClick = { onAction(TaskAction.AddSubTask) },
modifier = Modifier.testTag(ADD_SUBTASK),
enabled = false
)
}
Expand All @@ -101,6 +125,7 @@ fun TaskMenu(
RowWithIcon(stringResource(Res.string.task_menu_indent))
},
onClick = { onAction(TaskAction.Indent) },
modifier = Modifier.testTag(INDENT),
enabled = false
)
}
Expand All @@ -111,6 +136,7 @@ fun TaskMenu(
RowWithIcon(stringResource(Res.string.task_menu_unindent))
},
onClick = { onAction(TaskAction.Unindent) },
modifier = Modifier.testTag(UNINDENT),
enabled = false
)
}
Expand All @@ -130,6 +156,7 @@ fun TaskMenu(
RowWithIcon(stringResource(Res.string.task_menu_new_list), LucideIcons.ListPlus)
},
onClick = { onAction(TaskAction.MoveToNewList) },
modifier = Modifier.testTag(MOVE_TO_NEW_LIST),
enabled = false,
)

Expand All @@ -147,6 +174,7 @@ fun TaskMenu(
Text(taskList.title, overflow = TextOverflow.Ellipsis, maxLines = 1)
}
},
modifier = Modifier.testTag(MOVE_TO_LIST),
enabled = taskList.id != currentTaskList?.id,
onClick = { onAction(TaskAction.MoveToList(taskList)) }
)
Expand All @@ -161,6 +189,7 @@ fun TaskMenu(
RowWithIcon(stringResource(Res.string.task_menu_delete), LucideIcons.Trash2)
}
},
modifier = Modifier.testTag(DELETE),
onClick = { onAction(TaskAction.Delete) }
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,27 @@ import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.selected
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import net.opatry.tasks.app.ui.component.RowWithIcon
import net.opatry.tasks.app.ui.model.TaskListUIModel
import net.opatry.tasks.app.ui.screen.TaskListsPaneTestTag.NEW_TASK_LIST_BUTTON
import net.opatry.tasks.app.ui.screen.TaskListsPaneTestTag.TASK_LIST_ROW
import net.opatry.tasks.app.ui.tooling.TaskfolioPreview
import net.opatry.tasks.app.ui.tooling.TaskfolioThemedPreview
import net.opatry.tasks.resources.Res
import net.opatry.tasks.resources.task_lists_screen_add_task_list_cta
import org.jetbrains.compose.resources.stringResource


object TaskListsPaneTestTag {
const val NEW_TASK_LIST_BUTTON = "NEW_TASK_LIST_BUTTON"
const val TASK_LIST_ROW = "TASK_LIST_ROW"
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun TaskListsColumn(
Expand All @@ -78,6 +86,7 @@ fun TaskListsColumn(
// TODO could be a "in-place" replace with a text field (no border)
TextButton(
onClick = onNewTaskList,
Modifier.testTag(NEW_TASK_LIST_BUTTON)
) {
RowWithIcon(stringResource(Res.string.task_lists_screen_add_task_list_cta), LucideIcons.CircleFadingPlus)
}
Expand Down Expand Up @@ -112,7 +121,9 @@ fun TaskListRow(

Card(
onClick = onClick,
modifier = modifier.semantics { selected = isSelected },
modifier = modifier
.testTag(TASK_LIST_ROW)
.semantics { selected = isSelected },
) {
ListItem(
headlineContent = {
Expand Down
Loading

0 comments on commit 8a4dd4c

Please sign in to comment.