Files
NativeScript/tests/app/testRunner.ts
Hristo Hristov af034089ca iOS Frame, Page and TabView measure/layout methods removed. We now rely on the framework positioning. This will result in a change that width, height, minWidth, minHeight, margins not respected on these controls
iOS layout positioning now respects native properties like automaticallyAdjustsScrollViewInsets, edgesForExtendedLayout, extendedLayoutIncludesOpaqueBars, navigationBar.translucent, tabBar.translucent
Removed frame-tests.ios.ts - those tests are now invalid
Added new layout tests inside page-tests.ios.ts
Commented few asserts in scroll-view-tests
View now expose ios namespace with layoutView method and UILayoutViewController used by page, tab-view and application module
ViewBase now expose viewController property that should be set from all widgets that are using viewcontrollers internally (like Page, Frame, TabView)
ViewBase now sets ios property to either the view returned from createNativeView or to nativeViewProptected
fragment.transitions now use animation/transition start to add fragments to waitingQueue. Before we did it manually in navigate/goBack. This way we can reuse the fragment.transition when calling showDialog. Also when animation/transition ends we check the animation/transition to see if this fragment should be set as current.
Frame expose new loadViewFromEntry method (to load a view from URI)
Frame navigation happens once frame is loaded
Frame now supports Page as a child in XML
Fixed GridLayout row, rowSpan, column, columnSpan properties type
Fixed bug in GridLayout where add/remove of columns/rows won't update the internal state of the grid (backport from android when GridLayout is recycled)
ListView will no longer invalidate layout when cell is removed
Fixed bug in ScrollView ios where effectiveMinWidth/Height was multiplied to density (it is already on device pixels so no need to multiply)
TabView android now calls loaded only on the selected child (not all)
Core refactoring
2017-12-15 13:06:34 +02:00

474 lines
16 KiB
TypeScript

