Skip to content

Commit 075e70e

Browse files
author
Hristo Hristov
authored
cache page on forward navigation (NativeScript#4652)
* cache page on forward navigation Still some failing navigation tests * Current page is kept alive when navigating forward Refactoring code and removing all hacks and flags Remove one module circular reference * Disable Page recycling because when there is transition between pages the nativeView stays animated (e.g. when transition is Fade the hidden page nativeView stays with Alpha 0) Disable recycling if there is native anitmation * Fix failing tests on ios & android API17 Fix wrong urls in http tests Made some timer tests async * Animations are not stored in BackstackEntry instead of Fragment because fragments could die (activity die) and recreated and we lose animations. * Fix android crash when activity is recreated. Refactoring transitionListener.
1 parent e827ece commit 075e70e

33 files changed

Lines changed: 1565 additions & 1770 deletions

apps/.vscode/launch.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"appRoot": "${workspaceRoot}",
3131
"sourceMaps": true,
3232
"watch": true,
33+
"stopOnEntry": true,
3334
"tnsArgs": [
3435
"--sync-all-files"
3536
]

tests/app/TKUnit.ts

Lines changed: 74 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import * as timer from "tns-core-modules/timer";
1515
import * as trace from "tns-core-modules/trace";
1616
import * as types from "tns-core-modules/utils/types";
1717
import * as platform from "tns-core-modules/platform";
18+
import { topmost } from "tns-core-modules/ui/frame";
1819

1920
import * as utils from "tns-core-modules/utils/utils";
2021

@@ -42,12 +43,12 @@ export function time(): number {
4243
}
4344
}
4445

