From 10ae978151b880b6abc1d3e48b3d7969c28cbcbb Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Thu, 29 Aug 2024 12:08:33 -0400 Subject: [PATCH] New snapshot test for LazyList loading and unloading (#2265) * New snapshot test for LazyList loading and unloading This is in the wrong module as I intend to reuse the test infrastructure in redwood-layout-uiview to test the iOS implementation. * Test UIViewLazyList * Delay snapshots one frame * record: false * Copy-paste snapshot testing infrastructure for lazylist Rather than using the wrong module, or introducing build infrastructure to abstract it up. --- .github/workflows/build.yaml | 2 + .../SnapshotTestingCallback.swift | 4 +- .../layout/uiview/UIViewSnapshotCallback.kt | 2 +- redwood-lazylayout-shared-test/build.gradle | 28 ++ .../lazylayout/AbstractLazyListTest.kt | 134 ++++++ .../cash/redwood/lazylayout/utils.common.kt | 36 ++ .../app/cash/redwood/lazylayout/utils.kt | 27 ++ .../project.pbxproj | 420 ++++++++++++++++++ .../RedwoodLazylayoutUIViewTests.xcscheme | 54 +++ .../KotlinHostingXCTestCase.swift | 63 +++ .../KotlinHostingXCTestCaseHelper.h | 20 + .../KotlinHostingXCTestCaseHelper.m | 25 ++ ...oodLazylayoutUIViewTests-Bridging-Header.h | 1 + .../SnapshotTestingCallback.swift | 19 + .../UIViewLazyListTestHost.swift | 8 + .../testHappyPath.1.png | Bin 0 -> 82884 bytes ...ToLoadedAndLoadedToPlaceholder.0-empty.png | Bin 0 -> 34674 bytes ...dAndLoadedToPlaceholder.1-placeholders.png | Bin 0 -> 61236 bytes ...oLoadedAndLoadedToPlaceholder.2-loaded.png | Bin 0 -> 102382 bytes ...dAndLoadedToPlaceholder.3-placeholders.png | Bin 0 -> 61236 bytes ...ToLoadedAndLoadedToPlaceholder.4-empty.png | Bin 0 -> 34674 bytes .../testPlaceholdersExhausted.1.png | Bin 0 -> 66523 bytes redwood-lazylayout-uiview/build.gradle | 16 + .../lazylayout/uiview/UIViewLazyListTest.kt | 52 +++ .../uiview/UIViewSnapshotCallback.kt | 22 + .../redwood/lazylayout/uiview/testWidgets.kt | 38 ++ redwood-lazylayout-view/build.gradle | 1 + .../lazylayout/view/ViewLazyListTest.kt | 70 +++ ...ut.view_ViewLazyListTest_testHappyPath.png | Bin 0 -> 13360 bytes ...ToLoadedAndLoadedToPlaceholder_0_empty.png | Bin 0 -> 3837 bytes ...dAndLoadedToPlaceholder_1_placeholders.png | Bin 0 -> 4559 bytes ...oLoadedAndLoadedToPlaceholder_2_loaded.png | Bin 0 -> 20909 bytes ...dAndLoadedToPlaceholder_3_placeholders.png | Bin 0 -> 4559 bytes ...ToLoadedAndLoadedToPlaceholder_4_empty.png | Bin 0 -> 3837 bytes ...LazyListTest_testPlaceholdersExhausted.png | Bin 0 -> 6772 bytes settings.gradle | 1 + 36 files changed, 1040 insertions(+), 3 deletions(-) create mode 100644 redwood-lazylayout-shared-test/build.gradle create mode 100644 redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/AbstractLazyListTest.kt create mode 100644 redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/utils.common.kt create mode 100644 redwood-lazylayout-shared-test/src/iosMain/kotlin/app/cash/redwood/lazylayout/utils.kt create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/project.pbxproj create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/xcshareddata/xcschemes/RedwoodLazylayoutUIViewTests.xcscheme create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCase.swift create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.h create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.m create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/RedwoodLazylayoutUIViewTests-Bridging-Header.h create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/SnapshotTestingCallback.swift create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/UIViewLazyListTestHost.swift create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testHappyPath.1.png create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.0-empty.png create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.1-placeholders.png create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.2-loaded.png create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.3-placeholders.png create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.4-empty.png create mode 100644 redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholdersExhausted.1.png create mode 100644 redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewLazyListTest.kt create mode 100644 redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewSnapshotCallback.kt create mode 100644 redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/testWidgets.kt create mode 100644 redwood-lazylayout-view/src/test/kotlin/app/cash/redwood/lazylayout/view/ViewLazyListTest.kt create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testHappyPath.png create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_0_empty.png create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_1_placeholders.png create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_2_loaded.png create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_3_placeholders.png create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_4_empty.png create mode 100644 redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholdersExhausted.png diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8f3e9d8b97..8d2f3b646a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -85,6 +85,8 @@ jobs: - run: xcodebuild -project redwood-layout-uiview/RedwoodLayoutUIViewTests.xcodeproj -scheme RedwoodLayoutUIViewTests -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' test + - run: xcodebuild -project redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj -scheme RedwoodLazylayoutUIViewTests -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' test + - uses: actions/upload-artifact@v4 if: ${{ always() }} with: diff --git a/redwood-layout-uiview/RedwoodLayoutUIViewTests/SnapshotTestingCallback.swift b/redwood-layout-uiview/RedwoodLayoutUIViewTests/SnapshotTestingCallback.swift index 41ab23050e..8700a458bc 100644 --- a/redwood-layout-uiview/RedwoodLayoutUIViewTests/SnapshotTestingCallback.swift +++ b/redwood-layout-uiview/RedwoodLayoutUIViewTests/SnapshotTestingCallback.swift @@ -11,9 +11,9 @@ final class SnapshotTestingCallback : UIViewSnapshotCallback { self.fileName = fileName } - func verifySnapshot(view: UIView, name: String?) { + func verifySnapshot(view: UIView, name: String?, delay: TimeInterval = 0.0) { // Set `record` to true to generate new snapshots. Be sure to revert that before committing! // Note that tests always fail when `record` is true. - assertSnapshot(of: view, as: .image, named: name, record: false, file: fileName, testName: testName) + assertSnapshot(of: view, as: .wait(for: delay, on: .image), named: name, record: false, file: fileName, testName: testName) } } diff --git a/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSnapshotCallback.kt b/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSnapshotCallback.kt index 2dd8d84767..06dac31412 100644 --- a/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSnapshotCallback.kt +++ b/redwood-layout-uiview/src/commonTest/kotlin/app/cash/redwood/layout/uiview/UIViewSnapshotCallback.kt @@ -18,5 +18,5 @@ package app.cash.redwood.layout.uiview import platform.UIKit.UIView interface UIViewSnapshotCallback { - fun verifySnapshot(view: UIView, name: String?) + fun verifySnapshot(view: UIView, name: String?, delay: Double = 0.0) } diff --git a/redwood-lazylayout-shared-test/build.gradle b/redwood-lazylayout-shared-test/build.gradle new file mode 100644 index 0000000000..bb78f25513 --- /dev/null +++ b/redwood-lazylayout-shared-test/build.gradle @@ -0,0 +1,28 @@ +import static app.cash.redwood.buildsupport.TargetGroup.ToolkitAllWithoutAndroid + +redwoodBuild { + targets(ToolkitAllWithoutAndroid) +} + +kotlin { + sourceSets { + commonMain { + dependencies { + api projects.redwoodLazylayoutApi + api projects.redwoodLazylayoutWidget + 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 + } + } + } +} diff --git a/redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/AbstractLazyListTest.kt b/redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/AbstractLazyListTest.kt new file mode 100644 index 0000000000..68857549c0 --- /dev/null +++ b/redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/AbstractLazyListTest.kt @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2024 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.lazylayout + +import app.cash.redwood.Modifier +import app.cash.redwood.layout.api.Constraint +import app.cash.redwood.layout.api.CrossAxisAlignment +import app.cash.redwood.lazylayout.api.ScrollItemIndex +import app.cash.redwood.lazylayout.widget.LazyList +import app.cash.redwood.ui.Margin +import app.cash.redwood.ui.dp +import app.cash.redwood.widget.ChangeListener +import app.cash.redwood.widget.Widget +import kotlin.test.Test + +abstract class AbstractLazyListTest { + abstract fun text(): Text + + private fun coloredText( + modifier: Modifier = Modifier, + text: String, + backgroundColor: Int = Green, + ) = text().apply { + this.modifier = modifier + text(text) + bgColor(backgroundColor) + } + + abstract fun lazyList( + backgroundColor: Int = argb(51, 0, 0, 255), + ): LazyList + + private fun defaultLazyList(): LazyList { + val result = lazyList() + for (i in 0 until 10) { + result.placeholder.insert(i, coloredText(text = "...")) + } + result.isVertical(true) + result.itemsBefore(0) + result.itemsAfter(0) + result.width(Constraint.Fill) + result.height(Constraint.Fill) + result.margin(Margin(all = 0.dp)) + result.crossAxisAlignment(CrossAxisAlignment.Stretch) + result.scrollItemIndex(ScrollItemIndex(id = 0, index = 0)) + return result + } + + abstract fun verifySnapshot( + container: Widget, + name: String? = null, + ) + + @Test fun testHappyPath() { + val lazyList = defaultLazyList() + + for ((index, value) in movies.take(5).withIndex()) { + lazyList.items.insert(index, coloredText(text = value)) + } + (lazyList as? ChangeListener)?.onEndChanges() + + verifySnapshot(lazyList) + } + + @Test fun testPlaceholderToLoadedAndLoadedToPlaceholder() { + val lazyList = defaultLazyList() + + (lazyList as? ChangeListener)?.onEndChanges() + verifySnapshot(lazyList, "0 empty") + + lazyList.itemsBefore(0) + lazyList.itemsAfter(10) + (lazyList as? ChangeListener)?.onEndChanges() + verifySnapshot(lazyList, "1 placeholders") + + lazyList.itemsBefore(0) + lazyList.itemsAfter(0) + for ((index, value) in movies.take(10).withIndex()) { + lazyList.items.insert(index, coloredText(text = value)) + } + (lazyList as? ChangeListener)?.onEndChanges() + verifySnapshot(lazyList, "2 loaded") + + lazyList.itemsBefore(0) + lazyList.itemsAfter(10) + lazyList.items.remove(0, 10) + (lazyList as? ChangeListener)?.onEndChanges() + verifySnapshot(lazyList, "3 placeholders") + + lazyList.itemsBefore(0) + lazyList.itemsAfter(0) + (lazyList as? ChangeListener)?.onEndChanges() + verifySnapshot(lazyList, "4 empty") + } + + @Test fun testPlaceholdersExhausted() { + val lazyList = defaultLazyList() + + lazyList.itemsBefore(11) + for ((index, value) in movies.take(1).withIndex()) { + lazyList.items.insert(index, coloredText(text = value)) + } + (lazyList as? ChangeListener)?.onEndChanges() + verifySnapshot(lazyList) + } +} + +private val movies = listOf( + "The Godfather", + "The Dark Knight", + "12 Angry Men", + "Schindler's List", + "Pulp Fiction", + "Forrest Gump", + "Fight Club", + "Inception", + "The Matrix", + "Goodfellas", + "Se7en", + "Seven Samurai", +) diff --git a/redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/utils.common.kt b/redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/utils.common.kt new file mode 100644 index 0000000000..9ec3b24171 --- /dev/null +++ b/redwood-lazylayout-shared-test/src/commonMain/kotlin/app/cash/redwood/lazylayout/utils.common.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2024 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. + */ +@file:Suppress("ktlint:standard:property-naming") + +package app.cash.redwood.lazylayout + +import app.cash.redwood.widget.Widget + +const val Green: Int = 0xff00ff00.toInt() + +fun argb( + alpha: Int, + red: Int, + green: Int, + blue: Int, +): Int { + return (alpha shl 24) or (red shl 16) or (green shl 8) or (blue) +} + +interface Text : Widget { + fun text(text: String) + fun bgColor(color: Int) +} diff --git a/redwood-lazylayout-shared-test/src/iosMain/kotlin/app/cash/redwood/lazylayout/utils.kt b/redwood-lazylayout-shared-test/src/iosMain/kotlin/app/cash/redwood/lazylayout/utils.kt new file mode 100644 index 0000000000..3fb298616a --- /dev/null +++ b/redwood-lazylayout-shared-test/src/iosMain/kotlin/app/cash/redwood/lazylayout/utils.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 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.lazylayout + +import platform.UIKit.UIColor + +fun Int.toUIColor(): UIColor { + return UIColor( + red = ((this shr 16) and 0xff) / 255.0, + green = ((this shr 8) and 0xff) / 255.0, + blue = (this and 0xff) / 255.0, + alpha = ((this shr 24) and 0xff) / 255.0, + ) +} diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/project.pbxproj b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..9de94bf2c2 --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/project.pbxproj @@ -0,0 +1,420 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 102F1C8C2C7D18C700890D9F /* UIViewLazyListTestHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = 102F1C8B2C7D18C700890D9F /* UIViewLazyListTestHost.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 */; }; + CB9729D32AD82D0C00804E94 /* SnapshotTestingCallback.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB9729D22AD82D0C00804E94 /* SnapshotTestingCallback.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 102F1C8B2C7D18C700890D9F /* UIViewLazyListTestHost.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewLazyListTestHost.swift; sourceTree = ""; }; + 63E90CF521FEBBB700449E04 /* RedwoodLazylayoutUIViewTestKt.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RedwoodLazylayoutUIViewTestKt.framework; path = "build/xcode-frameworks/RedwoodLazylayoutUIViewTestKt.framework"; sourceTree = ""; }; + CB408CE52AC64CEF00E1BA00 /* RedwoodLazylayoutUIViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RedwoodLazylayoutUIViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CB408CEC2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KotlinHostingXCTestCase.swift; sourceTree = ""; }; + CB408CF52AC657EF00E1BA00 /* RedwoodLazylayoutUIViewTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RedwoodLazylayoutUIViewTests-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 = ""; }; + CB9729D22AD82D0C00804E94 /* SnapshotTestingCallback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotTestingCallback.swift; 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 /* RedwoodLazylayoutUIViewTests */, + 635661D221F12B7E00DD7240 /* Products */, + 00D5E68C2AAF3EBD00692213 /* Frameworks */, + 63E90CF521FEBBB700449E04 /* RedwoodLazylayoutUIViewTestKt.framework */, + ); + sourceTree = ""; + }; + 635661D221F12B7E00DD7240 /* Products */ = { + isa = PBXGroup; + children = ( + CB408CE52AC64CEF00E1BA00 /* RedwoodLazylayoutUIViewTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CB408CE62AC64CEF00E1BA00 /* RedwoodLazylayoutUIViewTests */ = { + isa = PBXGroup; + children = ( + CB9729D22AD82D0C00804E94 /* SnapshotTestingCallback.swift */, + CB408CEC2AC6549F00E1BA00 /* KotlinHostingXCTestCase.swift */, + CB408CF62AC657EF00E1BA00 /* KotlinHostingXCTestCaseHelper.m */, + CB408CF52AC657EF00E1BA00 /* RedwoodLazylayoutUIViewTests-Bridging-Header.h */, + CB408CF82AC6581100E1BA00 /* KotlinHostingXCTestCaseHelper.h */, + 102F1C8B2C7D18C700890D9F /* UIViewLazyListTestHost.swift */, + ); + path = RedwoodLazylayoutUIViewTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + CB408CE42AC64CEF00E1BA00 /* RedwoodLazylayoutUIViewTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB408CE92AC64CEF00E1BA00 /* Build configuration list for PBXNativeTarget "RedwoodLazylayoutUIViewTests" */; + buildPhases = ( + 00DD12E22AAF46C500CA3FD3 /* ShellScript */, + CB408CE12AC64CEF00E1BA00 /* Sources */, + CB408CE22AC64CEF00E1BA00 /* Frameworks */, + CB408CE32AC64CEF00E1BA00 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RedwoodLazylayoutUIViewTests; + packageProductDependencies = ( + CB8A21EE2AC6647F00C104C2 /* SnapshotTesting */, + ); + productName = RedwoodLazylayoutUIViewTests; + productReference = CB408CE52AC64CEF00E1BA00 /* RedwoodLazylayoutUIViewTests.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 "RedwoodLazylayoutUIViewTests" */; + 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 /* RedwoodLazylayoutUIViewTests */, + ); + }; +/* 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-lazylayout-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 */, + CB9729D32AD82D0C00804E94 /* SnapshotTestingCallback.swift in Sources */, + 102F1C8C2C7D18C700890D9F /* UIViewLazyListTestHost.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_SIGNING_ALLOWED = NO; + 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_SIGNING_ALLOWED = NO; + 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)", + "$(PROJECT_DIR)/build/xcode-frameworks", + ); + 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", + "\"RedwoodLazylayoutUIViewTestKt\"", + "-ObjC", + "-framework", + RedwoodLazylayoutUIViewTestKt, + ); + PRODUCT_BUNDLE_IDENTIFIER = app.cash.redwood.layout.uiview.testing; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OBJC_BRIDGING_HEADER = "RedwoodLazylayoutUIViewTests/RedwoodLazylayoutUIViewTests-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)", + "$(PROJECT_DIR)/build/xcode-frameworks", + ); + 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", + "\"RedwoodLazylayoutUIViewTestKt\"", + "-ObjC", + "-framework", + RedwoodLazylayoutUIViewTestKt, + ); + PRODUCT_BUNDLE_IDENTIFIER = app.cash.redwood.layout.uiview.testing; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OBJC_BRIDGING_HEADER = "RedwoodLazylayoutUIViewTests/RedwoodLazylayoutUIViewTests-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 "RedwoodLazylayoutUIViewTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 635661E121F12B8000DD7240 /* Debug */, + 635661E221F12B8000DD7240 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CB408CE92AC64CEF00E1BA00 /* Build configuration list for PBXNativeTarget "RedwoodLazylayoutUIViewTests" */ = { + 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-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/xcshareddata/xcschemes/RedwoodLazylayoutUIViewTests.xcscheme b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/xcshareddata/xcschemes/RedwoodLazylayoutUIViewTests.xcscheme new file mode 100644 index 0000000000..71d5321ebb --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests.xcodeproj/xcshareddata/xcschemes/RedwoodLazylayoutUIViewTests.xcscheme @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCase.swift b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCase.swift new file mode 100644 index 0000000000..c0382c8a5c --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCase.swift @@ -0,0 +1,63 @@ +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-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.h b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.h new file mode 100644 index 0000000000..7e4622d582 --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.h @@ -0,0 +1,20 @@ +// Created by Michał Laskowski on 10/02/2020. +// Copyright © 2020 Michał Laskowski. All rights reserved. +// Derived from https://github.com/michallaskowski/kuiks/blob/c8500df2a55fe031a1bcf546c771c3d9f30dbf90/NativeTestBase/ObjC/TestBaseForSelector.h +// Licensed as Apache-2.0. + +#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-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.m b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.m new file mode 100644 index 0000000000..f7991ed221 --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/KotlinHostingXCTestCaseHelper.m @@ -0,0 +1,25 @@ +// Created by Michał Laskowski on 10/02/2020. +// Copyright © 2020 Michał Laskowski. All rights reserved. +// Derived from https://github.com/michallaskowski/kuiks/blob/c8500df2a55fe031a1bcf546c771c3d9f30dbf90/NativeTestBase/ObjC/TestBaseForSelector.m +// Licensed as Apache-2.0. + +#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-lazylayout-uiview/RedwoodLazylayoutUIViewTests/RedwoodLazylayoutUIViewTests-Bridging-Header.h b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/RedwoodLazylayoutUIViewTests-Bridging-Header.h new file mode 100644 index 0000000000..832bf76ca4 --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/RedwoodLazylayoutUIViewTests-Bridging-Header.h @@ -0,0 +1 @@ +#include "KotlinHostingXCTestCaseHelper.h" diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/SnapshotTestingCallback.swift b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/SnapshotTestingCallback.swift new file mode 100644 index 0000000000..802de464f5 --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/SnapshotTestingCallback.swift @@ -0,0 +1,19 @@ +import RedwoodLazylayoutUIViewTestKt +import SnapshotTesting +import UIKit + +final class SnapshotTestingCallback : UIViewSnapshotCallback { + private let testName: String + private let fileName: StaticString + + init(named testName: String, _ fileName: StaticString = #file) { + self.testName = testName + self.fileName = fileName + } + + func verifySnapshot(view: UIView, name: String?, delay: TimeInterval = 0.0) { + // Set `record` to true to generate new snapshots. Be sure to revert that before committing! + // Note that tests always fail when `record` is true. + assertSnapshot(of: view, as: .wait(for: delay, on: .image), named: name, record: false, file: fileName, testName: testName) + } +} diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/UIViewLazyListTestHost.swift b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/UIViewLazyListTestHost.swift new file mode 100644 index 0000000000..c2c00536a6 --- /dev/null +++ b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/UIViewLazyListTestHost.swift @@ -0,0 +1,8 @@ +import RedwoodLazylayoutUIViewTestKt +import UIKit + +final class UIViewLazyListTestHost: KotlinHostingXCTestCase { + override class func initTest(name: String) -> UIViewLazyListTest { + return UIViewLazyListTest(callback: SnapshotTestingCallback(named: name)) + } +} diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testHappyPath.1.png b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testHappyPath.1.png new file mode 100644 index 0000000000000000000000000000000000000000..3c110a255cb425b48ba7c6ff1c9009377ade216b GIT binary patch literal 82884 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 N)-br3cmDc={{sdf!V>@h literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.0-empty.png b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.0-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..c266f4428b40f789827fbac76d88520f96a244cb GIT binary patch literal 34674 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 BNss^l literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.1-placeholders.png b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.1-placeholders.png new file mode 100644 index 0000000000000000000000000000000000000000..a536f1382c5056e38c2c3e136ed1a0bd01188998 GIT binary patch literal 61236 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 J=)$$%{s%`5<3a!c literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.3-placeholders.png b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholderToLoadedAndLoadedToPlaceholder.3-placeholders.png new file mode 100644 index 0000000000000000000000000000000000000000..a536f1382c5056e38c2c3e136ed1a0bd01188998 GIT binary patch literal 61236 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 BNss^l literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholdersExhausted.1.png b/redwood-lazylayout-uiview/RedwoodLazylayoutUIViewTests/__Snapshots__/UIViewLazyListTestHost/testPlaceholdersExhausted.1.png new file mode 100644 index 0000000000000000000000000000000000000000..46b689bb563bfea15619fb90201e665fc824869b GIT binary patch literal 66523 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 d@3Qe&NT%`CLg<3lqY(a&<+j~h3pXD;^*^IA{ + if (target.platformType != common) { + target.binaries.framework { + compilation = target.compilations.test + baseName = 'RedwoodLazylayoutUIViewTestKt' + } + } + } + sourceSets { commonMain { dependencies { @@ -13,5 +23,11 @@ kotlin { implementation projects.redwoodWidgetCompose } } + commonTest { + dependencies { + api projects.redwoodLazylayoutSharedTest + api libs.kotlin.test + } + } } } diff --git a/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewLazyListTest.kt b/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewLazyListTest.kt new file mode 100644 index 0000000000..1b4661c8bc --- /dev/null +++ b/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewLazyListTest.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 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.lazylayout.uiview + +import app.cash.redwood.lazylayout.AbstractLazyListTest +import app.cash.redwood.widget.Widget +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.DurationUnit +import platform.CoreGraphics.CGRectMake +import platform.UIKit.UIColor +import platform.UIKit.UIView + +class UIViewLazyListTest( + private val callback: UIViewSnapshotCallback, +) : AbstractLazyListTest() { + private val widgetFactory = UIViewRedwoodLazyLayoutWidgetFactory() + + override fun text() = UIViewText() + + override fun lazyList(backgroundColor: Int) = widgetFactory.LazyList() + + override fun verifySnapshot(container: Widget, name: String?) { + val screenSize = CGRectMake(0.0, 0.0, 390.0, 844.0) // iPhone 14. + container.value.setFrame(screenSize) + + // Snapshot the container on a white background. + val frame = UIView().apply { + backgroundColor = UIColor.whiteColor + setFrame(screenSize) + addSubview(container.value) + layoutIfNeeded() + } + + // Unfortunately even with animations forced off, UITableView's animation system breaks + // synchronous snapshots. The simplest workaround is to delay snapshots one frame. + callback.verifySnapshot(frame, name, delay = 1.milliseconds.toDouble(DurationUnit.SECONDS)) + container.value.removeFromSuperview() + } +} diff --git a/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewSnapshotCallback.kt b/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewSnapshotCallback.kt new file mode 100644 index 0000000000..e2e544c027 --- /dev/null +++ b/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/UIViewSnapshotCallback.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 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.lazylayout.uiview + +import platform.UIKit.UIView + +interface UIViewSnapshotCallback { + fun verifySnapshot(view: UIView, name: String?, delay: Double = 0.0) +} diff --git a/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/testWidgets.kt b/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/testWidgets.kt new file mode 100644 index 0000000000..4c7c2b2d30 --- /dev/null +++ b/redwood-lazylayout-uiview/src/commonTest/kotlin/app/cash/redwood/lazylayout/uiview/testWidgets.kt @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024 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.lazylayout.uiview + +import app.cash.redwood.Modifier +import app.cash.redwood.lazylayout.Text +import app.cash.redwood.lazylayout.toUIColor +import platform.UIKit.UILabel +import platform.UIKit.UIView + +class UIViewText : Text { + override val value = UILabel().apply { + numberOfLines = 0 + textColor = platform.UIKit.UIColor.blackColor + } + override var modifier: Modifier = Modifier + + override fun text(text: String) { + value.text = text + } + + override fun bgColor(color: Int) { + value.backgroundColor = color.toUIColor() + } +} diff --git a/redwood-lazylayout-view/build.gradle b/redwood-lazylayout-view/build.gradle index 3a566918f6..a8c1145896 100644 --- a/redwood-lazylayout-view/build.gradle +++ b/redwood-lazylayout-view/build.gradle @@ -15,6 +15,7 @@ dependencies { implementation libs.androidx.swipeRefreshLayout implementation libs.kotlinx.coroutines.android testImplementation projects.redwoodLayoutSharedTest + testImplementation projects.redwoodLazylayoutSharedTest testImplementation projects.redwoodLayoutView testImplementation libs.testParameterInjector } diff --git a/redwood-lazylayout-view/src/test/kotlin/app/cash/redwood/lazylayout/view/ViewLazyListTest.kt b/redwood-lazylayout-view/src/test/kotlin/app/cash/redwood/lazylayout/view/ViewLazyListTest.kt new file mode 100644 index 0000000000..d80e2e0a3e --- /dev/null +++ b/redwood-lazylayout-view/src/test/kotlin/app/cash/redwood/lazylayout/view/ViewLazyListTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 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.lazylayout.view + +import android.graphics.Color +import android.view.View +import android.widget.TextView +import app.cash.paparazzi.DeviceConfig +import app.cash.paparazzi.Paparazzi +import app.cash.redwood.Modifier +import app.cash.redwood.lazylayout.AbstractLazyListTest +import app.cash.redwood.lazylayout.Text +import app.cash.redwood.lazylayout.widget.LazyList +import app.cash.redwood.widget.Widget +import com.google.testing.junit.testparameterinjector.TestParameterInjector +import org.junit.Rule +import org.junit.runner.RunWith + +@RunWith(TestParameterInjector::class) +class ViewLazyListTest : AbstractLazyListTest() { + + @get:Rule + val paparazzi = Paparazzi( + deviceConfig = DeviceConfig.PIXEL_6, + theme = "android:Theme.Material.Light.NoActionBar", + supportsRtl = true, + ) + + override fun text(): Text { + return object : Text { + override val value = TextView(paparazzi.context).apply { + textSize = 18f + setTextColor(Color.BLACK) + } + + override var modifier: Modifier = Modifier + + override fun text(text: String) { + value.text = text + } + + override fun bgColor(color: Int) { + value.setBackgroundColor(color) + } + } + } + + override fun lazyList(backgroundColor: Int): LazyList { + return ViewLazyList(paparazzi.context).apply { + value.setBackgroundColor(backgroundColor) + } + } + + override fun verifySnapshot(container: Widget, name: String?) { + paparazzi.snapshot(container.value, name) + } +} diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testHappyPath.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testHappyPath.png new file mode 100644 index 0000000000000000000000000000000000000000..5d0cf11f524b61bf26b7e2300f0582abf8c04178 GIT binary patch literal 13360 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 literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_0_empty.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_0_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..0975752c4d937e6cfe75e761acfa93201344cab3 GIT binary patch literal 3837 zcmeAS@N?(olHy`uVBq!ia0y~yU_8XY!2E)P4JhKf;hzly1K$x(7srr_xVKjg85tCK z4s7@tZssrZA$g(Yrz;NW-(wh7%(7>2=oDm{kk-PmL{gC<(~ZMn)+l#0G)5D{XkHjC z3Pwx9(UNeqBpfXXM@z!dl5n&n94!e)OTqyt32nXZbP0l+XkK Di{b&W literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_1_placeholders.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_1_placeholders.png new file mode 100644 index 0000000000000000000000000000000000000000..fa85eca6596a27862f7df05ff7ca63939ce79f84 GIT binary patch literal 4559 zcmeAS@N?(olHy`uVBq!ia0y~yU_8XY!2E)P4JhKf;hzlygWxnz7srr_xVKjgx!A5s zx+Nav-N9l0U>=j$I|l<_g{jkSMMQV4jA>TT+_L5BA-4^|AqM8bC;0P?-xkR6oj0f{ zXM8W6|3}p`Xosc8q>wDWNh(ukHLG|oeWu_Uw2~sBSHJ$0)zts__o?8!n&+j-yY1xV z^X2F7vAMI?bJCY5>&`zvZhc%_pT9hRl8Wul{q=Qom;W~RoHXy2jEbk0DZA$+ud|Mm zmIM_~P+56}c0$*mpMHGz@#^XAyFqr}`TFxk#p@qmo<4l%J86k}dF?-oI*Wfbl{=~@ ztGql(5BI>mTUxu%@}B*^TBzNz^ZEPC`|J0@L$CjM`f-0)=us3;q{jKW^XHG(_r=G_ zy}PI4SygoX`QiWnW&YQ}9r|DHz3hFMLn%*2Bsg!E-G15o^85G01L^qj+sD;mf%N+G z&yVLm9zA{d?rarL|99`_$3K7h4;anM&FGcbz>)j)=ckJAKVHF;n4Q%dDkso5`=l6Z@&xhH4{dx1_vybBuq4)UX&5xI%p_fO+a)NLKzyAFB m(Moc(aWL8_8gXsKzx;{+rPL~Od!2v-H4L7velF{r5}E+f=-7S$ literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_2_loaded.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_2_loaded.png new file mode 100644 index 0000000000000000000000000000000000000000..b9d730e80ee3ab00e0de3194dbb1a3201ff439e3 GIT binary patch literal 20909 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 literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_3_placeholders.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_3_placeholders.png new file mode 100644 index 0000000000000000000000000000000000000000..fa85eca6596a27862f7df05ff7ca63939ce79f84 GIT binary patch literal 4559 zcmeAS@N?(olHy`uVBq!ia0y~yU_8XY!2E)P4JhKf;hzlygWxnz7srr_xVKjgx!A5s zx+Nav-N9l0U>=j$I|l<_g{jkSMMQV4jA>TT+_L5BA-4^|AqM8bC;0P?-xkR6oj0f{ zXM8W6|3}p`Xosc8q>wDWNh(ukHLG|oeWu_Uw2~sBSHJ$0)zts__o?8!n&+j-yY1xV z^X2F7vAMI?bJCY5>&`zvZhc%_pT9hRl8Wul{q=Qom;W~RoHXy2jEbk0DZA$+ud|Mm zmIM_~P+56}c0$*mpMHGz@#^XAyFqr}`TFxk#p@qmo<4l%J86k}dF?-oI*Wfbl{=~@ ztGql(5BI>mTUxu%@}B*^TBzNz^ZEPC`|J0@L$CjM`f-0)=us3;q{jKW^XHG(_r=G_ zy}PI4SygoX`QiWnW&YQ}9r|DHz3hFMLn%*2Bsg!E-G15o^85G01L^qj+sD;mf%N+G z&yVLm9zA{d?rarL|99`_$3K7h4;anM&FGcbz>)j)=ckJAKVHF;n4Q%dDkso5`=l6Z@&xhH4{dx1_vybBuq4)UX&5xI%p_fO+a)NLKzyAFB m(Moc(aWL8_8gXsKzx;{+rPL~Od!2v-H4L7velF{r5}E+f=-7S$ literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_4_empty.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholderToLoadedAndLoadedToPlaceholder_4_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..0975752c4d937e6cfe75e761acfa93201344cab3 GIT binary patch literal 3837 zcmeAS@N?(olHy`uVBq!ia0y~yU_8XY!2E)P4JhKf;hzly1K$x(7srr_xVKjg85tCK z4s7@tZssrZA$g(Yrz;NW-(wh7%(7>2=oDm{kk-PmL{gC<(~ZMn)+l#0G)5D{XkHjC z3Pwx9(UNeqBpfXXM@z!dl5n&n94!e)OTqyt32nXZbP0l+XkK Di{b&W literal 0 HcmV?d00001 diff --git a/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholdersExhausted.png b/redwood-lazylayout-view/src/test/snapshots/images/app.cash.redwood.lazylayout.view_ViewLazyListTest_testPlaceholdersExhausted.png new file mode 100644 index 0000000000000000000000000000000000000000..8a26e2b27750d1c20ac88138cbe2426680b14499 GIT binary patch literal 6772 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 ZFQqrU&)Zw=`kUlN*crW}ar=R<{sT(Kx2ymF literal 0 HcmV?d00001 diff --git a/settings.gradle b/settings.gradle index c988009db4..e033b5a36f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -63,6 +63,7 @@ include ':redwood-lazylayout-compose' include ':redwood-lazylayout-composeui' include ':redwood-lazylayout-dom' include ':redwood-lazylayout-schema' +include ':redwood-lazylayout-shared-test' include ':redwood-lazylayout-testing' include ':redwood-lazylayout-uiview' include ':redwood-lazylayout-view'