From 534935c9ff0158a2310420dd7a3a36982d5656bb Mon Sep 17 00:00:00 2001 From: Jake Wharton Date: Fri, 29 Sep 2023 11:01:06 -0400 Subject: [PATCH] Add UIKit screenshot tests for layout's Spacer This adds the start of a new setup for hosting Kotlin tests within an iOS project so that we can use a Swift screenshot testing library. For now you have to prefix your test functions with "test" and any before/after-annotated functions need to be named "setUp" and "tearDown" (very JUnit 3). We also do not support anything JVM-specific like rules or parameterization for now. --- .github/workflows/build.yaml | 8 +- gradle/libs.versions.toml | 1 + ...ui_ComposeUiSpacerTest_testBothSpacer.png} | 0 ...poseUiSpacerTest_testHeightOnlySpacer.png} | 0 ...mposeUiSpacerTest_testWidthOnlySpacer.png} | 0 ...ui_ComposeUiSpacerTest_testZeroSpacer.png} | 0 redwood-layout-shared-test/build.gradle | 38 +- .../cash/redwood/layout/AbstractSpacerTest.kt | 10 +- .../layout/AbstractFlexContainerTest.kt | 0 .../project.pbxproj | 410 ++++++++++++++++++ .../KotlinHostingXCTestCase.swift | 64 +++ .../KotlinHostingXCTestCaseHelper.h | 18 + .../KotlinHostingXCTestCaseHelper.m | 23 + ...RedwoodLayoutUIViewTests-Bridging-Header.h | 5 + .../UIViewSpacerTestHost.swift | 29 ++ .../verifySnapshot-view.testBothSpacer.png | 3 + ...rifySnapshot-view.testHeightOnlySpacer.png | 3 + ...erifySnapshot-view.testWidthOnlySpacer.png | 3 + .../verifySnapshot-view.testZeroSpacer.png | 3 + redwood-layout-uiview/build.gradle | 29 +- .../redwood/layout/uiview/UIViewSpacerTest.kt | 61 +++ ...ut.view_ViewSpacerTest_testBothSpacer.png} | 0 ...w_ViewSpacerTest_testHeightOnlySpacer.png} | 0 ...ew_ViewSpacerTest_testWidthOnlySpacer.png} | 0 ...ut.view_ViewSpacerTest_testZeroSpacer.png} | 0 25 files changed, 676 insertions(+), 32 deletions(-) rename redwood-layout-composeui/src/test/snapshots/images/{app.cash.redwood.layout.composeui_ComposeUiSpacerTest_bothSpacer.png => app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testBothSpacer.png} (100%) rename redwood-layout-composeui/src/test/snapshots/images/{app.cash.redwood.layout.composeui_ComposeUiSpacerTest_heightOnlySpacer.png => app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testHeightOnlySpacer.png} (100%) rename redwood-layout-composeui/src/test/snapshots/images/{app.cash.redwood.layout.composeui_ComposeUiSpacerTest_widthOnlySpacer.png => app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testWidthOnlySpacer.png} (100%) rename redwood-layout-composeui/src/test/snapshots/images/{app.cash.redwood.layout.composeui_ComposeUiSpacerTest_zeroSpacer.png => app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testZeroSpacer.png} (100%) rename redwood-layout-shared-test/src/{main => commonMain}/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt (90%) rename redwood-layout-shared-test/src/{main => jvmMain}/kotlin/app/cash/redwood/layout/AbstractFlexContainerTest.kt (100%) create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests.xcodeproj/project.pbxproj create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCase.swift create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.h create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.m create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/RedwoodLayoutUIViewTests-Bridging-Header.h create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/UIViewSpacerTestHost.swift create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testBothSpacer.png create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testHeightOnlySpacer.png create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testWidthOnlySpacer.png create mode 100644 redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testZeroSpacer.png create mode 100644 redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSpacerTest.kt rename redwood-layout-view/src/test/snapshots/images/{app.cash.redwood.layout.view_ViewSpacerTest_bothSpacer.png => app.cash.redwood.layout.view_ViewSpacerTest_testBothSpacer.png} (100%) rename redwood-layout-view/src/test/snapshots/images/{app.cash.redwood.layout.view_ViewSpacerTest_heightOnlySpacer.png => app.cash.redwood.layout.view_ViewSpacerTest_testHeightOnlySpacer.png} (100%) rename redwood-layout-view/src/test/snapshots/images/{app.cash.redwood.layout.view_ViewSpacerTest_widthOnlySpacer.png => app.cash.redwood.layout.view_ViewSpacerTest_testWidthOnlySpacer.png} (100%) rename redwood-layout-view/src/test/snapshots/images/{app.cash.redwood.layout.view_ViewSpacerTest_zeroSpacer.png => app.cash.redwood.layout.view_ViewSpacerTest_testZeroSpacer.png} (100%) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 214336b689..8fa2bba7a7 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -74,8 +74,8 @@ jobs: path: build/dokka/htmlMultiModule/ if-no-files-found: error - paparazzi: - runs-on: ubuntu-latest + screenshot-tests: + runs-on: macos-latest steps: - uses: actions/checkout@v4 with: @@ -91,6 +91,8 @@ jobs: - run: ./gradlew verifyPaparazziDebug + - run: xcodebuild -project redwood-layout-uiview/RedwoodLayoutUIViewTests.xcodeproj -scheme RedwoodLayoutUIViewTests -destination 'platform=iOS Simulator,name=iPhone 12,OS=latest' test + sample-counter: runs-on: macos-latest steps: @@ -161,9 +163,9 @@ jobs: - build - connected - dokka - - paparazzi - sample-counter - sample-emoji + - screenshot-tests - test-app steps: - uses: actions/checkout@v4 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c209da159e..ed9ba65b6a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,7 @@ kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", ve kotlin-serializationPlugin = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } diff --git a/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_bothSpacer.png b/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testBothSpacer.png similarity index 100% rename from redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_bothSpacer.png rename to redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testBothSpacer.png diff --git a/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_heightOnlySpacer.png b/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testHeightOnlySpacer.png similarity index 100% rename from redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_heightOnlySpacer.png rename to redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testHeightOnlySpacer.png diff --git a/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_widthOnlySpacer.png b/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testWidthOnlySpacer.png similarity index 100% rename from redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_widthOnlySpacer.png rename to redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testWidthOnlySpacer.png diff --git a/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_zeroSpacer.png b/redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testZeroSpacer.png similarity index 100% rename from redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_zeroSpacer.png rename to redwood-layout-composeui/src/test/snapshots/images/app.cash.redwood.layout.composeui_ComposeUiSpacerTest_testZeroSpacer.png diff --git a/redwood-layout-shared-test/build.gradle b/redwood-layout-shared-test/build.gradle index 98fd9881bc..311c9938ce 100644 --- a/redwood-layout-shared-test/build.gradle +++ b/redwood-layout-shared-test/build.gradle @@ -1,12 +1,30 @@ -apply plugin: 'org.jetbrains.kotlin.jvm' +import app.cash.redwood.buildsupport.KmpTargets -dependencies { - api projects.redwoodLayoutApi - api projects.redwoodLayoutModifiers - api projects.redwoodLayoutWidget - api projects.redwoodRuntime - api projects.redwoodWidget - api projects.redwoodYoga - api libs.junit - api libs.testParameterInjector +apply plugin: 'org.jetbrains.kotlin.multiplatform' + +kotlin { + KmpTargets.addAllTargets(project) + + sourceSets { + commonMain { + dependencies { + api projects.redwoodLayoutApi + api projects.redwoodLayoutModifiers + api projects.redwoodLayoutWidget + api projects.redwoodRuntime + api projects.redwoodWidget + api projects.redwoodYoga + api libs.kotlin.test + } + } + jvmMain { + dependencies { + // The kotlin.test library provides JVM variants for multiple testing frameworks. When used + // as a test dependency this selection is transparent. But since we are publishing a library + // we need to select one ourselves at compilation time. + api libs.kotlin.test.junit + api libs.testParameterInjector + } + } + } } diff --git a/redwood-layout-shared-test/src/main/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt b/redwood-layout-shared-test/src/commonMain/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt similarity index 90% rename from redwood-layout-shared-test/src/main/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt rename to redwood-layout-shared-test/src/commonMain/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt index 66b1628433..549efcac21 100644 --- a/redwood-layout-shared-test/src/main/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt +++ b/redwood-layout-shared-test/src/commonMain/kotlin/app/cash/redwood/layout/AbstractSpacerTest.kt @@ -18,7 +18,7 @@ package app.cash.redwood.layout import app.cash.redwood.layout.widget.Spacer import app.cash.redwood.ui.dp import app.cash.redwood.widget.Widget -import org.junit.Test +import kotlin.test.Test abstract class AbstractSpacerTest { @@ -33,22 +33,22 @@ abstract class AbstractSpacerTest { height(height.dp) } - @Test fun zeroSpacer() { + @Test fun testZeroSpacer() { val widget = widget(width = 0, height = 0) verifySnapshot(wrap(widget, horizontal = true)) } - @Test fun widthOnlySpacer() { + @Test fun testWidthOnlySpacer() { val widget = widget(width = 100, height = 0) verifySnapshot(wrap(widget, horizontal = true)) } - @Test fun heightOnlySpacer() { + @Test fun testHeightOnlySpacer() { val widget = widget(width = 0, height = 100) verifySnapshot(wrap(widget, horizontal = false)) } - @Test fun bothSpacer() { + @Test fun testBothSpacer() { val widget = widget(width = 100, height = 100) verifySnapshot(wrap(widget, horizontal = false)) } diff --git a/redwood-layout-shared-test/src/main/kotlin/app/cash/redwood/layout/AbstractFlexContainerTest.kt b/redwood-layout-shared-test/src/jvmMain/kotlin/app/cash/redwood/layout/AbstractFlexContainerTest.kt similarity index 100% rename from redwood-layout-shared-test/src/main/kotlin/app/cash/redwood/layout/AbstractFlexContainerTest.kt rename to redwood-layout-shared-test/src/jvmMain/kotlin/app/cash/redwood/layout/AbstractFlexContainerTest.kt diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests.xcodeproj/project.pbxproj b/redwood-layout-uiview/RedwoodLayoutUIViewTests.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..4c01754262 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests.xcodeproj/project.pbxproj @@ -0,0 +1,410 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + CB408CE82AC64CEF00E1BA00 /* UIViewSpacerTestHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB408CE72AC64CEF00E1BA00 /* UIViewSpacerTestHost.swift */; }; + CB408CED2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB408CEC2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift */; }; + CB408CF72AC657EF00E1BA00 /* KotlinHostingXCTestCaseHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = CB408CF62AC657EF00E1BA00 /* KotlinHostingXCTestCaseHelper.m */; }; + CB8A21EF2AC6647F00C104C2 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = CB8A21EE2AC6647F00C104C2 /* SnapshotTesting */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 63E90CF521FEBBB700449E04 /* RedwoodLayoutUIViewTestKt.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RedwoodLayoutUIViewTestKt.framework; path = "build/xcode-frameworks/RedwoodLayoutUIViewTestKt.framework"; sourceTree = ""; }; + CB408CE52AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RedwoodLayoutUIViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CB408CE72AC64CEF00E1BA00 /* UIViewSpacerTestHost.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewSpacerTestHost.swift; sourceTree = ""; }; + CB408CEC2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KotlinHostingXCTestCase.swift; sourceTree = ""; }; + CB408CF52AC657EF00E1BA00 /* RedwoodLayoutUIViewTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RedwoodLayoutUIViewTests-Bridging-Header.h"; sourceTree = ""; }; + CB408CF62AC657EF00E1BA00 /* KotlinHostingXCTestCaseHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KotlinHostingXCTestCaseHelper.m; sourceTree = ""; }; + CB408CF82AC6581100E1BA00 /* KotlinHostingXCTestCaseHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KotlinHostingXCTestCaseHelper.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + CB408CE22AC64CEF00E1BA00 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CB8A21EF2AC6647F00C104C2 /* SnapshotTesting in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00D5E68C2AAF3EBD00692213 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 635661C821F12B7D00DD7240 = { + isa = PBXGroup; + children = ( + CB408CE62AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests */, + 635661D221F12B7E00DD7240 /* Products */, + 00D5E68C2AAF3EBD00692213 /* Frameworks */, + 63E90CF521FEBBB700449E04 /* RedwoodLayoutUIViewTestKt.framework */, + ); + sourceTree = ""; + }; + 635661D221F12B7E00DD7240 /* Products */ = { + isa = PBXGroup; + children = ( + CB408CE52AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CB408CE62AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests */ = { + isa = PBXGroup; + children = ( + CB408CE72AC64CEF00E1BA00 /* UIViewSpacerTestHost.swift */, + CB408CEC2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift */, + CB408CF62AC657EF00E1BA00 /* KotlinHostingXCTestCaseHelper.m */, + CB408CF52AC657EF00E1BA00 /* RedwoodLayoutUIViewTests-Bridging-Header.h */, + CB408CF82AC6581100E1BA00 /* KotlinHostingXCTestCaseHelper.h */, + ); + path = RedwoodLayoutUIViewTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + CB408CE42AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB408CE92AC64CEF00E1BA00 /* Build configuration list for PBXNativeTarget "RedwoodLayoutUIViewTests" */; + buildPhases = ( + 00DD12E22AAF46C500CA3FD3 /* ShellScript */, + CB408CE12AC64CEF00E1BA00 /* Sources */, + CB408CE22AC64CEF00E1BA00 /* Frameworks */, + CB408CE32AC64CEF00E1BA00 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RedwoodLayoutUIViewTests; + packageProductDependencies = ( + CB8A21EE2AC6647F00C104C2 /* SnapshotTesting */, + ); + productName = RedwoodLayoutUIViewTests; + productReference = CB408CE52AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 635661C921F12B7D00DD7240 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1420; + LastUpgradeCheck = 1220; + ORGANIZATIONNAME = "Square Inc"; + TargetAttributes = { + CB408CE42AC64CEF00E1BA00 = { + CreatedOnToolsVersion = 14.2; + LastSwiftMigration = 1420; + }; + }; + }; + buildConfigurationList = 635661CC21F12B7D00DD7240 /* Build configuration list for PBXProject "RedwoodLayoutUIViewTests" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 635661C821F12B7D00DD7240; + packageReferences = ( + CB8A21ED2AC6647F00C104C2 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */, + ); + productRefGroup = 635661D221F12B7E00DD7240 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CB408CE42AC64CEF00E1BA00 /* RedwoodLayoutUIViewTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + CB408CE32AC64CEF00E1BA00 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD12E22AAF46C500CA3FD3 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd \"$SRCROOT/..\"\n./gradlew :redwood-layout-uiview:embedAndSignAppleFrameworkForXcode\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + CB408CE12AC64CEF00E1BA00 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CB408CED2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift in Sources */, + CB408CF72AC657EF00E1BA00 /* KotlinHostingXCTestCaseHelper.m in Sources */, + CB408CE82AC64CEF00E1BA00 /* UIViewSpacerTestHost.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 635661E121F12B8000DD7240 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 635661E221F12B8000DD7240 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + CB408CEA2AC64CEF00E1BA00 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-l\"c++\"", + "-framework", + "\"RedwoodLayoutUIViewTestKt\"", + "-ObjC", + "-framework", + RedwoodLayoutUIViewTestKt, + ); + PRODUCT_BUNDLE_IDENTIFIER = app.cash.redwood.layout.uiview.testing; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OBJC_BRIDGING_HEADER = "RedwoodLayoutUIViewTests/RedwoodLayoutUIViewTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + CB408CEB2AC64CEF00E1BA00 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)"; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-l\"c++\"", + "-framework", + "\"RedwoodLayoutUIViewTestKt\"", + "-ObjC", + "-framework", + RedwoodLayoutUIViewTestKt, + ); + PRODUCT_BUNDLE_IDENTIFIER = app.cash.redwood.layout.uiview.testing; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OBJC_BRIDGING_HEADER = "RedwoodLayoutUIViewTests/RedwoodLayoutUIViewTests-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 635661CC21F12B7D00DD7240 /* Build configuration list for PBXProject "RedwoodLayoutUIViewTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 635661E121F12B8000DD7240 /* Debug */, + 635661E221F12B8000DD7240 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CB408CE92AC64CEF00E1BA00 /* Build configuration list for PBXNativeTarget "RedwoodLayoutUIViewTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB408CEA2AC64CEF00E1BA00 /* Debug */, + CB408CEB2AC64CEF00E1BA00 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + CB8A21ED2AC6647F00C104C2 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/pointfreeco/swift-snapshot-testing"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + CB8A21EE2AC6647F00C104C2 /* SnapshotTesting */ = { + isa = XCSwiftPackageProductDependency; + package = CB8A21ED2AC6647F00C104C2 /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */; + productName = SnapshotTesting; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 635661C921F12B7D00DD7240 /* Project object */; +} diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCase.swift b/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCase.swift new file mode 100644 index 0000000000..14b378acb6 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCase.swift @@ -0,0 +1,64 @@ +import Foundation +import XCTest + +/** + * An abstract base class for hosting Kotlin test classes in Swift projects. + * + * Subclasses must override `initTest(name:)` to create instances of `KotlinType`. + */ +open class KotlinHostingXCTestCase: KotlinHostingXCTestCaseHelper where KotlinTest: NSObject { + /** + * Create an instance of `KotlinTest` for invoking test method `name`. + */ + open class func initTest(name: String) -> KotlinTest { + fatalError("Missing override for initTest(name:)") + } + + public override class func createTestMethods() { + var targetClass: AnyClass = KotlinTest.self + while (targetClass != NSObject.self) { + var methodCount: UInt32 = 0 + let methodList = class_copyMethodList(targetClass, &methodCount) + if let methodList = methodList { + defer { free(methodList) } + + for i in 0.. Void = { + if target.responds(to: #selector(setUp)) { + target.perform(#selector(setUp)) + } + defer { + if target.responds(to: #selector(tearDown)) { + target.perform(#selector(tearDown)) + } + } + + target.perform(selector) + } + let implementation = imp_implementationWithBlock(block) + class_addMethod(self, selector, implementation, "v@:") + } + + public override class var defaultTestSuite: XCTestSuite { + createTestMethods() + return super.defaultTestSuite + } +} diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.h b/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.h new file mode 100644 index 0000000000..6b8e3c783f --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.h @@ -0,0 +1,18 @@ +// Created by Michał Laskowski on 10/02/2020. +// Copyright © 2020 Michał Laskowski. All rights reserved. + +#ifndef TestBase_h +#define TestBase_h +@import XCTest; + +NS_ASSUME_NONNULL_BEGIN + +@interface KotlinHostingXCTestCaseHelper : XCTestCase + ++(void)createTestMethods; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* TestBase_h */ diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.m b/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.m new file mode 100644 index 0000000000..39d6c1ee38 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/KotlinHostingXCTestCaseHelper.m @@ -0,0 +1,23 @@ +// Created by Michał Laskowski on 10/02/2020. +// Copyright © 2020 Michał Laskowski. All rights reserved. + +#import +#include "KotlinHostingXCTestCaseHelper.h" +#import "objc/runtime.h" + +@implementation KotlinHostingXCTestCaseHelper + ++(void)createTestMethods { + [NSException raise:@"NotImplemented" format:@"Subclasses must implement a valid createTestMethods method"]; +} + +/** + This is overriden in order to be able to trigger tests from Test Navigator panel. Method can not be overriden in Swift, because it needs also + to override `testCaseWithInvocation:`. And using NSInvocation is not possible in Swift. Hence this Obj-C TestBase class, and this method. + */ ++(instancetype)testCaseWithSelector:(SEL)selector { + [self createTestMethods]; + return [super testCaseWithSelector:selector]; +} + +@end diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/RedwoodLayoutUIViewTests-Bridging-Header.h b/redwood-layout-uiview/RedwoodLayoutUIViewTests/RedwoodLayoutUIViewTests-Bridging-Header.h new file mode 100644 index 0000000000..e3b26ca019 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/RedwoodLayoutUIViewTests-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#include "KotlinHostingXCTestCaseHelper.h" diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/UIViewSpacerTestHost.swift b/redwood-layout-uiview/RedwoodLayoutUIViewTests/UIViewSpacerTestHost.swift new file mode 100644 index 0000000000..5099314498 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/UIViewSpacerTestHost.swift @@ -0,0 +1,29 @@ +// +// UIViewSpacerTestHost.swift +// RedwoodLayoutUIViewTests +// +// Created by Jake Wharton on 9/28/23. +// Copyright © 2023 Square Inc. All rights reserved. +// + +import SnapshotTesting +import RedwoodLayoutUIViewTestKt +import UIKit + +final class UIViewSpacerTestHost: KotlinHostingXCTestCase { + override class func initTest(name: String) -> UIViewSpacerTest { + return UIViewSpacerTest(callback: Callback(named: name)) + } +} + +private class Callback : UIViewSpacerTestCallback { + private let name: String + + init(named name: String) { + self.name = name + } + + func verifySnapshot(view: UIView) { + assertSnapshot(of: view, as: .image, named: name) + } +} diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testBothSpacer.png b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testBothSpacer.png new file mode 100644 index 0000000000..a8976739dc --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testBothSpacer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a58dfb47e6b680ad1b2f7b9af34e020eab455f250ca330f9d515fb7c614595b4 +size 6468 diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testHeightOnlySpacer.png b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testHeightOnlySpacer.png new file mode 100644 index 0000000000..35c6724760 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testHeightOnlySpacer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9e8506fb3eb0f85beec0df8140a545deecf5f28e80c7230ffc7ce5be8ebbc8f +size 5071 diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testWidthOnlySpacer.png b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testWidthOnlySpacer.png new file mode 100644 index 0000000000..2a98e68e10 --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testWidthOnlySpacer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fabf6e1666eb1c39ec024129a937da7018695b4bbbc8f7878142e6e0a14d935 +size 3647 diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testZeroSpacer.png b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testZeroSpacer.png new file mode 100644 index 0000000000..a6f2a8757c --- /dev/null +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/__Snapshots__/UIViewSpacerTestHost/verifySnapshot-view.testZeroSpacer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f641aa41af975c180667f5edc8df3a2179547794d7de72f2c4419485f47f9f7 +size 3076 diff --git a/redwood-layout-uiview/build.gradle b/redwood-layout-uiview/build.gradle index f2e2e235f4..5146de327b 100644 --- a/redwood-layout-uiview/build.gradle +++ b/redwood-layout-uiview/build.gradle @@ -8,9 +8,16 @@ redwoodBuild { } kotlin { - iosArm64() - iosX64() - iosSimulatorArm64() + [ + iosArm64(), + iosX64(), + iosSimulatorArm64(), + ].each { iosTarget -> + iosTarget.binaries.framework { + compilation = iosTarget.compilations.test + baseName = 'RedwoodLayoutUIViewTestKt' + } + } sourceSets { commonMain { @@ -22,17 +29,11 @@ kotlin { implementation projects.redwoodYoga } } - - iosArm64Main { - dependsOn commonMain - } - - iosX64Main { - dependsOn commonMain - } - - iosSimulatorArm64Main { - dependsOn commonMain + commonTest { + dependencies { + api projects.redwoodLayoutSharedTest + api libs.kotlin.test + } } } } diff --git a/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSpacerTest.kt b/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSpacerTest.kt new file mode 100644 index 0000000000..53bb053079 --- /dev/null +++ b/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSpacerTest.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package app.cash.redwood.layout.uiview + +import app.cash.redwood.layout.AbstractSpacerTest +import app.cash.redwood.widget.Widget +import kotlinx.cinterop.readValue +import kotlinx.cinterop.useContents +import platform.CoreGraphics.CGRectMake +import platform.UIKit.UILabel +import platform.UIKit.UILayoutConstraintAxisHorizontal +import platform.UIKit.UILayoutConstraintAxisVertical +import platform.UIKit.UILayoutFittingCompressedSize +import platform.UIKit.UIStackView +import platform.UIKit.UIView + +interface UIViewSpacerTestCallback { + fun verifySnapshot(view: UIView) +} + +class UIViewSpacerTest( + private val callback: UIViewSpacerTestCallback, +) : AbstractSpacerTest() { + private val factory = UIViewRedwoodLayoutWidgetFactory() + + override fun widget() = factory.Spacer() + + override fun wrap(widget: Widget, horizontal: Boolean): UIView { + return UIStackView().apply { + axis = if (horizontal) UILayoutConstraintAxisHorizontal else UILayoutConstraintAxisVertical + addArrangedSubview(UILabel().apply { text = "Text 1" }) + addArrangedSubview(widget.value) + addArrangedSubview(UILabel().apply { text = "Text 2" }) + + // Force the frame to match the smallest size which fits the contents. + val size = systemLayoutSizeFittingSize(UILayoutFittingCompressedSize.readValue()) + setFrame( + size.useContents { + CGRectMake(0.0, 0.0, width, height) + }, + ) + } + } + + override fun verifySnapshot(value: UIView) { + callback.verifySnapshot(value) + } +} diff --git a/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_bothSpacer.png b/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testBothSpacer.png similarity index 100% rename from redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_bothSpacer.png rename to redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testBothSpacer.png diff --git a/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_heightOnlySpacer.png b/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testHeightOnlySpacer.png similarity index 100% rename from redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_heightOnlySpacer.png rename to redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testHeightOnlySpacer.png diff --git a/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_widthOnlySpacer.png b/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testWidthOnlySpacer.png similarity index 100% rename from redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_widthOnlySpacer.png rename to redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testWidthOnlySpacer.png diff --git a/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_zeroSpacer.png b/redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testZeroSpacer.png similarity index 100% rename from redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_zeroSpacer.png rename to redwood-layout-view/src/test/snapshots/images/app.cash.redwood.layout.view_ViewSpacerTest_testZeroSpacer.png