feat(hmr): preserve navigation history on applying changes (#7146)

This commit is contained in:
Vasil Chimev
2019-04-23 17:47:29 +03:00
committed by GitHub
parent 4e56c89f7d
commit d35e14ed0f
23 changed files with 414 additions and 168 deletions

View File

@@ -0,0 +1,5 @@
<Page loaded="onLoaded">
<StackLayout>
<Button id="button" text="button"></Button>
</StackLayout>
</Page>

View File

@@ -0,0 +1,3 @@
export function onLoaded() {
console.log("Button page loaded!");
}

View File

@@ -0,0 +1,5 @@
<Page loaded="onLoaded">
<StackLayout>
<Button id="button" text="button"></Button>
</StackLayout>
</Page>

View File

@@ -0,0 +1,3 @@
export function onLoaded() {
console.log("Label page loaded!");
}

View File

@@ -0,0 +1,5 @@
<Page loaded="onLoaded">
<StackLayout>
<Label id="label" text="label"></Label>
</StackLayout>
</Page>

View File

@@ -1,37 +1,29 @@
import * as app from "tns-core-modules/application/application";
import * as frame from "tns-core-modules/ui/frame";
import * as helper from "../ui/helper";
import * as TKUnit from "../TKUnit";
import * as app from "tns-core-modules/application/application";
import * as frame from "tns-core-modules/ui/frame";
import { Color } from "tns-core-modules/color";
import { parse } from "tns-core-modules/ui/builder";
import { isAndroid } from "tns-core-modules/platform";
import { createViewFromEntry } from "tns-core-modules/ui/builder";
import { Page } from "tns-core-modules/ui/page";
import { Frame } from "tns-core-modules/ui/frame";
const appCssFileName = "./app/application.css";
const appNewCssFileName = "./app/app-new.css";
const appNewScssFileName = "./app/app-new.scss";
const appJsFileName = "./app/app.js";
const appTsFileName = "./app/app.ts";
const mainPageCssFileName = "./app/main-page.css";
const mainPageHtmlFileName = "./app/main-page.html";
const mainPageXmlFileName = "./app/main-page.xml";
const buttonCssFileName = "./app/button-page.css";
const buttonPageModuleName = "livesync/livesync-button-page";
const buttonHtmlPageFileName = "./livesync/livesync-button-page.html";
const buttonXmlPageFileName = "./livesync/livesync-button-page.xml";
const buttonJsPageFileName = "./livesync/livesync-button-page.js";
const buttonTsPageFileName = "./livesync/livesync-button-page.ts";
const labelPageModuleName = "livesync/livesync-label-page";
const black = new Color("black");
const green = new Color("green");
const mainPageTemplate = `
<Page>
<StackLayout>
<Label id="label" text="label"></Label>
</StackLayout>
</Page>`;
const pageTemplate = `
<Page>
<StackLayout>
<Button id="button" text="button"></Button>
</StackLayout>
</Page>`;
export function test_onLiveSync_ModuleContext_AppStyle_AppNewCss() {
_test_onLiveSync_ModuleContext_AppStyle(appNewCssFileName);
}
@@ -48,29 +40,29 @@ export function test_onLiveSync_ModuleContext_ModuleUndefined() {
_test_onLiveSync_ModuleContext({ type: "script", path: undefined });
}
export function test_onLiveSync_ModuleContext_Script_AppJs() {
_test_onLiveSync_ModuleContext({ type: "script", path: appJsFileName });
export function test_onLiveSync_ModuleContext_Script_JsFile() {
_test_onLiveSync_ModuleReplace({ type: "script", path: buttonJsPageFileName });
}
export function test_onLiveSync_ModuleContext_Script_AppTs() {
_test_onLiveSync_ModuleContext({ type: "script", path: appTsFileName });
export function test_onLiveSync_ModuleContext_Script_TsFile() {
_test_onLiveSync_ModuleReplace({ type: "script", path: buttonTsPageFileName });
}
export function test_onLiveSync_ModuleContext_Style_MainPageCss() {
_test_onLiveSync_ModuleContext_TypeStyle({ type: "style", path: mainPageCssFileName });
export function test_onLiveSync_ModuleContext_Style_CssFile() {
_test_onLiveSync_ModuleContext_TypeStyle({ type: "style", path: buttonCssFileName });
}
export function test_onLiveSync_ModuleContext_Markup_MainPageHtml() {
_test_onLiveSync_ModuleContext({ type: "markup", path: mainPageHtmlFileName });
export function test_onLiveSync_ModuleContext_Markup_HtmlFile() {
_test_onLiveSync_ModuleReplace({ type: "markup", path: buttonHtmlPageFileName });
}
export function test_onLiveSync_ModuleContext_Markup_MainPageXml() {
_test_onLiveSync_ModuleContext({ type: "markup", path: mainPageXmlFileName });
export function test_onLiveSync_ModuleContext_Markup_XmlFile() {
_test_onLiveSync_ModuleReplace({ type: "markup", path: buttonXmlPageFileName });
}
export function setUpModule() {
const mainPage = <Page>parse(mainPageTemplate);
helper.navigate(() => mainPage);
export function setUp() {
const labelPage = <Page>createViewFromEntry(({ moduleName: labelPageModuleName }));
helper.navigate(() => labelPage);
}
export function tearDown() {
@@ -79,32 +71,29 @@ export function tearDown() {
function _test_onLiveSync_ModuleContext_AppStyle(styleFileName: string) {
const pageBeforeNavigation = helper.getCurrentPage();
const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName }));
helper.navigateWithHistory(() => buttonPage);
const page = <Page>parse(pageTemplate);
helper.navigateWithHistory(() => page);
app.setCssFileName(styleFileName);
const pageBeforeLiveSync = helper.getCurrentPage();
global.__onLiveSync({ type: "style", path: styleFileName });
const pageAfterLiveSync = helper.getCurrentPage();
TKUnit.waitUntilReady(() => pageAfterLiveSync.getViewById("button").style.color.toString() === green.toString());
TKUnit.assertTrue(pageAfterLiveSync.frame.canGoBack(), "App styles NOT applied - livesync navigation executed!");
TKUnit.assertEqual(pageAfterLiveSync, pageBeforeLiveSync, "Pages are different - livesync navigation executed!");
TKUnit.assertTrue(pageAfterLiveSync._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version NOT applied!");
TKUnit.assertTrue(pageAfterLiveSync.frame.canGoBack(), "Can NOT go back!");
TKUnit.assertEqual(pageAfterLiveSync, pageBeforeLiveSync, "Pages are different!");
TKUnit.assertTrue(pageAfterLiveSync._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version is NOT applied!");
helper.goBack();
const pageAfterNavigationBack = helper.getCurrentPage();
TKUnit.assertEqual(pageAfterNavigationBack.getViewById("label").style.color, green, "App styles NOT applied on back navigation!");
TKUnit.assertEqual(pageBeforeNavigation, pageAfterNavigationBack, "Pages are different - livesync navigation executed!");
TKUnit.assertEqual(pageBeforeNavigation, pageAfterNavigationBack, "Pages are different");
TKUnit.assertTrue(pageAfterNavigationBack._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version is NOT applied!");
}
function _test_onLiveSync_ModuleContext(context: { type, path }) {
const page = <Page>parse(pageTemplate);
helper.navigateWithHistory(() => page);
const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName }));
helper.navigateWithHistory(() => buttonPage);
global.__onLiveSync({ type: context.type, path: context.path });
TKUnit.waitUntilReady(() => !!frame.topmost());
@@ -113,27 +102,53 @@ function _test_onLiveSync_ModuleContext(context: { type, path }) {
TKUnit.assertTrue(topmostFrame.currentPage.getViewById("label").isLoaded);
}
function _test_onLiveSync_ModuleReplace(context: { type, path }) {
const pageBeforeNavigation = helper.getCurrentPage();
const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName }));
helper.navigateWithHistory(() => buttonPage);
global.__onLiveSync({ type: context.type, path: context.path });
const topmostFrame = frame.topmost();
waitUntilLivesyncComplete(topmostFrame);
TKUnit.assertTrue(topmostFrame.currentPage.getViewById("button").isLoaded, "Button page is NOT loaded!");
TKUnit.assertEqual(topmostFrame.backStack.length, 1, "Backstack is clean!");
TKUnit.assertTrue(topmostFrame.canGoBack(), "Can NOT go back!");
helper.goBack();
const pageAfterBackNavigation = helper.getCurrentPage();
TKUnit.assertTrue(topmostFrame.currentPage.getViewById("label").isLoaded, "Label page is NOT loaded!");
TKUnit.assertEqual(topmostFrame.backStack.length, 0, "Backstack is NOT clean!");
TKUnit.assertEqual(pageBeforeNavigation, pageAfterBackNavigation, "Pages are different!");
}
function _test_onLiveSync_ModuleContext_TypeStyle(context: { type, path }) {
const pageBeforeNavigation = helper.getCurrentPage();
const page = <Page>parse(pageTemplate);
helper.navigateWithHistory(() => page);
const buttonPage = <Page>createViewFromEntry(({ moduleName: buttonPageModuleName }));
helper.navigateWithHistory(() => buttonPage);
const pageBeforeLiveSync = helper.getCurrentPage();
pageBeforeLiveSync._moduleName = "main-page";
pageBeforeLiveSync._moduleName = "button-page";
global.__onLiveSync({ type: context.type, path: context.path });
const topmostFrame = frame.topmost();
waitUntilLivesyncComplete(topmostFrame);
const pageAfterLiveSync = helper.getCurrentPage();
TKUnit.waitUntilReady(() => pageAfterLiveSync.getViewById("button").style.color.toString() === green.toString());
TKUnit.assertTrue(pageAfterLiveSync.frame.canGoBack(), "Local styles NOT applied - livesync navigation executed!");
TKUnit.assertEqual(pageAfterLiveSync, pageBeforeLiveSync, "Pages are different - livesync navigation executed!");
TKUnit.assertTrue(pageAfterLiveSync._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version NOT applied!");
TKUnit.assertTrue(pageAfterLiveSync.frame.canGoBack(), "Can NOT go back!");
TKUnit.assertEqual(topmostFrame.backStack.length, 1, "Backstack is clean!");
TKUnit.assertTrue(pageAfterLiveSync._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version is NOT applied!");
helper.goBack();
const pageAfterNavigationBack = helper.getCurrentPage();
TKUnit.assertEqual(pageAfterNavigationBack.getViewById("label").style.color, black, "App styles applied on back navigation!");
TKUnit.assertEqual(pageBeforeNavigation, pageAfterNavigationBack, "Pages are different - livesync navigation executed!");
TKUnit.assertEqual(pageBeforeNavigation, pageAfterNavigationBack, "Pages are different!");
TKUnit.assertTrue(pageAfterNavigationBack._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version is NOT applied!");
}
}
function waitUntilLivesyncComplete(frame: Frame) {
if (isAndroid) {
TKUnit.waitUntilReady(() => frame._executingEntry === null);
} else {
TKUnit.waitUntilReady(() => frame.currentPage.isLoaded);
}
}