45-
export var write = function write(message: string, type?: number) {
46+
export function write(message: string, type?: number) {
4647
//console.log(message);
4748
trace.write(message, trace.categories.Test, type);
4849
}
4950

50-
var runTest = function (testInfo: TestInfoEntry) {
51+
function runTest(testInfo: TestInfoEntry) {
5152
let start = time();
5253
let duration;
5354
try {
@@ -74,7 +75,7 @@ var runTest = function (testInfo: TestInfoEntry) {
7475
testInfo.errorMessage = e.message;
7576
}
7677
}
77-
};
78+
}
7879

7980
export interface TestFailure {
8081
moduleName: string;
@@ -89,55 +90,45 @@ export interface TestModuleRunResult {
8990
failed: Array<TestFailure>;
9091
}
9192

92-
var testsQueue: Array<TestInfoEntry>;
93-
var defaultTimeout = 5000;
93+
let testsQueue: Array<TestInfoEntry>;
94+
const defaultTimeout = 5000;
9495

95-
// testInfo : {testFunc: func, testName: string, isTest: boolean, isPassed: boolean, errorMessage: string}
9696
function runAsync(testInfo: TestInfoEntry, recursiveIndex: number, testTimeout?: number) {
97-
var error;
98-
var isDone = false;
99-
var handle;
100-
var testStartTime = time();
97+
let error;
98+
let isDone = false;
99+
let handle;
100+
const testStartTime = time();
101101
//write("--- [" + testInfo.testName + "] Started at: " + testStartTime, trace.messageType.info);
102-
var doneCallback = function (e: Error) {
102+
const doneCallback = (e: Error) => {
103103
if (e) {
104104
error = e;
105-
}
106-
else {
105+
} else {
107106
isDone = true;
108107
}
109108
}
110-
var testTimeout = testInfo.testTimeout;
111-
if (!testTimeout) {
112-
testTimeout = defaultTimeout;
113-
}
109+
110+
const timeout = testTimeout || testInfo.testTimeout || defaultTimeout;
114111

115112
let duration;
116-
var checkFinished = function () {
113+
const checkFinished = () => {
117114
duration = time() - testStartTime;
118115
testInfo.duration = duration;
119116
if (isDone) {
120-
write("--- [" + testInfo.testName + "] OK, duration: " + duration, trace.messageType.info);
121-
//write("--- [" + testInfo.testName + "] took: " + (new Date().getTime() - testStartTime), trace.messageType.info);
117+
write(`--- [${testInfo.testName}] OK, duration: ${duration}`, trace.messageType.info);
122118
testInfo.isPassed = true;
123119
runTests(testsQueue, recursiveIndex + 1);
124-
}
125-
else if (error) {
126-
write("--- [" + testInfo.testName + "] FAILED: " + error.message + ", duration: " + duration, trace.messageType.error);
127-
//write("--- [" + testInfo.testName + "] took: " + (new Date().getTime() - testStartTime), trace.messageType.info);
120+
} else if (error) {
121+
write(`--- ["${testInfo.testName}"] FAILED: ${error.message}, duration: ${duration}`, trace.messageType.error);
128122
testInfo.errorMessage = error.message;
129123
runTests(testsQueue, recursiveIndex + 1);
130-
}
131-
else {
132-
var testEndTime = time();
133-
if (testEndTime - testStartTime > testTimeout) {
134-
write("--- [" + testInfo.testName + "] TIMEOUT, duration: " + duration, trace.messageType.error);
135-
//write("--- [" + testInfo.testName + "] took: " + (testEndTime - testStartTime), trace.messageType.info);
124+
} else {
125+
const testEndTime = time();
126+
if (testEndTime - testStartTime > timeout) {
127+
write(`--- ["${testInfo.testName}"] TIMEOUT, duration: ${duration}`, trace.messageType.error);
136128
testInfo.errorMessage = "Test timeout.";
137129
runTests(testsQueue, recursiveIndex + 1);
138-
}
139-
else {
140-
setTimeout(checkFinished, 10);
130+
} else {
131+
setTimeout(checkFinished, 0);
141132
}
142133
}
143134
}
@@ -146,7 +137,7 @@ function runAsync(testInfo: TestInfoEntry, recursiveIndex: number, testTimeout?:
146137
if (testInfo.instance) {
147138
testInfo.testFunc.apply(testInfo.instance, [doneCallback]);
148139
} else {
149-
var func: any = testInfo.testFunc;
140+
const func: any = testInfo.testFunc;
150141
func(doneCallback);
151142
}
152143
} catch (e) {
@@ -156,17 +147,15 @@ function runAsync(testInfo: TestInfoEntry, recursiveIndex: number, testTimeout?:
156147
setTimeout(checkFinished, 0);
157148
}
158149

159-
// tests : Array<{testFunc: func, testName: string, isTest: boolean, isPassed: boolean, errorMessage: string}>
160-
export var runTests = function (tests: Array<TestInfoEntry>, recursiveIndex) {
150+
export function runTests(tests: Array<TestInfoEntry>, recursiveIndex) {
161151
testsQueue = tests;
152+
153+
for (let i = recursiveIndex; i < testsQueue.length; i++) {
154+
const testEntry = testsQueue[i];
162155

163-
var i;
164-
for (i = recursiveIndex; i < testsQueue.length; i++) {
165-
var testEntry = testsQueue[i];
166156
if (testEntry.testFunc.length > 0) {
167157
return runAsync(testEntry, i);
168-
}
169-
else {
158+
} else {
170159
runTest(testEntry);
171160
}
172161
}
@@ -176,35 +165,31 @@ export function assert(test: any, message?: string) {
176165
if (!test) {
177166
throw new Error(message);
178167
}
179-
};
168+
}
180169

181170
export function assertTrue(test: boolean, message?: string) {
182171
if (test !== true) {
183172
throw new Error(message);
184173
}
185-
};
174+
}
186175

187176
export function assertFalse(test: boolean, message?: string) {
188177
if (test !== false) {
189178
throw new Error(message);
190179
}
191-
};
180+
}
192181

193182
export function assertNotEqual(actual: any, expected: any, message?: string) {
194-
195-
var equals = false;
183+
let equals = false;
196184
if (types.isUndefined(actual) && types.isUndefined(expected)) {
197185
equals = true;
198-
}
199-
else if (!types.isNullOrUndefined(actual) && !types.isNullOrUndefined(expected)) {
186+
} else if (!types.isNullOrUndefined(actual) && !types.isNullOrUndefined(expected)) {
200187
if (types.isFunction(actual.equals)) {
201-
202188
// Use the equals method
203189
if (actual.equals(expected)) {
204190
equals = true;
205191
}
206-
}
207-
else {
192+
} else {
208193
equals = actual === expected;
209194
}
210195
}
@@ -228,7 +213,7 @@ export function assertEqual<T extends { equals?(arg: T): boolean } | any>(actual
228213
else if (actual !== expected) {
229214
throw new Error(`${message} Actual: <${actual}>(${typeof (actual)}). Expected: <${expected}>(${typeof (expected)})`);
230215
}
231-
};
216+
}
232217

233218
/**
234219
* Assert two json like objects are deep equal.
@@ -310,13 +295,13 @@ export function assertNull(actual: any, message?: string) {
310295
if (actual !== null && actual !== undefined) {
311296
throw new Error(message + " Actual: " + actual + " is not null/undefined");
312297
}
313-
};
298+
}
314299

315300
export function assertNotNull(actual: any, message?: string) {
316301
if (actual === null || actual === undefined) {
317302
throw new Error(message + " Actual: " + actual + " is null/undefined");
318303
}
319-
};
304+
}
320305

321306
export function areClose(actual: number, expected: number, delta: number): boolean {
322307
if (isNaN(actual) || Math.abs(actual - expected) > delta) {
@@ -325,26 +310,27 @@ export function areClose(actual: number, expected: number, delta: number): boole
325310

326311
return true;
327312
}
313+
328314
export function assertAreClose(actual: number, expected: number, delta: number, message?: string) {
329315
if (!areClose(actual, expected, delta)) {
330316
throw new Error(message + " Numbers are not close enough. Actual: " + actual + " Expected: " + expected + " Delta: " + delta);
331317
}
332-
};
318+
}
333319

334320
export function arrayAssert(actual: Array<any>, expected: Array<any>, message?: string) {
335321
if (actual.length !== expected.length) {
336322
throw new Error(message + " Actual array length: " + actual.length + " Expected array length: " + expected.length);
337323
}
338-
var i;
339-
for (i = 0; i < actual.length; i++) {
324+
325+
for (let i = 0; i < actual.length; i++) {
340326
if (actual[i] !== expected[i]) {
341327
throw new Error(message + " Actual element at " + i + " is: " + actual[i] + " Expected element is: " + expected[i]);
342328
}
343329
}
344330
}
345331

346332
export function assertThrows(testFunc: () => void, assertMessage?: string, expectedMessage?: string) {
347-
var actualError: Error;
333+
let actualError: Error;
348334
try {
349335
testFunc();
350336
} catch (e) {
@@ -360,29 +346,30 @@ export function assertThrows(testFunc: () => void, assertMessage?: string, expec
360346
}
361347
}
362348

363-
export var wait = function (seconds: number) {
364-
waitUntilReady(function () {
365-
return false;
366-
}, seconds, false);
367-
};
349+
export function wait(seconds: number): void {
350+
waitUntilReady(() => false, seconds, false);
351+
}
368352

369-
export var waitUntilReady = function (isReady: () => boolean, timeoutSec: number = 3, shouldThrow: boolean = true) {
353+
export function waitUntilReady(isReady: () => boolean, timeoutSec: number = 300, shouldThrow: boolean = true) {
370354
if (!isReady) {
371355
return;
372356
}
373357

374358
if (Application.ios) {
375-
const waitTime = 20 / 1000;
376-
var totalWaitTime = 0;
359+
// const waitTime = 1 / 10000;
360+
const timeoutMs = timeoutSec * 1000;
361+
let totalWaitTime = 0;
377362
while (true) {
378-
utils.ios.getter(NSRunLoop, NSRunLoop.currentRunLoop).runUntilDate(<any>NSDate.dateWithTimeIntervalSinceNow(waitTime));
379-
363+
// const nsDate = <any>NSDate.dateWithTimeIntervalSinceNow(waitTime);
364+
const begin = time();
365+
const currentRunLoop = utils.ios.getter(NSRunLoop, NSRunLoop.currentRunLoop);
366+
currentRunLoop.limitDateForMode(currentRunLoop.currentMode);
380367
if (isReady()) {
381368
break;
382369
}
383370

384-
totalWaitTime += waitTime;
385-
if (timeoutSec && totalWaitTime >= timeoutSec) {
371+
totalWaitTime += (time() - begin);
372+
if (totalWaitTime >= timeoutMs) {
386373
if (shouldThrow) {
387374
throw new Error("waitUntilReady Timeout.");
388375
} else {
@@ -393,36 +380,32 @@ export var waitUntilReady = function (isReady: () => boolean, timeoutSec: number
393380
} else if (Application.android) {
394381
doModalAndroid(isReady, timeoutSec, shouldThrow);
395382
}
396-
};
383+
}
397384

398385
// Setup for the Android modal loop implementation
399386
// TODO: If these platform-specific implementations continue to grow, think of per-platform separation (TKUnit.android)
400-
var nextMethod;
401-
var targetField;
402-
var prepared;
387+
let nextMethod;
388+
let targetField;
389+
let prepared;
403390

404-
var prepareModal = function () {
391+
function prepareModal() {
405392
if (prepared) {
406393
return;
407394
}
408395

409-
var clsMsgQueue = java.lang.Class.forName("android.os.MessageQueue");
410-
var clsMsg = java.lang.Class.forName("android.os.Message");
411-
412-
nextMethod;
413-
var methods = clsMsgQueue.getDeclaredMethods();
414-
var i;
415-
for (i = 0; i < methods.length; i++) {
396+
const clsMsgQueue = java.lang.Class.forName("android.os.MessageQueue");
397+
const clsMsg = java.lang.Class.forName("android.os.Message");
398+
const methods = clsMsgQueue.getDeclaredMethods();
399+
for (let i = 0; i < methods.length; i++) {
416400
if (methods[i].getName() === "next") {
417401
nextMethod = methods[i];
418402
nextMethod.setAccessible(true);
419403
break;
420404
}
421405
}
422406

423-
targetField;
424-
var fields = clsMsg.getDeclaredFields();
425-
for (i = 0; i < fields.length; i++) {
407+
const fields = clsMsg.getDeclaredFields();
408+
for (let i = 0; i < fields.length; i++) {
426409
if (fields[i].getName() === "target") {
427410
targetField = fields[i];
428411
targetField.setAccessible(true);
@@ -433,28 +416,28 @@ var prepareModal = function () {
433416
prepared = true;
434417
}
435418

436-
var doModalAndroid = function (quitLoop: () => boolean, timeoutSec: number, shouldThrow: boolean = true) {
419+
function doModalAndroid(quitLoop: () => boolean, timeoutSec: number, shouldThrow: boolean = true) {
437420
if (!quitLoop) {
438421
return;
439422
}
440423

441424
prepareModal();
442425

443-
var queue = android.os.Looper.myQueue();
426+
const queue = android.os.Looper.myQueue();
444427

445428
let quit = false;
446429
let timeout = false;
447-
timer.setTimeout(function () {
430+
timer.setTimeout(() => {
448431
quit = true;
449432
timeout = true;
450433
}, timeoutSec * 1000);
451434

452-
var msg;
435+
let msg;
453436

454437
while (!quit) {
455438
msg = nextMethod.invoke(queue, null);
456439
if (msg) {
457-
var target = targetField.get(msg);
440+
const target = targetField.get(msg);
458441
if (!target) {
459442
quit = true;
460443
} else {
@@ -474,4 +457,4 @@ var doModalAndroid = function (quitLoop: () => boolean, timeoutSec: number, shou
474457
quit = true;
475458
}
476459
}
477-
};
460+
}

0 commit comments

Comments
 (0)