diff --git a/feature/deck/build.gradle b/feature/deck/build.gradle index accee28..b3900bf 100644 --- a/feature/deck/build.gradle +++ b/feature/deck/build.gradle @@ -2,6 +2,7 @@ plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.plugin.compose' + id 'io.github.takahirom.roborazzi' } android { @@ -21,6 +22,12 @@ android { kotlinOptions { jvmTarget = '17' } + // Roborazzi/Robolectric: рендер Compose deck-экранов в PNG на JVM (Fd-сверка, mail/111). + testOptions { + unitTests { + includeAndroidResources = true + } + } } dependencies { @@ -35,4 +42,10 @@ dependencies { implementation libs.compose.material3 implementation libs.compose.foundation implementation libs.lifecycle.viewmodel.compose + testImplementation libs.robolectric + testImplementation libs.roborazzi + testImplementation libs.roborazzi.compose + testImplementation libs.roborazzi.junit.rule + testImplementation libs.compose.ui.test.junit4 + debugImplementation libs.compose.ui.test.manifest } diff --git a/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt b/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt index d0e8d4c..d721413 100644 --- a/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt +++ b/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt @@ -213,7 +213,7 @@ private fun DeckStackDialogs( } @Composable -private fun DeckBoardRow(board: DeckBoard, onClick: () -> Unit) { +internal fun DeckBoardRow(board: DeckBoard, onClick: () -> Unit) { Row( modifier = Modifier .fillMaxWidth() @@ -245,7 +245,7 @@ private fun DeckBoardRow(board: DeckBoard, onClick: () -> Unit) { @OptIn(ExperimentalLayoutApi::class) @Composable -private fun DeckStackSection( +internal fun DeckStackSection( stack: DeckStack, canEdit: Boolean, onCardClick: (DeckCard) -> Unit, diff --git a/feature/deck/src/test/java/ru/forbion/f7cloud/feature/deck/DeckScreenshotTest.kt b/feature/deck/src/test/java/ru/forbion/f7cloud/feature/deck/DeckScreenshotTest.kt new file mode 100644 index 0000000..a10e3f2 --- /dev/null +++ b/feature/deck/src/test/java/ru/forbion/f7cloud/feature/deck/DeckScreenshotTest.kt @@ -0,0 +1,101 @@ +package ru.forbion.f7cloud.feature.deck + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onRoot +import androidx.compose.ui.unit.dp +import com.github.takahirom.roborazzi.captureRoboImage +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import ru.forbion.f7cloud.core.designsystem.F7Theme + +/** + * Fd-сверка Карточек (Roborazzi, mail/111): рендер экранов в PNG на JVM (360dp, без эмулятора). + * Данные — только мок (`bmob-*`), реальные данные `cloude` не используются. + * Сравнение PNG ↔ веб-эталон (`docs/app-map/reference/deck/`) → пункты Д в `deck.diff.md`. + */ +@RunWith(RobolectricTestRunner::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config(sdk = [34], qualifiers = "w360dp-h800dp-xxhdpi") +class DeckScreenshotTest { + + @get:Rule + val composeRule = createComposeRule() + + private val labels = listOf( + DeckLabel(id = 1, title = "bmob-важное", color = "e74c3c"), + DeckLabel(id = 2, title = "bmob-ревью", color = "3498db"), + ) + + private val mockStack = DeckStack( + id = 1, + boardId = 1, + title = "В работе", + order = 0, + cards = listOf( + DeckCard( + id = 1, + title = "bmob-карточка со сроком и метками", + done = false, + description = "- [x] шаг 1\n- [ ] шаг 2", + duedate = "2026-07-20T00:00:00+00:00", + order = 0, + stackId = 1, + labels = labels, + assignees = listOf("bmob-user"), + assigneeUids = listOf("bmob-user"), + commentsCount = 3, + ), + DeckCard(id = 2, title = "bmob-выполненная", done = true, stackId = 1, order = 1), + ), + ) + + @Test + fun deck_boards_list() { + composeRule.setContent { + F7Theme { + Column( + modifier = Modifier.fillMaxSize().background(Color.White).padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + DeckBoardRow(DeckBoard(id = 1, title = "bmob-доска", color = "9b59b6")) {} + DeckBoardRow(DeckBoard(id = 2, title = "bmob-проект", color = "2ecc71")) {} + } + } + } + composeRule.onRoot().captureRoboImage("src/test/screenshots/deck-boards.png") + } + + @Test + fun deck_board_with_stack() { + composeRule.setContent { + F7Theme { + Column( + modifier = Modifier.fillMaxSize().background(Color.White).padding(8.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + DeckStackSection( + stack = mockStack, + canEdit = true, + onCardClick = {}, + onToggleDone = {}, + onAddCard = {}, + onRename = {}, + onDelete = {}, + ) + } + } + } + composeRule.onRoot().captureRoboImage("src/test/screenshots/deck-board.png") + } +} diff --git a/feature/deck/src/test/screenshots/deck-board.png b/feature/deck/src/test/screenshots/deck-board.png new file mode 100644 index 0000000..e13246b Binary files /dev/null and b/feature/deck/src/test/screenshots/deck-board.png differ diff --git a/feature/deck/src/test/screenshots/deck-boards.png b/feature/deck/src/test/screenshots/deck-boards.png new file mode 100644 index 0000000..06de882 Binary files /dev/null and b/feature/deck/src/test/screenshots/deck-boards.png differ