import page = require("ui/page"); import layout = require("ui/layouts/grid-layout"); import {Button} from "ui/button"; import TKUnit = require("../TKUnit"); import helper = require("./layout-helper"); import view = require("ui/core/view"); import navHelper = require("../ui/helper"); import utils = require("utils/utils"); import builder = require("ui/builder"); import enums = require("ui/enums"); var ASYNC = 2; var DELTA = 1; export class MyGridLayout extends layout.GridLayout { public measureCount: number = 0; public layoutCount: number = 0; public get measured(): boolean { return this.measureCount > 0; } public get layouted(): boolean { return this.layoutCount > 0; } public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { super.onMeasure(widthMeasureSpec, heightMeasureSpec); this.measureCount++; } public onLayout(left: number, top: number, right: number, bottom: number): void { super.onLayout(left, top, right, bottom); this.layoutCount++; } } var tmp: Button; var newPage: page.Page; var rootLayout: MyGridLayout; export function setUpModule() { var pageFactory = function (): page.Page { newPage = new page.Page; tmp = new Button(); tmp.text = "Loading test"; newPage.content = tmp; return newPage; }; navHelper.navigate(pageFactory); } export function tearDownModule() { navHelper.goBack(); tmp = null; newPage = null; rootLayout = null; } export function setUp() { rootLayout = new MyGridLayout(); newPage.content = rootLayout; } export function tearDown() { newPage.content = tmp; } function row(view: view.View): number { return layout.GridLayout.getRow(view); } function rowSpan(view: view.View): number { return layout.GridLayout.getRowSpan(view); } function col(view: view.View): number { return layout.GridLayout.getColumn(view); } function colSpan(view: view.View): number { return layout.GridLayout.getColumnSpan(view); } export function test_row_defaultValue() { var test = new Button(); TKUnit.assert(test !== null); TKUnit.assertEqual(row(test), 0, "'row' property default value should be 0."); } export function test_rowSpan_defaultValue() { var test = new Button(); TKUnit.assert(test !== null); TKUnit.assertEqual(rowSpan(test), 1, "'rowSpan' property default value should be 1."); } export function test_column_defaultValue() { var test = new Button(); TKUnit.assert(test !== null); TKUnit.assertEqual(col(test), 0, "'column' property default value should be 0."); } export function test_columnSpan_defaultValue() { var test = new Button(); TKUnit.assert(test !== null); TKUnit.assertEqual(colSpan(test), 1, "'columnSpan' property default value should be 1."); } export function test_getRow_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.getRow(null); }, "getRow called with null should throw exception"); } export function test_getRowSpan_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.getRowSpan(null); }, "getRowSpan called with null should throw exception"); } export function test_getColumn_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.getColumn(null); }, "getColumn called with null should throw exception"); } export function test_getColumnSpan_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.getColumnSpan(null); }, "getColumnSpan called with null should throw exception"); } export function test_setRow_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.setRow(null, 1); }, "setRow called with null should throw exception"); } export function test_setRowSpan_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.setRowSpan(null, 1); }, "setRowSpan called with null should throw exception"); } export function test_setColumn_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.setColumn(null, 1); }, "setColumn called with null should throw exception") } export function test_setColumnSpan_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { layout.GridLayout.setColumnSpan(null, 1); }, "setColumnSpan called with null should throw exception"); } export function test_setRow_shouldThrow_onNegativeValues() { TKUnit.assertThrows(() => { layout.GridLayout.setRow(tmp, -1); }, "setRow should throw when value < 0"); } export function test_setRowSpan_shouldThrow_onNotPositiveValues() { TKUnit.assertThrows(() => { layout.GridLayout.setRowSpan(tmp, 0); }, "setRowSpan should throw when value <= 0"); } export function test_setColumn_shouldThrow_onNegativeValues() { TKUnit.assertThrows(() => { layout.GridLayout.setColumn(tmp, -1); }, "setColumn should when value < 0"); } export function test_setColumnSpan_shouldThrow_onNotPositiveValues() { TKUnit.assertThrows(() => { layout.GridLayout.setColumnSpan(tmp, 0); }, "setColumnSpan should throw when value <= 0"); } export function test_addRow_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { rootLayout.addRow(null); }, "addRow called with null should throw exception"); } export function test_addColumn_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { rootLayout.addColumn(null); }, "addColumn called with null should throw exception"); } export function test_removeRow_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { rootLayout.removeRow(null); }, "removeRow called with null should throw exception"); } export function test_removeColumn_shouldThrow_onNullValues() { TKUnit.assertThrows(() => { rootLayout.removeColumn(null); }, "removeColumn called with null should throw exception"); } export function test_removeColumns() { prepareGridLayout(false); TKUnit.assertTrue(rootLayout.getColumns().length > 0, "There should be columns."); rootLayout.removeColumns(); TKUnit.assertTrue(rootLayout.getColumns().length === 0, "Columns should be empty."); } export function test_removeRows() { prepareGridLayout(false); TKUnit.assertTrue(rootLayout.getRows().length > 0, "There should be rows."); rootLayout.removeRows(); TKUnit.assertTrue(rootLayout.getRows().length === 0, "Rows should be empty."); } export function test_removeChildren() { prepareGridLayout(false); TKUnit.assertTrue(rootLayout.getChildrenCount() > 0, "There should be children."); rootLayout.removeChildren(); TKUnit.assertTrue(rootLayout.getChildrenCount() === 0, "Childrens should be empty."); } export function test_measuredWidth_when_not_stretched_single_column() { rootLayout.horizontalAlignment = enums.HorizontalAlignment.center; let btn = new Button(); btn.text = "A"; rootLayout.addChild(btn); TKUnit.waitUntilReady(function () { return rootLayout.isLayoutValid; }, ASYNC); TKUnit.assertTrue(btn.getMeasuredWidth() === rootLayout.getMeasuredWidth()); } export function test_measuredWidth_when_not_stretched_two_columns() { rootLayout.horizontalAlignment = enums.HorizontalAlignment.center; rootLayout.addColumn(new layout.ItemSpec(80, layout.GridUnitType.pixel)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); let btn = new Button(); btn.text = "A"; btn.width = 100; MyGridLayout.setColumnSpan(btn, 2); rootLayout.addChild(btn); TKUnit.waitUntilReady(function () { return rootLayout.isLayoutValid; }, ASYNC); var density = utils.layout.getDisplayDensity(); var delta = Math.floor(density) !== density ? 2 : DELTA; var cols = rootLayout.getColumns(); TKUnit.assertAreClose(cols[0].actualLength, 80, delta); TKUnit.assertAreClose(cols[1].actualLength, 20, delta); TKUnit.assertAreClose(rootLayout.getMeasuredWidth(), 100 * density, delta); } export function test_measuredWidth_when_not_stretched_three_columns() { rootLayout.horizontalAlignment = enums.HorizontalAlignment.center; rootLayout.addColumn(new layout.ItemSpec(80, layout.GridUnitType.pixel)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.auto)); for (let i = 1; i < 4; i++) { let btn = new Button(); btn.text = "A"; btn.width = i * 20; MyGridLayout.setColumn(btn, i - 1); rootLayout.addChild(btn); } let btn = new Button(); btn.text = "B"; btn.width = 100; MyGridLayout.setColumnSpan(btn, 3); rootLayout.addChild(btn); TKUnit.waitUntilReady(function () { return rootLayout.isLayoutValid; }, ASYNC); var density = utils.layout.getDisplayDensity(); var delta = Math.floor(density) !== density ? 2 : DELTA; var cols = rootLayout.getColumns(); TKUnit.assertAreClose(cols[0].actualLength, 80, delta); TKUnit.assertAreClose(cols[1].actualLength, 40, delta); TKUnit.assertAreClose(cols[2].actualLength, 60, delta); TKUnit.assertAreClose(rootLayout.getMeasuredWidth(), 180 * density, delta); } export function test_getRows_shouldNotReturnNULL() { var rows = rootLayout.getRows(); TKUnit.assert(rows, "getRows should not return null/undefinied"); } export function test_getColumns_shouldNotReturnNULL() { var cols = rootLayout.getColumns(); TKUnit.assert(cols, "getColumns should not return null/undefinied"); } export function test_ItemSpec_actualLength_defaultValue() { var def = new layout.ItemSpec(1, layout.GridUnitType.auto); TKUnit.assertEqual(def.actualLength, 0, "'actualLength' property default value should be 0."); } export function test_ItemSpec_constructor_throws_onNegativeValue() { TKUnit.assertThrows(() => { new layout.ItemSpec(-1, layout.GridUnitType.auto); }, "'value' should be positive number."); } export function test_ItemSpec_constructor_doesnt_throw_onCorrectType() { try { new layout.ItemSpec(1, layout.GridUnitType.auto); new layout.ItemSpec(1, layout.GridUnitType.star); new layout.ItemSpec(1, layout.GridUnitType.pixel); } catch (ex) { TKUnit.assert(false, "ItemSpec type should support auto, star and pixel."); } } export function test_ItemSpec_constructor_throws_onWrongType() { TKUnit.assertThrows(() => { new layout.ItemSpec(1, "unsupported"); }, "'ItemSpec type' incorrect value."); } export function test_ItemSpec_auto() { var w = new layout.ItemSpec(1, layout.GridUnitType.auto); TKUnit.assertEqual(w.gridUnitType, layout.GridUnitType.auto, "'gridUnitType' property default value should be 'auto'"); TKUnit.assertEqual(w.isAbsolute, false, "'isAbsolute' property default value should be 'false'"); TKUnit.assertEqual(w.isAuto, true, "'isAuto' property default value should be 'false'"); TKUnit.assertEqual(w.isStar, false, "'isAuto' property default value should be 'true'"); TKUnit.assertEqual(w.value, 1, "'value' property default value should be '1'"); } export function test_ItemSpec_unitType_pixel() { var w = new layout.ItemSpec(6, layout.GridUnitType.pixel); TKUnit.assertEqual(w.gridUnitType, layout.GridUnitType.pixel, "'gridUnitType' property default value should be 'pixel'"); TKUnit.assertEqual(w.isAbsolute, true, "'isAbsolute' property default value should be 'false'"); TKUnit.assertEqual(w.isAuto, false, "'isAuto' property default value should be 'false'"); TKUnit.assertEqual(w.isStar, false, "'isAuto' property default value should be 'true'"); TKUnit.assertEqual(w.value, 6, "'value' property default value should be '1'"); } export function test_ItemSpec_unitType() { var w = new layout.ItemSpec(2, layout.GridUnitType.star); TKUnit.assertEqual(w.gridUnitType, layout.GridUnitType.star, "'gridUnitType' property default value should be 'star'"); TKUnit.assertEqual(w.isAbsolute, false, "'isAbsolute' property default value should be 'false'"); TKUnit.assertEqual(w.isAuto, false, "'isAuto' property default value should be 'false'"); TKUnit.assertEqual(w.isStar, true, "'isAuto' property default value should be 'true'"); TKUnit.assertEqual(w.value, 2, "'value' property default value should be '1'"); } function prepareGridLayout(wait?: boolean) { rootLayout.addRow(new layout.ItemSpec(1, layout.GridUnitType.star)); rootLayout.addRow(new layout.ItemSpec(2, layout.GridUnitType.star)); rootLayout.addRow(new layout.ItemSpec(50, layout.GridUnitType.pixel)); rootLayout.addRow(new layout.ItemSpec(50, layout.GridUnitType.auto)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); rootLayout.addColumn(new layout.ItemSpec(2, layout.GridUnitType.star)); rootLayout.addColumn(new layout.ItemSpec(50, layout.GridUnitType.pixel)); rootLayout.addColumn(new layout.ItemSpec(50, layout.GridUnitType.auto)); for (var r = 0; r < 4; r++) { for (var c = 0; c < 4; c++) { var btn = new helper.MyButton(); btn.text = "R" + r + "C" + c; layout.GridLayout.setColumn(btn, c); layout.GridLayout.setRow(btn, r); if (c === 3) { btn.width = 100; // Auto column should take 100px for this test. } if (r === 3) { btn.height = 100; // Auto row should take 100px for this test. } rootLayout.addChild(btn); } } rootLayout.width = 300; rootLayout.height = 300; if (wait) { TKUnit.waitUntilReady(function () { return rootLayout.isLayoutValid; }, ASYNC); } } export function test_desiredSize_isCorrect() { prepareGridLayout(false); rootLayout.width = Number.NaN; rootLayout.height = Number.NaN; TKUnit.waitUntilReady(function () { return rootLayout.isLayoutValid; }, ASYNC); var maxWidth = 0; var maxHeight = 0; var width = 0; var height = 0; var i = 0; var cols = rootLayout.getColumns(); var rows = rootLayout.getRows(); for (var r = 0; r < 4; r++) { width = 0; height = 0; for (var c = 0; c < 4; c++) { var btn = rootLayout.getChildAt(i++); if (cols[c].isAbsolute) { width += helper.dip(cols[c].actualLength); } else { width += btn.getMeasuredWidth(); } height = Math.max(height, btn.getMeasuredHeight()); } maxWidth = Math.max(maxWidth, width); if (rows[r].isAbsolute) { maxHeight += helper.dip(rows[r].actualLength); } else { maxHeight += height; } } var delta = 1.1; // Set to an overly high value to avoid failing on some emulators. let measuredWidth = rootLayout.getMeasuredWidth(); let measuredHeight = rootLayout.getMeasuredHeight(); TKUnit.assertAreClose(measuredWidth, maxWidth, delta, "GridLayout incorrect measured width"); TKUnit.assertAreClose(measuredHeight, maxHeight, delta, "GridLayout incorrect measured height"); } export function test_columnsActualWidth_isCorrect() { prepareGridLayout(true); var cols = rootLayout.getColumns(); TKUnit.assertEqual(cols[0].actualLength, 50, "Star column should be 50px width"); TKUnit.assertEqual(cols[1].actualLength, 100, "2*Star column should be 100px width"); TKUnit.assertEqual(cols[2].actualLength, 50, "Absolute column should be 50px width"); TKUnit.assertEqual(cols[3].actualLength, 100, "Auto column should be 100px width"); } export function test_rowsActualHeight_isCorrect() { prepareGridLayout(true); var rows = rootLayout.getRows(); TKUnit.assertEqual(rows[0].actualLength, 50, "Star row should be 50px width"); TKUnit.assertEqual(rows[1].actualLength, 100, "2*Star row should be 100px width"); TKUnit.assertEqual(rows[2].actualLength, 50, "Absolute row should be 50px width"); TKUnit.assertEqual(rows[3].actualLength, 100, "Auto row should be 100px width"); } export function test_Measure_and_Layout_Children_withCorrect_size() { prepareGridLayout(true); var rows = rootLayout.getRows(); var cols = rootLayout.getColumns(); var i = 0; var density = utils.layout.getDisplayDensity(); var delta = Math.floor(density) !== density ? 1.1 : DELTA; for (var r = 0; r < 4; r++) { for (var c = 0; c < 4; c++) { var btn = rootLayout.getChildAt(i++); var col = cols[c]; var row = rows[r]; var h = r % 2 === 0 ? 50 : 100; var w = c % 2 === 0 ? 50 : 100; h = Math.round(h * density); w = Math.round(w * density); if (row.isAuto) { TKUnit.assertAreClose(btn.layoutHeight, btn.getMeasuredHeight(), delta, "Auto rows should layout with measured height"); } else if (row.isAbsolute) { TKUnit.assertAreClose(btn.measureHeight, h, delta, "Absolute rows should measure with specific height"); TKUnit.assertAreClose(btn.layoutHeight, h, delta, "Absolute rows should layout with specific height"); } else { TKUnit.assertAreClose(btn.measureHeight, h, delta, "Star rows should measure with specific height"); TKUnit.assertAreClose(btn.layoutHeight, h, delta, "Star rows should layout with exact length"); } if (col.isAuto) { TKUnit.assertAreClose(btn.layoutWidth, btn.getMeasuredWidth(), delta, "Auto columns should layout with measured width"); } else if (col.isAbsolute) { TKUnit.assertAreClose(btn.measureWidth, w, delta, "Absolute columns should measure with specific width"); TKUnit.assertAreClose(btn.layoutWidth, w, delta, "Absolute columns should layout with specific width"); } else { TKUnit.assertAreClose(btn.measureWidth, w, delta, "Star columns should measure with specific width"); TKUnit.assertAreClose(btn.layoutWidth, w, delta, "Star columns should layout with exact length"); } } } } export function test_ColumnWidth_when_4stars_and_width_110() { rootLayout.width = 110; rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); rootLayout.addColumn(new layout.ItemSpec(1, layout.GridUnitType.star)); TKUnit.waitUntilReady(function () { return rootLayout.isLayoutValid; }, ASYNC); var cols = rootLayout.getColumns(); var density = utils.layout.getDisplayDensity(); var delta = Math.floor(density) !== density ? 1.1 : DELTA; TKUnit.assertAreClose(cols[0].actualLength, 28, delta, "Column[0] actual length should be 28"); TKUnit.assertAreClose(cols[1].actualLength, 27, delta, "Column[1] actual length should be 27"); TKUnit.assertAreClose(cols[2].actualLength, 28, delta, "Column[2] actual length should be 28"); TKUnit.assertAreClose(cols[3].actualLength, 27, delta, "Column[3] actual length should be 27"); } export function test_margins_and_verticalAlignment_center() { rootLayout.height = 200; rootLayout.width = 200; var btn = new helper.MyButton(); btn.text = "btn"; btn.height = 100; btn.width = 100; btn.marginBottom = 50; btn.marginRight = 50; rootLayout.addChild(btn); TKUnit.waitUntilReady(function () { return btn.isLayoutValid; }, ASYNC); var density = utils.layout.getDisplayDensity(); var delta = Math.floor(density) !== density ? 1.1 : DELTA; TKUnit.assertAreClose(btn.layoutTop, 25 * density, delta, "vertical margins"); TKUnit.assertAreClose(btn.layoutLeft, 25 * density, delta, "horizontal margins"); } export function test_set_columns_in_XML() { var p = builder.parse("