diff --git a/tests/app/testRunner.ts b/tests/app/testRunner.ts index daa336c48..337c33db9 100644 --- a/tests/app/testRunner.ts +++ b/tests/app/testRunner.ts @@ -136,10 +136,12 @@ import * as flexBoxLayoutTests from "./ui/layouts/flexbox-layout-tests"; allTests["FLEXBOXLAYOUT"] = flexBoxLayoutTests; import * as safeAreaLayoutTests from "./ui/layouts/safe-area-tests"; +import * as safeAreaListViewtTests from "./ui/list-view/list-view-safe-area-tests"; import * as scrollViewSafeAreaTests from "./ui/scroll-view/scroll-view-safe-area-tests"; if (platform.isIOS && ios.MajorVersion > 10) { allTests["SAFEAREALAYOUT"] = safeAreaLayoutTests; + allTests["SAFEAREA-LISTVIEW"] = safeAreaListViewtTests; allTests["SAFEAREA-SCROLL-VIEW"] = scrollViewSafeAreaTests; } diff --git a/tests/app/ui/list-view/list-view-safe-area-tests.ts b/tests/app/ui/list-view/list-view-safe-area-tests.ts new file mode 100644 index 000000000..2c01f52bf --- /dev/null +++ b/tests/app/ui/list-view/list-view-safe-area-tests.ts @@ -0,0 +1,287 @@ +import * as TKUnit from "../../TKUnit"; +import * as helper from "../helper"; +import * as platform from "tns-core-modules/platform"; +import * as view from "tns-core-modules/ui/core/view"; +import { UITest } from "../../ui-test"; +import { ios as iosUtils } from "tns-core-modules/utils/utils"; +import { parse } from "tns-core-modules/ui/builder"; +import { ViewModel } from "./list-view-view-model"; +import { getResources as appGetResources } from "tns-core-modules/application"; +import { Observable, EventData } from "tns-core-modules/data/observable"; +import { isFunction, isUndefined } from "tns-core-modules/utils/types"; +import { isAndroid, isIOS } from "tns-core-modules/platform"; +import { GC } from "tns-core-modules/utils/utils"; +import { Page } from "tns-core-modules/ui/page"; +import { View, KeyedTemplate } from "tns-core-modules/ui/core/view"; +import { MyButton, MyStackLayout } from "../layouts/layout-helper"; +import { + dipToDp, left, top, right, bottom, height, width, + equal, check, + isLeftAlignedWith, isRightAlignedWith, isTopAlignedWith, isBottomAlignedWith, + isLeftWith, isRightWith, isBelowWith +} from "../layouts/layout-tests-helper"; + +// >> article-require-listview-module +import { ListView, ItemEventData } from "tns-core-modules/ui/list-view"; +import { Label } from "tns-core-modules/ui/label"; + +export class ListViewSafeAreaTest extends UITest { + + private executeSnippet(ui: U, setup: (ui: U) => void, test: (ui: U) => void, pageOptions?: helper.PageOptions): void { + function waitUntilTestElementLayoutIsValid(view: view.View, timeoutSec?: number): void { + TKUnit.waitUntilReady(() => { + return view.isLayoutValid; + }, timeoutSec || 1); + } + + setup(ui); + helper.buildUIAndRunTest(ui.root, () => { + waitUntilTestElementLayoutIsValid(ui.root); + test(ui); + }, pageOptions); + }; + + private noop() { + // no operation + }; + + private getViews(template: string) { + let root = parse(template); + return { + root, + list: root.getViewById("list") as ListView, + cells: [ + [root.getViewById("cell00") as ListView, root.getViewById("cell01") as ListView, root.getViewById("cell02") as ListView], + [root.getViewById("cell10") as ListView, root.getViewById("cell11") as ListView, root.getViewById("cell12") as ListView], + [root.getViewById("cell20") as ListView, root.getViewById("cell21") as ListView, root.getViewById("cell22") as ListView] + ] + }; + }; + + private list_view_in_full_screen(listView: ListView, pageOptions?: helper.PageOptions) { + let expectedTop = 0; + if (pageOptions && pageOptions.actionBarFlat) { + const actionBarHeight = round(dipToDp(listView.page.actionBar.nativeViewProtected.frame.size.height)); + const app = iosUtils.getter(UIApplication, UIApplication.sharedApplication); + const statusBarHeight = round(dipToDp(app.statusBarFrame.size.height)); + expectedTop = actionBarHeight + statusBarHeight; + } + + const l = left(listView); + const t = top(listView); + const r = right(listView); + const b = bottom(listView); + equal(l, 0, `${listView}.left - actual:${l}; expected: ${0}`); + equal(t, expectedTop, `${listView}.top - actual:${t}; expected: ${expectedTop}`); + equal(r, platform.screen.mainScreen.widthPixels, `${listView}.right - actual:${r}; expected: ${platform.screen.mainScreen.widthPixels}`); + equal(b, platform.screen.mainScreen.heightPixels, `${listView}.bottom - actual:${b}; expected: ${platform.screen.mainScreen.heightPixels}`); + } + + private list_view_in_full_screen_test(pageOptions?: helper.PageOptions) { + const snippet = ` + + `; + this.executeSnippet( + this.getViews(snippet), + this.noop, + ({ list }) => { + this.list_view_in_full_screen(list, pageOptions); + }, + pageOptions + ); + } + + // public test_list_view_in_full_screen_action_bar() { + // this.list_view_in_full_screen_test({ actionBar: true }); + // } + + // public test_scroll_view_in_full_screen_action_bar_hidden() { + // this.list_view_in_full_screen_test({ actionBarHidden: true }); + // } + + // public test_scroll_view_in_full_screen_action_bar_flat() { + // this.list_view_in_full_screen_test({ actionBarFlat: true }); + // } + + // public test_scroll_view_in_full_screen_tab_bar() { + // this.list_view_in_full_screen_test({ tabBar: true }); + // } + + private list_view_children_components_in_safe_area(pageOptions?: helper.PageOptions) { + const snippet = ` + + + + + + `; + + this.executeSnippet( + this.getViews(snippet), + ({ list }) => { + list.on("loaded", setBindingContext(list)); + }, + ({ list }) => { + // const insets = root.getSafeAreaInsets(); + + // isLeftAlignedWith(root, stack); + // isTopAlignedWith(root, stack); + // isRightAlignedWith(root, stack); + + // isLeftWith(root, childFirst, insets.left); + // isBelowWith(root, childFirst, insets.top); + // isRightWith(childFirst, root, insets.right); + + // const scrollViewContentHeight = round(dipToDp(root.nativeViewProtected.contentSize.height)); + // const sumOfNestedLabelHeightsAndInsets = height(childFirst) * stack.getChildrenCount() + insets.top + insets.bottom; + // equal(scrollViewContentHeight, sumOfNestedLabelHeightsAndInsets, `scroll view content height<${scrollViewContentHeight}> sum of nested label height and insets <${sumOfNestedLabelHeightsAndInsets}>`); + }, + pageOptions + ); + } + + public test_list_view_children_components_in_safe_area() { + this.list_view_children_components_in_safe_area({ actionBar: true }); + } + + public test_list_view_children_components_beyond_safe_area_action_bar_hidden() { + this.list_view_children_components_in_safe_area({ actionBarHidden: true }); + } + + public test_list_view_children_components_beyond_safe_area_action_bar_flat() { + this.list_view_children_components_in_safe_area({ actionBarFlat: true }); + } + + public test_list_view_children_components_beyond_safe_area_tab_bar() { + this.list_view_children_components_in_safe_area({ tabBar: true }); + } + + + private grid_nested_list_views_layout_beyond_safe_area(pageOptions?: helper.PageOptions) { + const snippet = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + + this.executeSnippet( + this.getViews(snippet), + ({ cells }) => { + cells[0][0].on("loaded", setBindingContext(cells[0][0])); + cells[0][1].on("loaded", setBindingContext(cells[0][1])); + cells[0][2].on("loaded", setBindingContext(cells[0][2])); + + cells[1][0].on("loaded", setBindingContext(cells[1][0])); + cells[1][1].on("loaded", setBindingContext(cells[1][1])); + cells[1][2].on("loaded", setBindingContext(cells[1][2])); + + cells[2][0].on("loaded", setBindingContext(cells[2][0])); + cells[2][1].on("loaded", setBindingContext(cells[2][1])); + cells[2][2].on("loaded", setBindingContext(cells[2][2])); + }, + ({ root, cells }) => { + isLeftAlignedWith(root, cells[0][0]); + isLeftAlignedWith(root, cells[1][0]); + isLeftAlignedWith(root, cells[2][0]); + + isTopAlignedWith(root, cells[0][0]); + isTopAlignedWith(root, cells[0][1]); + isTopAlignedWith(root, cells[0][2]); + + isRightAlignedWith(root, cells[0][2]); + isRightAlignedWith(root, cells[1][2]); + isRightAlignedWith(root, cells[2][2]); + + check(height(cells[0][1]) >= height(cells[1][1]), `cell01 height<${height(cells[0][1])}> not greater or equal cell11 height<${height(cells[1][1])}>`); + check(height(cells[1][1]) <= height(cells[2][1]), `cell11 height<${height(cells[1][1])}> not less or equal cell21 height<${height(cells[2][1])}>`); + const sumOfNestedListViewHeights = height(cells[0][1]) + height(cells[1][1]) + height(cells[2][1]); + equal(height(root), sumOfNestedListViewHeights, `grid height<${height(root)}> sum of nested list views height <${sumOfNestedListViewHeights}>`); + + check(width(cells[1][0]) >= width(cells[1][1]), `cell10 width<${width(cells[1][0])}> not greater or equal cell11 width<${width(cells[1][1])}>`); + check(width(cells[1][1]) <= width(cells[1][2]), `cell11 width<${width(cells[1][1])}> not less or equal cell12 width<${width(cells[1][2])}>`); + const sumOfNestedListViewWidths = width(cells[1][0]) + width(cells[1][1]) + width(cells[1][2]) + equal(width(root), sumOfNestedListViewWidths, `grid width<${width(root)}> sum of nested list views width <${sumOfNestedListViewWidths}>`); + }, + pageOptions + ); + } + + // public test_grid_nested_list_views_layout_beyond_safe_area_action_bar() { + // this.grid_nested_list_views_layout_beyond_safe_area({ actionBar: true }); + // } + + // public test_grid_nested_list_views_layout_in_safe_area_action_bar_hidden() { + // this.grid_nested_list_views_layout_beyond_safe_area({ actionBarHidden: true }); + // } + + // public test_grid_nested_list_views_layout_in_safe_area_action_bar_flat() { + // this.grid_nested_list_views_layout_beyond_safe_area({ actionBarFlat: true }); + // } + + // public test_grid_nested_list_views_layout_in_safe_area_tab_bar() { + // this.grid_nested_list_views_layout_beyond_safe_area({ tabBar: true }); + // } +} + +function setBindingContext(list: ListView) { + return function () { + const page = list.page; + page.bindingContext = new ViewModel(); + } +} + +export function createTestCase(): ListViewSafeAreaTest { + return new ListViewSafeAreaTest(); +} diff --git a/tests/app/ui/list-view/list-view-view-model.ts b/tests/app/ui/list-view/list-view-view-model.ts new file mode 100644 index 000000000..5326ed31b --- /dev/null +++ b/tests/app/ui/list-view/list-view-view-model.ts @@ -0,0 +1,19 @@ +import { Observable } from "tns-core-modules/data/observable"; + +export class ViewModel extends Observable { + items: Array; + + constructor() { + super(); + + this.items = []; + + for (let i = 0; i < 50; i++) { + this.items.push({ + id: "child" + i.toString(), + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut scelerisque enim mi, id ultrices felis maximus vel.", + shortText: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + }); + } + } +} \ No newline at end of file