From 3ca12e54fec9e5a6807f50d1f0bef81864d09eec Mon Sep 17 00:00:00 2001 From: Marshall Weir Date: Mon, 19 Apr 2021 11:26:05 -0400 Subject: [PATCH 1/2] Fix unbound fragments tests --- .../androidTest/java/dev/enro/core/UnboundFragmentsTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/enro/src/androidTest/java/dev/enro/core/UnboundFragmentsTest.kt b/enro/src/androidTest/java/dev/enro/core/UnboundFragmentsTest.kt index a79f6101..757860e1 100644 --- a/enro/src/androidTest/java/dev/enro/core/UnboundFragmentsTest.kt +++ b/enro/src/androidTest/java/dev/enro/core/UnboundFragmentsTest.kt @@ -7,8 +7,7 @@ import dev.enro.* import org.junit.Ignore import org.junit.Test -@Ignore("Something isn't working with the unbound fragment test environment, tests are failing but are known to pass") -class UnboundFragmentsTest { +class UnboundFragmentsTest { @Test fun whenUnboundFragmentIsOpened_thenNavigationKeyIsUnbound() { @@ -31,7 +30,8 @@ class UnboundFragmentsTest { caught = t } assertTrue(caught is IllegalStateException) - assertEquals("This NavigationHandle has no NavigationKey", caught.message) + assertNotNull(caught.message) + assertTrue(caught.message!!.matches(Regex("The navigation handle for the context UnboundFragment.*has no NavigationKey"))) } @Test From dbe03b134b7e86bd4c43ef0fe292f312dad7df9a Mon Sep 17 00:00:00 2001 From: Marshall Weir Date: Mon, 19 Apr 2021 12:51:24 -0400 Subject: [PATCH 2/2] Fix crash on close when previous fragment has been destroyed --- .../core/fragment/DefaultFragmentExecutor.kt | 10 ++- .../dev/enro/core/FragmentToFragmentTests.kt | 81 +++++++++++++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 enro/src/androidTest/java/dev/enro/core/FragmentToFragmentTests.kt diff --git a/enro-core/src/main/java/dev/enro/core/fragment/DefaultFragmentExecutor.kt b/enro-core/src/main/java/dev/enro/core/fragment/DefaultFragmentExecutor.kt index aeb524b9..6036c676 100644 --- a/enro-core/src/main/java/dev/enro/core/fragment/DefaultFragmentExecutor.kt +++ b/enro-core/src/main/java/dev/enro/core/fragment/DefaultFragmentExecutor.kt @@ -105,22 +105,24 @@ object DefaultFragmentExecutor : NavigationExecutor attach(previousFragment) !previousFragment.isAdded -> add(context.contextReference.getContainerId(), previousFragment) } } - if(sameFragmentManagers) setPrimaryNavigationFragment(previousFragment) + if(!differentFragmentManagers) setPrimaryNavigationFragment(previousFragment) } - if(previousFragment != null && !sameFragmentManagers) { + if(previousFragment != null && differentFragmentManagers) { previousFragment.parentFragmentManager.commit { setPrimaryNavigationFragment(previousFragment) } diff --git a/enro/src/androidTest/java/dev/enro/core/FragmentToFragmentTests.kt b/enro/src/androidTest/java/dev/enro/core/FragmentToFragmentTests.kt new file mode 100644 index 00000000..3db95ad0 --- /dev/null +++ b/enro/src/androidTest/java/dev/enro/core/FragmentToFragmentTests.kt @@ -0,0 +1,81 @@ +package dev.enro.core + +import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.commit +import androidx.fragment.app.commitNow +import androidx.test.core.app.ActivityScenario +import dev.enro.* +import dev.enro.expectFragment +import junit.framework.TestCase +import org.junit.Test +import java.util.* + +private fun expectSingleFragmentActivity(): FragmentActivity { + return expectActivity { it::class.java.simpleName == "SingleFragmentActivity"} +} + +class FragmentToFragmentTests { + + @Test + fun whenFragmentOpensFragment_andFragmentIsInAHost_thenFragmentIsLaunchedIntoHost() { + val scenario = ActivityScenario.launch(ActivityWithFragments::class.java) + val handle = scenario.getNavigationHandle() + + val id = UUID.randomUUID().toString() + handle.forward(ActivityChildFragmentKey(id)) + + val parentFragment = expectFragment() + val id2 = UUID.randomUUID().toString() + parentFragment.getNavigationHandle().forward(ActivityChildFragmentTwoKey(id2)) + + val childFragment = expectFragment() + val fragmentHandle = childFragment.getNavigationHandle().asTyped() + TestCase.assertEquals(id2, fragmentHandle.key.id) + } + + @Test + fun whenFragmentOpensFragment_andFragmentIsNotInAHost_thenFragmentIsLaunchedAsSingleFragmentActivity() { + val scenario = ActivityScenario.launch(DefaultActivity::class.java) + val handle = scenario.getNavigationHandle() + + val id = UUID.randomUUID().toString() + handle.forward(ActivityChildFragmentKey(id)) + + val activity = expectSingleFragmentActivity() + val parentFragment = activity.supportFragmentManager.primaryNavigationFragment!! + val id2 = UUID.randomUUID().toString() + parentFragment.getNavigationHandle().forward(ActivityChildFragmentTwoKey(id2)) + + val activity2 = expectSingleFragmentActivity() + val childFragment = activity2.supportFragmentManager.primaryNavigationFragment!! + val fragmentHandle = childFragment.getNavigationHandle().asTyped() + TestCase.assertEquals(id2, fragmentHandle.key.id) + } + + @Test + fun whenFragmentOpensFragment_andFragmentIsInAHost_andIsDestroyed_thenClosingChildFragmentCreatesNewParentFragment() { + val scenario = ActivityScenario.launch(ActivityWithFragments::class.java) + val handle = scenario.getNavigationHandle() + + val id = "UUID.randomUUID().toString()" + handle.forward(ActivityChildFragmentKey(id)) + + val parentFragment = expectFragment() + val id2 = UUID.randomUUID().toString() + parentFragment.getNavigationHandle().forward(ActivityChildFragmentTwoKey(id2)) + + val parentFragmentManager = parentFragment.parentFragmentManager + + val childFragment = expectFragment() + val fragmentHandle = childFragment.getNavigationHandle().asTyped() + TestCase.assertEquals(id2, fragmentHandle.key.id) + + // This will destroy the parent fragment, making it unavailable to re-use on close + parentFragmentManager.commit { remove(parentFragment) } + + childFragment.getNavigationHandle().close() + val newParentFragment = expectFragment() + TestCase.assertEquals(id, newParentFragment.getNavigationHandle().asTyped().key.id) + TestCase.assertNotSame(parentFragment, newParentFragment) + } +} \ No newline at end of file