test(deck): Roborazzi Fd screenshot-тесты (360dp) — список досок + доска со стеком (mail/111)
Обвязка build.gradle (плагин roborazzi + testOptions + тест-деп), DeckScreenshotTest рендерит DeckBoardRow/DeckStackSection на мок-данных bmob-* (метки/срок/чек-пункты/комментарии/исполнитель), PNG в src/test/screenshots. DeckBoardRow/DeckStackSection private→internal для рендера из теста. Проверено: recordRoborazziDebug зелёный, detekt green.
This commit is contained in:
@@ -2,6 +2,7 @@ plugins {
|
|||||||
id 'com.android.library'
|
id 'com.android.library'
|
||||||
id 'org.jetbrains.kotlin.android'
|
id 'org.jetbrains.kotlin.android'
|
||||||
id 'org.jetbrains.kotlin.plugin.compose'
|
id 'org.jetbrains.kotlin.plugin.compose'
|
||||||
|
id 'io.github.takahirom.roborazzi'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -21,6 +22,12 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '17'
|
jvmTarget = '17'
|
||||||
}
|
}
|
||||||
|
// Roborazzi/Robolectric: рендер Compose deck-экранов в PNG на JVM (Fd-сверка, mail/111).
|
||||||
|
testOptions {
|
||||||
|
unitTests {
|
||||||
|
includeAndroidResources = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -35,4 +42,10 @@ dependencies {
|
|||||||
implementation libs.compose.material3
|
implementation libs.compose.material3
|
||||||
implementation libs.compose.foundation
|
implementation libs.compose.foundation
|
||||||
implementation libs.lifecycle.viewmodel.compose
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ private fun DeckStackDialogs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DeckBoardRow(board: DeckBoard, onClick: () -> Unit) {
|
internal fun DeckBoardRow(board: DeckBoard, onClick: () -> Unit) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -245,7 +245,7 @@ private fun DeckBoardRow(board: DeckBoard, onClick: () -> Unit) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun DeckStackSection(
|
internal fun DeckStackSection(
|
||||||
stack: DeckStack,
|
stack: DeckStack,
|
||||||
canEdit: Boolean,
|
canEdit: Boolean,
|
||||||
onCardClick: (DeckCard) -> Unit,
|
onCardClick: (DeckCard) -> Unit,
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Reference in New Issue
Block a user