/* tslint:disable */
import * as TKUnit from "./TKUnit";
import { messageType } from "tns-core-modules/trace";
import { topmost, Frame } from "tns-core-modules/ui/frame";
import { TextView } from "tns-core-modules/ui/text-view";
import { Button } from "tns-core-modules/ui/button";
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout";
import * as platform from "tns-core-modules/platform";
import "./ui-test";
import * as fs from "tns-core-modules/file-system";
import { unsetValue } from "tns-core-modules/ui/core/properties";
import { ad } from "tns-core-modules/utils/utils";
Frame.defaultAnimatedNavigation = false;
export function isRunningOnEmulator(): boolean {
// This checks are not good enough to be added to modules but keeps unittests green.
if (platform.device.os === platform.platformNames.android) {
return android.os.Build.FINGERPRINT.indexOf("generic") > -1 ||
android.os.Build.HARDWARE.toLowerCase() === "goldfish" ||
android.os.Build.HARDWARE.toLowerCase() === "donatello" || // VS Emulator
android.os.Build.PRODUCT.toLocaleLowerCase().indexOf("sdk") > -1 ||
android.os.Build.PRODUCT.toLocaleLowerCase().indexOf("emulator") > -1; // VS Emulator
}
else if (platform.device.os === platform.platformNames.ios) {
//return platform.device.model === "iPhone Simulator";
return (__dirname.search("Simulator") > -1);
}
}
export const allTests = {};
import * as domNodeTest from "./debugger/dom-node-tests";
allTests["DOM-NODE"] = domNodeTest;
import * as profilingTests from "./profiling/profiling-tests";
allTests["PROFILING"] = profilingTests;
import * as platformTests from "./platform/platform-tests";
allTests["PLATFORM"] = platformTests;
import * as fsTests from "./file-system/file-system-tests";
allTests["FILE-SYSTEM"] = fsTests;
import * as httpTests from "./http/http-tests";
allTests["HTTP"] = httpTests;
import * as xhrTests from "./xhr/xhr-tests";
allTests["XHR"] = xhrTests;
import * as fetchTests from "./fetch/fetch-tests";
allTests["FETCH"] = fetchTests;
import * as appSettingsTests from "./application-settings/application-settings-tests";
allTests["APPLICATION-SETTINGS"] = appSettingsTests;
import * as applicationTests from "./application/application-tests";
allTests["APPLICATION"] = applicationTests;
import * as imageSourceTests from "./image-source/image-source-tests";
allTests["IMAGE-SOURCE"] = imageSourceTests;
import * as observableArrayTests from "./data/observable-array-tests";
allTests["OBSERVABLE-ARRAY"] = observableArrayTests;
import * as virtualArrayTests from "./data/virtual-array-tests";
allTests["VIRTUAL-ARRAY"] = virtualArrayTests;
import * as observableTests from "./data/observable-tests";
allTests["OBSERVABLE"] = observableTests;
import * as timerTests from "./timer/timer-tests";
allTests["TIMER"] = timerTests;
import * as colorTests from "./color/color-tests";
allTests["COLOR"] = colorTests;
import * as bindableTests from "./ui/core/bindable/bindable-tests";
allTests["BINDABLE"] = bindableTests;
import * as bindintExpressionTests from "./ui/core/bindable/binding-expressions-tests";
allTests["BINDING-EXPRESSIONS"] = bindintExpressionTests;
import * as xmlParserTests from "./xml-parser-tests/xml-parser-tests";
allTests["XML-PARSER"] = xmlParserTests;
import * as formattedStringTests from "./text/formatted-string-tests";
allTests["FORMATTEDSTRING"] = formattedStringTests;
import * as fileSystemAccessTests from "./file-system-access-tests/file-system-access-tests";
allTests["FILE-SYSTEM-ACCESS"] = fileSystemAccessTests;
import * as fileNameResolverTests from "./file-name-resolver-tests/file-name-resolver-tests";
allTests["FILE-NAME-RESOLVER"] = fileNameResolverTests;
import * as weakEventsTests from "./ui/core/weak-event-listener/weak-event-listener-tests";
allTests["WEAK-EVENTS"] = weakEventsTests;
import * as connectivityTests from "./connectivity/connectivity-tests";
allTests["CONNECTIVITY"] = connectivityTests;
import * as proxyViewContainerTests from "./ui/proxy-view-container/proxy-view-container-tests";
allTests["PROXY-VIEW-CONTAINER"] = proxyViewContainerTests;
import * as scrollViewTests from "./ui/scroll-view/scroll-view-tests";
allTests["SCROLL-VIEW"] = scrollViewTests;
import * as actionBarTests from "./ui/action-bar/action-bar-tests";
allTests["ACTION-BAR"] = actionBarTests;
import * as xmlDeclarationTests from "./xml-declaration/xml-declaration-tests";
allTests["XML-DECLARATION"] = xmlDeclarationTests;
import * as dockLayoutTests from "./ui/layouts/dock-layout-tests";
allTests["DOCKLAYOUT"] = dockLayoutTests;
import * as wrapLayoutTests from "./ui/layouts/wrap-layout-tests";
allTests["WRAPLAYOUT"] = wrapLayoutTests;
import * as absoluteLayoutTests from "./ui/layouts/absolute-layout-tests";
allTests["ABSOLUTELAYOUT"] = absoluteLayoutTests;
import * as gridLayoutTests from "./ui/layouts/grid-layout-tests";
allTests["GRIDLAYOUT"] = gridLayoutTests;
import * as stackLayoutTests from "./ui/layouts/stack-layout-tests";
allTests["STACKLAYOUT"] = stackLayoutTests;
import * as flexBoxLayoutTests from "./ui/layouts/flexbox-layout-tests";
allTests["FLEXBOXLAYOUT"] = flexBoxLayoutTests;
import * as stylePropertiesTests from "./ui/styling/style-properties-tests";
allTests["STYLE-PROPERTIES"] = stylePropertiesTests;
import * as frameTests from "./ui/frame/frame-tests";
allTests["FRAME"] = frameTests;
import * as viewTests from "./ui/view/view-tests";
allTests["VIEW"] = viewTests;
import * as styleTests from "./ui/styling/style-tests";
allTests["STYLE"] = styleTests;
import * as visualStateTests from "./ui/styling/visual-state-tests";
allTests["VISUAL-STATE"] = visualStateTests;
import * as valueSourceTests from "./ui/styling/value-source-tests";
allTests["VALUE-SOURCE"] = valueSourceTests;
import * as buttonTests from "./ui/button/button-tests";
allTests["BUTTON"] = buttonTests;
import * as borderTests from "./ui/border/border-tests";
allTests["BORDER"] = borderTests;
import * as labelTests from "./ui/label/label-tests";
allTests["LABEL"] = labelTests;
import * as tabViewTests from "./ui/tab-view/tab-view-tests";
allTests["TAB-VIEW"] = tabViewTests;
import * as tabViewNavigationTests from "./ui/tab-view/tab-view-navigation-tests";
allTests["TAB-VIEW-NAVIGATION"] = tabViewNavigationTests;
import * as imageTests from "./ui/image/image-tests";
allTests["IMAGE"] = imageTests;
import * as sliderTests from "./ui/slider/slider-tests";
allTests["SLIDER"] = sliderTests;
import * as switchTests from "./ui/switch/switch-tests";
allTests["SWITCH"] = switchTests;
import * as progressTests from "./ui/progress/progress-tests";
allTests["PROGRESS"] = progressTests;
import * as placeholderTests from "./ui/placeholder/placeholder-tests";
allTests["PLACEHOLDER"] = placeholderTests;
import * as pageTests from "./ui/page/page-tests";
allTests["PAGE"] = pageTests;
import * as listViewTests from "./ui/list-view/list-view-tests";
allTests["LISTVIEW"] = listViewTests;
import * as activityIndicatorTests from "./ui/activity-indicator/activity-indicator-tests";
allTests["ACTIVITY-INDICATOR"] = activityIndicatorTests;
import * as textFieldTests from "./ui/text-field/text-field-tests";
allTests["TEXT-FIELD"] = textFieldTests;
import * as textViewTests from "./ui/text-view/text-view-tests";
allTests["TEXT-VIEW"] = textViewTests;
import * as listPickerTests from "./ui/list-picker/list-picker-tests";
allTests["LIST-PICKER"] = listPickerTests;
import * as datePickerTests from "./ui/date-picker/date-picker-tests";
allTests["DATE-PICKER"] = datePickerTests;
import * as timePickerTests from "./ui/time-picker/time-picker-tests";
allTests["TIME-PICKER"] = timePickerTests;
import * as webViewTests from "./ui/web-view/web-view-tests";
allTests["WEB-VIEW"] = webViewTests;
import * as htmlViewTests from "./ui/html-view/html-view-tests";
allTests["HTML-VIEW"] = htmlViewTests;
import * as repeaterTests from "./ui/repeater/repeater-tests";
allTests["REPEATER"] = repeaterTests;
import * as segmentedBarTests from "./ui/segmented-bar/segmented-bar-tests";
allTests["SEGMENTED-BAR"] = segmentedBarTests;
import * as animationTests from "./ui/animation/animation-tests";
allTests["ANIMATION"] = animationTests;
import * as lifecycle from "./ui/lifecycle/lifecycle-tests";
allTests["LIFECYCLE"] = lifecycle;
import * as cssAnimationTests from "./ui/animation/css-animation-tests";
allTests["CSS-ANIMATION"] = cssAnimationTests;
import * as transitionTests from "./navigation/transition-tests";
allTests["TANSITIONS"] = transitionTests;
import * as searchBarTests from "./ui/search-bar/search-bar-tests";
allTests["SEARCH-BAR"] = searchBarTests;
import * as navigationTests from "./navigation/navigation-tests";
allTests["NAVIGATION"] = navigationTests;
const testsSuitesWithLongDelay = {
HTTP: 15 * 1000,
}
const testsWithLongDelay = {
testLocation: 10000,
testLocationOnce: 10000,
testLocationOnceMaximumAge: 10000,
//web-view-tests
testLoadExistingUrl: 10000 * 5,
testLoadLocalFile: 10000 * 5,
testLoadInvalidUrl: 10000,
testLoadUpperCaseSrc: 10000 * 5,
test_SettingImageSrc: 30 * 1000,
test_ChainingAnimations: 30 * 1000,
test_AnimatingProperties: 30 * 1000,
test_AnimateBackgroundColor_FromString: 10 * 1000
}
let startTime;
let running = false;
let testsQueue = new Array<TestInfo>();
function printRunTestStats() {
const testCases = new Array<string>();
let failedTestCount = 0;
const failedTestInfo = [];
const slowTests = new Array<string>();
let allTests = testsQueue.filter(t => t.isTest);
allTests.forEach((testCase, i, arr) => {
let testName = testCase.testName;
if (!testCase.isPassed) {
failedTestCount++;
failedTestInfo.push(testCase.testName + " FAILED: " + testCase.errorMessage);
}
let duration = (testCase.duration / 1000).toFixed(2);
if (testCase.duration > 500) {
slowTests.push(`${testCase.testName}: ${duration}s`);
}
});
const totalTime = (TKUnit.time() - startTime).toFixed(2);
let finalMessage = `\n` +
`=== ALL TESTS COMPLETE ===\n` +
`${(allTests.length - failedTestCount)} OK, ${failedTestCount} failed\n` +
`DURATION: ${totalTime} ms\n` +
`=== END OF TESTS ===\n`;
TKUnit.write(finalMessage, messageType.info);
failedTestInfo.forEach((message, i, arr) => {
TKUnit.write(message, messageType.error);
finalMessage += "\n" + message;
});
// console.log("test-result.xml:\n" + generateTestFile(allTests));
// DO NOT CHANGE THE FIRST ROW! Used as an indicator for test run pass detection.
TKUnit.write(`Tests EOF!`, messageType.info);
showReportPage(finalMessage);
}
function generateTestFile(allTests: TestInfo[]) {
let failedTestCount = 0;
const testCases = new Array<string>();
allTests.forEach((testCase, i, arr) => {
let testName = testCase.testName;
let duration = (testCase.duration / 1000).toFixed(2);
testCases.push(`<testcase classname="${platform.device.os}" name="${testName}" time="${duration}">`)
if (!testCase.isPassed) {
failedTestCount++;
testCases.push(`<failure type="exceptions.AssertionError"><![CDATA[${testCase.errorMessage}]]></failure>`)
}
testCases.push(`</testcase>`);
});
const totalTime = (TKUnit.time() - startTime).toFixed(2);
const result = [
"<testsuites>",
`<testsuite name="NativeScript Tests" timestamp="${new Date()}" hostname="hostname" time="${totalTime}" errors="0" tests="${allTests.length}" skipped="0" failures="${failedTestCount}">`,
...testCases,
"</testsuite>",
"</testsuites>"
].join("");
return result;
}
function showReportPage(finalMessage: string) {
const stack = new StackLayout();
const btn = new Button();
btn.text = "Rerun tests";
btn.on("tap", () => runAll(testsSelector));
stack.addChild(btn);
const messageContainer = new TextView();
messageContainer.editable = messageContainer.autocorrect = false;
messageContainer.text = finalMessage;
stack.addChild(messageContainer);
const page = topmost().currentPage;
page.id = unsetValue;
page.className = unsetValue;
page.bindingContext = unsetValue;
page.style.color = unsetValue;
page.backgroundColor = "white";
page.content = stack;
messageContainer.focus();
page.style.fontSize = 11;
if (page.android) {
setTimeout(() => {
messageContainer.dismissSoftInput();
(<android.view.View>messageContainer.nativeViewProtected).scrollTo(0, 0);
}, 10);
}
}
function startLog(): void {
let testsName: string = this.name;
TKUnit.write("START " + testsName + " TESTS.", messageType.info);
this.start = TKUnit.time();
}
function log(): void {
let testsName: string = this.name;
let duration = TKUnit.time() - this.start;
TKUnit.write(testsName + " COMPLETED for " + duration.toFixed(2) + " BACKSTACK DEPTH: " + topmost().backStack.length, messageType.info);
}
let testsSelector: string
export function runAll(testSelector?: string) {
testsSelector = testSelector;
if (running) {
// TODO: We may schedule pending run requests
return;
}
let singleModuleName, singleTestName;
if (testSelector) {
const pair = testSelector.split(".");
singleModuleName = pair[0];
if (singleModuleName) {
if (singleModuleName.length === 0) {
singleModuleName = undefined;
} else {
singleModuleName = singleModuleName.toLowerCase();
}
}
singleTestName = pair[1];
if (singleTestName) {
if (singleTestName.length === 0) {
singleTestName = undefined;
} else {
singleTestName = singleTestName.toLowerCase();
}
}
}
console.log("TESTS: " + singleModuleName ? singleModuleName : "" + " " + singleTestName ? singleTestName : "");
const totalSuccess = 0;
const totalFailed: Array<TKUnit.TestFailure> = [];
testsQueue.push(new TestInfo(() => { running = true; startTime = TKUnit.time(); }));
for (const name in allTests) {
if (singleModuleName && (singleModuleName !== name.toLowerCase())) {
continue;
}
const testModule = allTests[name];
const test = testModule.createTestCase ? testModule.createTestCase() : testModule;
test.name = name;
testsQueue.push(new TestInfo(startLog, test));
if (test.setUpModule) {
testsQueue.push(new TestInfo(test.setUpModule, test));
}
for (const testName in test) {
if (singleTestName && (singleTestName !== testName.toLowerCase())) {
continue;
}
const testFunction = test[testName];
if ((typeof (testFunction) === "function") && (testName.substring(0, 4) == "test")) {
if (test.setUp) {
testsQueue.push(new TestInfo(test.setUp, test));
}
const testTimeout = testsWithLongDelay[testName] || testsSuitesWithLongDelay[name];
testsQueue.push(new TestInfo(testFunction, test, true, name + "." + testName, false, null, testTimeout));
if (test.tearDown) {
testsQueue.push(new TestInfo(test.tearDown, test));
}
}
}
if (test.tearDownModule) {
testsQueue.push(new TestInfo(test.tearDownModule, test));
}
testsQueue.push(new TestInfo(log, test));
}
testsQueue.push(new TestInfo(printRunTestStats));
testsQueue.push(new TestInfo(function () { testsQueue = []; running = false; }));
TKUnit.runTests(testsQueue, 0);
}
class TestInfo implements TKUnit.TestInfoEntry {
testFunc: () => void;
instance: any;
isTest: boolean;
testName: string;
isPassed: boolean;
errorMessage: string;
testTimeout: number;
duration: number;
constructor(testFunc, testInstance?: any, isTest?, testName?, isPassed?, errorMessage?, testTimeout?, duration?) {
this.testFunc = testFunc;
this.instance = testInstance || null;
this.isTest = isTest || false;
this.testName = testName || "";
this.isPassed = isPassed || false;
this.errorMessage = errorMessage || "";
this.testTimeout = testTimeout;
this.duration = duration;
}
}