diff --git a/tests/app/ui/page/modal-tab-page.ts b/tests/app/ui/page/modal-tab-page.ts new file mode 100644 index 000000000..9585789bf --- /dev/null +++ b/tests/app/ui/page/modal-tab-page.ts @@ -0,0 +1,13 @@ +import { NavigatedData } from "tns-core-modules/ui/page"; +import { View } from "tns-core-modules/ui/core/view"; +import * as TKUnit from "../../TKUnit"; +import { stack } from "tns-core-modules/ui/frame"; +import { isAndroid } from "tns-core-modules/platform"; + +export function onNavigatedTo(args: NavigatedData) { + TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!"); + // shownModally raised after page.NavigatedTo on iOS so we close modal there + if (isAndroid) { + (args.object as View).closeModal(); + } +} diff --git a/tests/app/ui/page/modal-tab-page.xml b/tests/app/ui/page/modal-tab-page.xml new file mode 100644 index 000000000..31586bea6 --- /dev/null +++ b/tests/app/ui/page/modal-tab-page.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/tests/app/ui/page/modal-tab-root.ts b/tests/app/ui/page/modal-tab-root.ts new file mode 100644 index 000000000..20b26a0ef --- /dev/null +++ b/tests/app/ui/page/modal-tab-root.ts @@ -0,0 +1,22 @@ +import { ShownModallyData } from "tns-core-modules/ui/core/view"; +import { TabView } from "tns-core-modules/ui/tab-view/tab-view"; +import * as TKUnit from "../../TKUnit"; +import { stack } from "tns-core-modules/ui/frame"; +import { isIOS } from "tns-core-modules/platform" + +export function onShownModally(args: ShownModallyData) { + const tabView = args.object; + TKUnit.assertNotNull(tabView); + if (args.context) { + args.context.shownModally = true; + } + + const hostFrame = stack()[0]; + TKUnit.assertNotNull(hostFrame, "Host frame should not be null"); + TKUnit.assertEqual(hostFrame.currentPage.modal, tabView, "hostFrame.currentPage.modal should be equal to the tabView instance on tabView.shownModally event handler."); + + // shownModally raised after page.NavigatedTo on iOS + if (isIOS) { + args.closeCallback("return value"); + } +} \ No newline at end of file diff --git a/tests/app/ui/page/modal-tab-root.xml b/tests/app/ui/page/modal-tab-root.xml new file mode 100644 index 000000000..9760affe7 --- /dev/null +++ b/tests/app/ui/page/modal-tab-root.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tests/app/ui/page/page-tests-common.ts b/tests/app/ui/page/page-tests-common.ts index 3e344fe6b..6efd3e5f8 100644 --- a/tests/app/ui/page/page-tests-common.ts +++ b/tests/app/ui/page/page-tests-common.ts @@ -23,6 +23,7 @@ import { Frame, stack } from "tns-core-modules/ui/frame"; import { Label } from "tns-core-modules/ui/label"; import { Color } from "tns-core-modules/color"; import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view/tab-view"; +import { _resetRootView, getRootView } from "tns-core-modules/application"; export function addLabelToPage(page: Page, text?: string) { const label = new Label(); @@ -874,6 +875,71 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalPage() { TKUnit.assertTrue(shownModallyCount === 1); } +export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView() { + let showingModallyCount = 0; + let shownModallyCount = 0; + + let ready = false; + + const modalCloseCallback = function (returnValue: any) { + TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!"); + + ready = true; + } + + const modalTabViewShowingModallyEventHandler = function(args: ShownModallyData) { + showingModallyCount++; + } + + const modalTabViewShownModallyEventHandler = function(args: ShownModallyData) { + shownModallyCount++; + } + + const hostNavigatedToEventHandler = function(args) { + const page = args.object; + page.off(Page.navigatedToEvent, hostNavigatedToEventHandler); + + const basePath = "ui/page/"; + const entry: NavigationEntry = { + moduleName: basePath + "modal-tab-root" + }; + + TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!"); + + const modalTabView = createViewFromEntry(entry) as TabView; + modalTabView.on(TabView.showingModallyEvent, modalTabViewShowingModallyEventHandler); + modalTabView.on(TabView.shownModallyEvent, modalTabViewShownModallyEventHandler); + + TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!"); + + page.showModal(modalTabView, { }, modalCloseCallback, false, false); + } + + const masterPageFactory = function (): Page { + const masterPage = new Page(); + masterPage.id = "masterPage_test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView"; + masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler); + + const label = new Label(); + label.text = "Text"; + masterPage.content = label; + return masterPage; + }; + + TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!"); + + helper.navigate(masterPageFactory); + + TKUnit.assertEqual(stack().length, 2, "Host and modal tab frame should be instantiated at this point!"); + + TKUnit.waitUntilReady(() => ready); + + TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!"); + + TKUnit.assertTrue(showingModallyCount === 1); + TKUnit.assertTrue(shownModallyCount === 1); +} + export function test_percent_width_and_height_support() { const testPage = new Page(); testPage.id = "test_percent_width_and_height_support"; @@ -935,40 +1001,3 @@ export function test_percent_margin_support() { TKUnit.assertEqual(bounds.right, parentWidth, "Stack RIGHT position incorrect"); TKUnit.assertEqual(bounds.bottom, parentHeight, "Stack BOTTOM position incorrect"); } - -//export function test_ModalPage_Layout_is_Correct() { -// const testPage: Page; -// const label: Label; -// const pageFactory = function () { -// testPage = new Page(); -// label = new Label(); -// label.text = "Will Show modal page"; -// testPage.content = label; -// return testPage; -// }; - -// helper.navigate(pageFactory); -// const basePath = "ui/page/"; -// testPage.showModal(basePath + "page21", testPage, () => { }, false); - -// // TODO: Remove this once navigate and showModal returns Promise. -// TKUnit.wait(0.350); -// const childPage = (testPage).childPage; -// const closeCallback: Function = (testPage).close; - -// try { -// const layout = childPage.content; -// const repeater = layout.getChildAt(1); -// TKUnit.assertTrue(repeater.isLayoutValid, "layout should be valid."); -// const bounds = repeater._getCurrentLayoutBounds(); -// const height = bounds.bottom - bounds.top; -// TKUnit.assertTrue(height > 0, "Layout should be >0."); - -// closeCallback(); -// TKUnit.wait(0.150); -// } -// finally { -// helper.goBack -// helper.goBack(); -// } -//} \ No newline at end of file diff --git a/tns-core-modules/ui/core/view-base/view-base.ts b/tns-core-modules/ui/core/view-base/view-base.ts index 7056f8051..75233bcfa 100644 --- a/tns-core-modules/ui/core/view-base/view-base.ts +++ b/tns-core-modules/ui/core/view-base/view-base.ts @@ -959,7 +959,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition } public _dialogClosed(): void { - return; + eachDescendant(this, (child: ViewBase) => { + child._dialogClosed(); + return true; + }); } public _onRootViewReset(): void { diff --git a/tns-core-modules/ui/frame/frame-common.ts b/tns-core-modules/ui/frame/frame-common.ts index aee925fa7..3b8552664 100644 --- a/tns-core-modules/ui/frame/frame-common.ts +++ b/tns-core-modules/ui/frame/frame-common.ts @@ -435,7 +435,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition { } public _dialogClosed(): void { - this._popFromFrameStack(); + // No super call as we do not support nested frames to clean up + this._removeFromFrameStack(); } public _onRootViewReset(): void {