diff --git a/PAPARAZZI_SETUP.md b/PAPARAZZI_SETUP.md new file mode 100644 index 0000000..523f053 --- /dev/null +++ b/PAPARAZZI_SETUP.md @@ -0,0 +1,131 @@ +# Paparazzi UI Snapshot Testing Setup + +This project uses [Paparazzi](https://github.com/cashapp/paparazzi) for snapshot testing of Compose UI components. + +## Overview + +Paparazzi enables fast, deterministic screenshot testing without requiring an Android device or emulator. All UI snapshots are generated during unit tests and stored as golden images. + +## Configuration + +### Versions +- **Android Gradle Plugin**: 8.5.2 +- **Kotlin**: 2.0.0 +- **Paparazzi**: 1.3.4 +- **Compile SDK**: 34 + +### Build Configuration + +Paparazzi is configured in both `app/build.gradle` and `composed-barcodes/build.gradle`: + +```gradle +plugins { + id 'app.cash.paparazzi' +} + +dependencies { + testImplementation(libs.junit) +} +``` + +## Snapshot Tests + +### Library Module (`composed-barcodes`) + +**Location**: `composed-barcodes/src/test/kotlin/com/simonsickle/compose/barcodes/` + +#### Test Files: +- `BarcodeSnapshotTest.kt` - Tests all Barcode component preview variations + +#### Preview Composables: +Created in `BarcodePreviews.kt`, covering: +- QR Code (default, small, high-resolution, no-progress variations) +- Code 128, Code 39, EAN-13, UPC-A +- Data Matrix, Aztec, PDF417 + +### App Module (`app`) + +**Location**: `app/src/test/java/com/simonsickle/composedbarcodes/examples/` + +#### Test Files: +- `BarcodePreviewSnapshotTest.kt` - Tests all barcode example screens + +Covers all 13 barcode types: +QR, Aztec, Code39, Code93, Code128, Codabar, DataMatrix, EAN8, EAN13, ITF, PDF417, UPC-A, UPC-E + +## Running Tests + +### Record Golden Images +```bash +# Record all snapshots +./gradlew recordPaparazziDebug + +# Record for specific module +./gradlew composed-barcodes:recordPaparazziDebug +./gradlew app:recordPaparazziDebug +``` + +### Verify Snapshots +```bash +# Verify all snapshots match golden images +./gradlew verifyPaparazziDebug + +# Verify for specific module +./gradlew composed-barcodes:verifyPaparazziDebug +./gradlew app:verifyPaparazziDebug +``` + +### View Reports +After running tests, view the generated report at: +- Library: `composed-barcodes/build/reports/paparazzi/debug/index.html` +- App: `app/build/reports/paparazzi/debug/index.html` + +## CI Integration + +The GitHub Actions workflow (`.github/workflows/unit-tests.yml`) runs Paparazzi tests automatically on push and pull requests: + +```yaml +- name: Run Paparazzi snapshot tests - Library + run: ./gradlew composed-barcodes:verifyPaparazziDebug --stacktrace + +- name: Run Paparazzi snapshot tests - App + run: ./gradlew app:verifyPaparazziDebug --stacktrace +``` + +## Implementation Details + +### Synchronous Barcode for Testing + +To ensure snapshots capture actual barcodes instead of loading states, the library provides a `SynchronousBarcode` composable specifically for preview and testing purposes. This version generates barcodes synchronously during composition, making it ideal for Paparazzi snapshot tests. + +- **Production use**: Use the async `Barcode` composable with loading indicator support +- **Testing/Previews**: Use `SynchronousBarcode` for reliable snapshot testing + +All preview composables in `BarcodePreviews.kt` use `SynchronousBarcode` to ensure accurate snapshot rendering. + +**Important**: When using `SynchronousBarcode`, ensure the `width` and `height` parameters match the modifier dimensions to prevent barcode distortion. This maintains proper aspect ratios for each barcode type (e.g., square for QR codes and Data Matrix, wide rectangles for Code 128, EAN-13, and UPC-A). + +## Known Limitations + +1. **App Module**: There's a known Gradle dependency version mismatch in the app module (requires compileSdk 35 and AGP 8.6.0+, currently using 34 and 8.5.2). This doesn't affect the library module tests. + +## Troubleshooting + +### Tests Failing After Dependency Updates +Run `./gradlew --stop` to stop all Gradle daemons, then re-run tests. + +### Snapshot Mismatches +If legitimate UI changes were made, record new golden images: +```bash +./gradlew recordPaparazziDebug +``` + +### Build Failures +Ensure you're using the correct SDK version (34) and the specified plugin versions. + +## Best Practices + +1. **Always record golden images** after intentional UI changes +2. **Review snapshot diffs** carefully before accepting changes +3. **Keep snapshots small** - test individual components rather than entire screens when possible +4. **Use descriptive test names** to make snapshot files easy to identify diff --git a/app/build.gradle b/app/build.gradle index 9277cd4..b7ec508 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,14 +1,16 @@ plugins { id 'com.android.application' + id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.plugin.compose' + id 'app.cash.paparazzi' } android { defaultConfig { applicationId "com.simonsickle.composedbarcodes" - compileSdk = 36 + compileSdk = 34 minSdkVersion 26 - targetSdkVersion 36 + targetSdkVersion 34 versionCode 2 versionName "1.1.0" @@ -27,6 +29,10 @@ android { targetCompatibility JavaVersion.VERSION_19 } + kotlinOptions { + jvmTarget = '19' + } + buildFeatures { compose true } @@ -50,4 +56,7 @@ dependencies { // Nav components implementation(libs.androidx.navigation.compose) + + // Testing + testImplementation(libs.junit) } diff --git a/app/src/main/java/com/simonsickle/composedbarcodes/examples/GenericBarcodeExample.kt b/app/src/main/java/com/simonsickle/composedbarcodes/examples/GenericBarcodeExample.kt index eee5df3..ccd01b5 100644 --- a/app/src/main/java/com/simonsickle/composedbarcodes/examples/GenericBarcodeExample.kt +++ b/app/src/main/java/com/simonsickle/composedbarcodes/examples/GenericBarcodeExample.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.simonsickle.compose.barcodes.Barcode +import com.simonsickle.compose.barcodes.SynchronousBarcode import com.simonsickle.compose.barcodes.BarcodeType @Composable @@ -30,7 +30,7 @@ fun GenericBarcodeExample( .fillMaxSize() ) { if (barcodeType.isValueValid(value)) { - Barcode( + SynchronousBarcode( modifier = Modifier .align(Alignment.CenterHorizontally) .width(300.dp) diff --git a/app/src/test/java/com/simonsickle/composedbarcodes/examples/BarcodePreviewSnapshotTest.kt b/app/src/test/java/com/simonsickle/composedbarcodes/examples/BarcodePreviewSnapshotTest.kt new file mode 100644 index 0000000..1aa00e2 --- /dev/null +++ b/app/src/test/java/com/simonsickle/composedbarcodes/examples/BarcodePreviewSnapshotTest.kt @@ -0,0 +1,110 @@ +package com.simonsickle.composedbarcodes.examples + +import app.cash.paparazzi.DeviceConfig +import app.cash.paparazzi.Paparazzi +import org.junit.Rule +import org.junit.Test + +/** + * Paparazzi snapshot tests for all barcode preview composables. + * These tests ensure that the UI renders correctly and catches any visual regressions. + */ +class BarcodePreviewSnapshotTest { + + @get:Rule + val paparazzi = Paparazzi( + deviceConfig = DeviceConfig.PIXEL_5, + showSystemUi = false + ) + + @Test + fun qrCodePreview() { + paparazzi.snapshot { + Qr() + } + } + + @Test + fun aztecPreview() { + paparazzi.snapshot { + Aztec() + } + } + + @Test + fun code39Preview() { + paparazzi.snapshot { + Code39() + } + } + + @Test + fun code93Preview() { + paparazzi.snapshot { + Code93() + } + } + + @Test + fun code128Preview() { + paparazzi.snapshot { + Code128() + } + } + + @Test + fun codabarPreview() { + paparazzi.snapshot { + Codabar() + } + } + + @Test + fun dataMatrixPreview() { + paparazzi.snapshot { + DataMatrix() + } + } + + @Test + fun ean8Preview() { + paparazzi.snapshot { + Ean8() + } + } + + @Test + fun ean13Preview() { + paparazzi.snapshot { + Ean13() + } + } + + @Test + fun itfPreview() { + paparazzi.snapshot { + Itf() + } + } + + @Test + fun pdf417Preview() { + paparazzi.snapshot { + Pdf417() + } + } + + @Test + fun upcAPreview() { + paparazzi.snapshot { + UpcA() + } + } + + @Test + fun upcEPreview() { + paparazzi.snapshot { + UpcE() + } + } +} diff --git a/build.gradle b/build.gradle index 1403e08..1a8a5eb 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,9 @@ plugins { - id("com.android.application") version '9.1.0' apply false - id("com.android.library") version '9.1.0' apply false - id("org.jetbrains.kotlin.plugin.compose") version "2.3.10" apply false + id("com.android.application") version '8.5.2' apply false + id("com.android.library") version '8.5.2' apply false + id("org.jetbrains.kotlin.android") version "2.0.0" apply false + id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" apply false + id("app.cash.paparazzi") version "1.3.4" apply false id("io.github.gradle-nexus.publish-plugin") version "2.0.0" } diff --git a/composed-barcodes/build.gradle b/composed-barcodes/build.gradle index d6f3896..c59d978 100644 --- a/composed-barcodes/build.gradle +++ b/composed-barcodes/build.gradle @@ -1,6 +1,8 @@ plugins { id "com.android.library" + id "org.jetbrains.kotlin.android" id "org.jetbrains.kotlin.plugin.compose" + id "app.cash.paparazzi" } ext { @@ -13,7 +15,7 @@ android { namespace "com.simonsickle.compose" defaultConfig { - compileSdk = 36 + compileSdk = 34 minSdkVersion 21 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -35,6 +37,10 @@ android { targetCompatibility JavaVersion.VERSION_19 } + kotlinOptions { + jvmTarget = '19' + } + buildFeatures { compose true } @@ -50,7 +56,7 @@ android { testOptions { animationsDisabled true - targetSdk 36 + targetSdk 34 } publishing { @@ -60,7 +66,7 @@ android { } } lint { - targetSdk 36 + targetSdk 34 } } @@ -75,6 +81,9 @@ dependencies { implementation(libs.androidx.compose.material) implementation(libs.androidx.compose.ui.tooling.preview) debugImplementation(libs.androidx.compose.ui.tooling) + + // Testing + testImplementation(libs.junit) } apply from: "${rootDir}/scripts/publish-module.gradle" diff --git a/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/Barcode.kt b/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/Barcode.kt index b6df915..96356d0 100644 --- a/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/Barcode.kt +++ b/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/Barcode.kt @@ -91,3 +91,51 @@ fun Barcode( } } } + +/** + * SynchronousBarcode generates a barcode bitmap synchronously during composition. + * This version is intended for snapshot testing with Paparazzi where asynchronous + * operations are not suitable. For production use, prefer the async [Barcode] composable. + * + * @param modifier the modifier to be applied to the layout + * @param resolutionFactor multiplied on the width/height to get the resolution, in px, for the bitmap + * @param width for the generated bitmap multiplied by the resolutionFactor + * @param height for the generated bitmap multiplied by the resolutionFactor + * @param type the type of barcode to render + * @param value the value of the barcode to show + * @param encodeHints immutable ZXing encode hints wrapper (for example, setting CHARACTER_SET) + */ +@Composable +fun SynchronousBarcode( + modifier: Modifier = Modifier, + resolutionFactor: Int = 1, + width: Dp = 128.dp, + height: Dp = 128.dp, + type: BarcodeType, + value: String, + encodeHints: BarcodeEncodeHints = BarcodeEncodeHints.None +) { + val barcodeBitmap = remember(value, type, width, height, resolutionFactor, encodeHints) { + try { + type.getImageBitmap( + width = (width.value * resolutionFactor).toInt(), + height = (height.value * resolutionFactor).toInt(), + value = value, + encodeHints = encodeHints + ) + } catch (e: Exception) { + Log.e("ComposeBarcodes", "Invalid Barcode Format", e) + null + } + } + + Box(modifier = modifier) { + barcodeBitmap?.let { barcode -> + Image( + modifier = Modifier.fillMaxSize(), + painter = BitmapPainter(barcode), + contentDescription = value + ) + } + } +} diff --git a/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/BarcodePreviews.kt b/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/BarcodePreviews.kt new file mode 100644 index 0000000..f9f0b2d --- /dev/null +++ b/composed-barcodes/src/main/kotlin/com/simonsickle/compose/barcodes/BarcodePreviews.kt @@ -0,0 +1,259 @@ +package com.simonsickle.compose.barcodes + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.material.lightColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +/** + * Preview composables for the Barcode component to enable snapshot testing. + * + * Each preview uses SynchronousBarcode with matching width/height parameters + * to prevent distortion and maintain proper aspect ratios for each barcode type: + * - Square (200x200): QR Code, Data Matrix, Aztec + * - Wide rectangle (400x120): Code 128, Code 39 + * - Wide rectangle (400x150): EAN-13, UPC-A + * - Medium rectangle (300x100): PDF417 + */ + +@Preview(name = "QR Code Default") +@Composable +fun BarcodeQrCodePreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(200.dp) + .height(200.dp), + type = BarcodeType.QR_CODE, + value = "https://github.com/simonsickle/composed-barcodes", + width = 200.dp, + height = 200.dp + ) + Text("QR Code") + } + } + } +} + +@Preview(name = "Code128 Barcode") +@Composable +fun BarcodeCode128Preview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(400.dp) + .height(120.dp), + type = BarcodeType.CODE_128, + value = "123456789012", + width = 400.dp, + height = 120.dp + ) + Text("Code 128") + } + } + } +} + +@Preview(name = "EAN13 Barcode") +@Composable +fun BarcodeEan13Preview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(400.dp) + .height(150.dp), + type = BarcodeType.EAN_13, + value = "978020137962", + width = 400.dp, + height = 150.dp + ) + Text("EAN-13") + } + } + } +} + +@Preview(name = "UPC-A Barcode") +@Composable +fun BarcodeUpcAPreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(400.dp) + .height(150.dp), + type = BarcodeType.UPC_A, + value = "012345678905", + width = 400.dp, + height = 150.dp + ) + Text("UPC-A") + } + } + } +} + +@Preview(name = "Data Matrix") +@Composable +fun BarcodeDataMatrixPreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(200.dp) + .height(200.dp), + type = BarcodeType.DATA_MATRIX, + value = "Data Matrix Test", + width = 200.dp, + height = 200.dp + ) + Text("Data Matrix") + } + } + } +} + +@Preview(name = "Aztec Code") +@Composable +fun BarcodeAztecPreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(200.dp) + .height(200.dp), + type = BarcodeType.AZTEC, + value = "Aztec Code Test", + width = 200.dp, + height = 200.dp + ) + Text("Aztec Code") + } + } + } +} + +@Preview(name = "PDF417 Barcode") +@Composable +fun BarcodePdf417Preview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(300.dp) + .height(100.dp), + type = BarcodeType.PDF_417, + value = "PDF417 Test Data", + width = 300.dp, + height = 100.dp + ) + Text("PDF417") + } + } + } +} + +@Preview(name = "Barcode Without Progress Indicator") +@Composable +fun BarcodeNoProgressPreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Box(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(200.dp) + .height(200.dp) + .align(Alignment.Center), + type = BarcodeType.QR_CODE, + value = "No Progress Test", + width = 200.dp, + height = 200.dp + ) + } + } + } +} + +@Preview(name = "High Resolution Barcode") +@Composable +fun BarcodeHighResolutionPreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(200.dp) + .height(200.dp), + type = BarcodeType.QR_CODE, + value = "High Resolution Test", + resolutionFactor = 4 + ) + Text("High Resolution (4x)") + } + } + } +} + +@Preview(name = "Small QR Code") +@Composable +fun BarcodeSmallPreview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(100.dp) + .height(100.dp), + type = BarcodeType.QR_CODE, + value = "Small", + width = 100.dp, + height = 100.dp + ) + Text("Small QR Code") + } + } + } +} + +@Preview(name = "Code39 Barcode") +@Composable +fun BarcodeCode39Preview() { + MaterialTheme(colors = lightColors()) { + Surface(color = MaterialTheme.colors.background) { + Column(modifier = Modifier.background(Color.White).padding(16.dp)) { + SynchronousBarcode( + modifier = Modifier + .width(400.dp) + .height(120.dp), + type = BarcodeType.CODE_39, + value = "CODE39TEST", + width = 400.dp, + height = 120.dp + ) + Text("Code 39") + } + } + } +} diff --git a/composed-barcodes/src/test/kotlin/com/simonsickle/compose/barcodes/BarcodeSnapshotTest.kt b/composed-barcodes/src/test/kotlin/com/simonsickle/compose/barcodes/BarcodeSnapshotTest.kt new file mode 100644 index 0000000..af0c20b --- /dev/null +++ b/composed-barcodes/src/test/kotlin/com/simonsickle/compose/barcodes/BarcodeSnapshotTest.kt @@ -0,0 +1,100 @@ +package com.simonsickle.compose.barcodes + +import app.cash.paparazzi.DeviceConfig +import app.cash.paparazzi.Paparazzi +import org.junit.Rule +import org.junit.Test + +/** + * Paparazzi snapshot tests for the Barcode composable. + * These tests verify the visual appearance of different barcode types and configurations. + * + * Uses SynchronousBarcode in preview composables to ensure actual barcodes are rendered + * in snapshots rather than loading states. Each preview includes matching width/height + * parameters to prevent distortion and maintain proper aspect ratios. + */ +class BarcodeSnapshotTest { + + @get:Rule + val paparazzi = Paparazzi( + deviceConfig = DeviceConfig.PIXEL_5, + showSystemUi = false + ) + + @Test + fun barcodeQrCode() { + paparazzi.snapshot { + BarcodeQrCodePreview() + } + } + + @Test + fun barcodeCode128() { + paparazzi.snapshot { + BarcodeCode128Preview() + } + } + + @Test + fun barcodeEan13() { + paparazzi.snapshot { + BarcodeEan13Preview() + } + } + + @Test + fun barcodeUpcA() { + paparazzi.snapshot { + BarcodeUpcAPreview() + } + } + + @Test + fun barcodeDataMatrix() { + paparazzi.snapshot { + BarcodeDataMatrixPreview() + } + } + + @Test + fun barcodeAztec() { + paparazzi.snapshot { + BarcodeAztecPreview() + } + } + + @Test + fun barcodePdf417() { + paparazzi.snapshot { + BarcodePdf417Preview() + } + } + + @Test + fun barcodeNoProgress() { + paparazzi.snapshot { + BarcodeNoProgressPreview() + } + } + + @Test + fun barcodeHighResolution() { + paparazzi.snapshot { + BarcodeHighResolutionPreview() + } + } + + @Test + fun barcodeSmall() { + paparazzi.snapshot { + BarcodeSmallPreview() + } + } + + @Test + fun barcodeCode39() { + paparazzi.snapshot { + BarcodeCode39Preview() + } + } +} diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeAztec.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeAztec.png new file mode 100644 index 0000000..226272a Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeAztec.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeCode128.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeCode128.png new file mode 100644 index 0000000..28717b8 Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeCode128.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeCode39.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeCode39.png new file mode 100644 index 0000000..104d34c Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeCode39.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeDataMatrix.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeDataMatrix.png new file mode 100644 index 0000000..e02ee9e Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeDataMatrix.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeEan13.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeEan13.png new file mode 100644 index 0000000..a0252fb Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeEan13.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeHighResolution.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeHighResolution.png new file mode 100644 index 0000000..be70fd8 Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeHighResolution.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeNoProgress.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeNoProgress.png new file mode 100644 index 0000000..a04d75f Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeNoProgress.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodePdf417.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodePdf417.png new file mode 100644 index 0000000..db9f01d Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodePdf417.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeQrCode.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeQrCode.png new file mode 100644 index 0000000..32f32a0 Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeQrCode.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeSmall.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeSmall.png new file mode 100644 index 0000000..b04b8ad Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeSmall.png differ diff --git a/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeUpcA.png b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeUpcA.png new file mode 100644 index 0000000..bd8fe68 Binary files /dev/null and b/composed-barcodes/src/test/snapshots/images/com.simonsickle.compose.barcodes_BarcodeSnapshotTest_barcodeUpcA.png differ diff --git a/gradle.properties b/gradle.properties index 9d86238..0492924 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,3 +20,5 @@ kotlin.code.style=official android.uniquePackageNames=false android.dependency.useConstraints=false android.r8.strictFullModeForKeepRules=false +org.gradle.configuration-cache=false +android.suppressUnsupportedCompileSdk=34 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b5abaf6..39d4b63 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,6 +5,8 @@ appcompat = "1.7.1" material = "1.13.0" navigationCompose = "2.9.7" zxingCore = "3.5.4" +paparazzi = "1.3.4" +junit = "4.13.2" [libraries] androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } @@ -20,3 +22,7 @@ androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } zxing-core = { group = "com.google.zxing", name = "core", version.ref = "zxingCore" } +junit = { group = "junit", name = "junit", version.ref = "junit" } + +[plugins] +paparazzi = { id = "app.cash.paparazzi", version.ref = "paparazzi" }