Skip to content

Commit f0119a0

Browse files
authored
fix(location-strategy): find the correct outlet when navigating back and forward (#1404)
* feat(frame-service): extend FrameService to provide reusable frames FrameServices should be responsible for delivering the correct topmost frame too * fix(location-strategy): find the correct outlet when navigating back and forward * chore(modal-navigation-ng): add modal view with frame navigation tests * chore(modal-navigation-ng): add named p-r-o as root tests * chore(location-strategy): address PR review issues and comments
1 parent 32dcb52 commit f0119a0

20 files changed

+700
-42
lines changed

Diff for: e2e/modal-navigation-ng/app/app.css

+3
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ of writing your own CSS rules. For a full list of class names in the theme
1010
refer to http://docs.nativescript.org/ui/theme.
1111
*/
1212
@import '~nativescript-theme-core/css/core.light.css';
13+
Button {
14+
font-size: 10px;
15+
}

Diff for: e2e/modal-navigation-ng/app/app.module.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core";
22
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
33
import { AppRoutingModule } from "./app.routing";
44
import { AppComponent } from "./app.component";
5+
import { NamedRouterComponent } from "./named-router.component";
56
import { TabComponent } from "./tab.component";
67
import { LayoutComponent } from "./layout.component";
78

@@ -29,16 +30,18 @@ traceEnable();
2930
AppRoutingModule
3031
],
3132
entryComponents: [
32-
AppComponent,
33-
TabComponent,
34-
LayoutComponent,
35-
ModalRouterComponent,
36-
NestedModalComponent,
37-
ModalComponent,
33+
AppComponent,
34+
NamedRouterComponent,
35+
TabComponent,
36+
LayoutComponent,
37+
ModalRouterComponent,
38+
NestedModalComponent,
39+
ModalComponent,
3840
ModalViewComponent
3941
],
4042
declarations: [
4143
AppComponent,
44+
NamedRouterComponent,
4245
TabComponent,
4346
LayoutComponent,
4447
HomeComponent,
@@ -75,8 +78,9 @@ export class AppModule {
7578
static bootstrapRootComponent() {
7679
const options = {
7780
'page-router': AppComponent,
81+
'named-page-router': NamedRouterComponent,
7882
'tab': TabComponent,
79-
'layout': LayoutComponent
83+
'layout': LayoutComponent
8084
};
8185

8286
const component = options[AppModule.root];

Diff for: e2e/modal-navigation-ng/app/app.routing.ts

+30
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,34 @@ const routes: Routes = [
4040
}
4141
];
4242

43+
const namedOutletRoutes: Routes = [
44+
{ path: "", redirectTo: "/(namedRouter:home)", pathMatch: "full" },
45+
{
46+
path: "home", component: HomeComponent, outlet: "namedRouter", children: [
47+
{
48+
path: "modal", component: ModalComponent, children: [
49+
{ path: "nested-frame-modal", component: NestedModalComponent }]
50+
},
51+
{ path: "modal-second", component: ModalSecondComponent }
52+
]
53+
},
54+
{
55+
path: "second", outlet: "namedRouter", component: SecondComponent, children: [
56+
{
57+
path: "modal", component: ModalComponent, children: [
58+
{ path: "nested-frame-modal", component: NestedModalComponent }]
59+
},
60+
{ path: "modal-second", component: ModalSecondComponent }
61+
]
62+
},
63+
{
64+
path: "modal-shared", component: ModalViewContentComponent, outlet: "modalOutlet"
65+
},
66+
{
67+
path: "modal-shared-second-host", outlet: "namedRouter", component: ModalSharedSecondComponent
68+
}
69+
];
70+
4371
const routesTab: Routes = [
4472
{ path: "", redirectTo: "/home(secondOutlet:second)", pathMatch: "full" },
4573
{
@@ -96,6 +124,8 @@ export class AppRoutingModule {
96124
this.router.resetConfig(routes);
97125
} else if (AppModule.root === "layout") {
98126
this.router.resetConfig(routesLayout);
127+
} else if (AppModule.root === "named-page-router") {
128+
this.router.resetConfig(namedOutletRoutes);
99129
} else {
100130
this.router.resetConfig(routesTab);
101131
}

Diff for: e2e/modal-navigation-ng/app/home/home.component.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<ActionBar class="action-bar">
2-
<Label class="action-bar-title" text="Home"></Label>
2+
<Label class="action-bar-title" text="Home Component"></Label>
33
</ActionBar>
44

5-
<StackLayout>
5+
<WrapLayout>
66
<Button text="Show Modal Without Frame" (tap)="onModalNoFrame()"></Button>
77
<Button text="Show Modal Page With Frame" (tap)="onModalFrame()"></Button>
88
<Button text="Navigate To Second Page" (tap)="onNavigateSecond()"></Button>
9+
<Button text="Reset Named Frame Root View" (tap)="onNamedFrameRootViewReset()"></Button>
910
<Button text="Reset Frame Root View" (tap)="onFrameRootViewReset()"></Button>
1011
<Button text="Reset Tab Root View" (tap)="onTabRootViewReset()"></Button>
1112
<Button text="Reset Layout Root View" (tap)="onLayoutRootViewReset()"></Button>
1213
<Button text="Show Dialog" (tap)="onShowDialog()"></Button>
1314

1415
<Button text="show shared modal" (tap)="onRootModalTap()"></Button>
1516
<Button text="go to second (to open shared modal)" [nsRouterLink]="['/modal-shared-second-host']"></Button>
16-
<Label text="home component" verticalAlignment="bottom"></Label>
17-
</StackLayout>
17+
</WrapLayout>

Diff for: e2e/modal-navigation-ng/app/home/home.component.ts

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ export class HomeComponent {
6161
AppModule.platformRef._livesync();
6262
}
6363

64+
onNamedFrameRootViewReset() {
65+
AppModule.root = "named-page-router";
66+
AppModule.platformRef._livesync();
67+
}
68+
6469
onTabRootViewReset() {
6570
AppModule.root = "tab";
6671
AppModule.platformRef._livesync();

Diff for: e2e/modal-navigation-ng/app/layout.component.html

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
<StackLayout>
2-
<Label text="Home" horizontalAlignment="center"></Label>
1+
<WrapLayout>
2+
<Label text="Home Component" horizontalAlignment="center"></Label>
33
<Button text="Show Modal Without Frame" (tap)="onModalNoFrame()"></Button>
44
<Button text="Show Modal Page With Frame" (tap)="onModalFrame()"></Button>
5+
<Button text="Reset Named Frame Root View" (tap)="onNamedFrameRootViewReset()"></Button>
56
<Button text="Reset Frame Root View" (tap)="onFrameRootViewReset()"></Button>
67
<Button text="Reset Tab Root View" (tap)="onTabRootViewReset()"></Button>
78
<Button text="Reset Layout Root View" (tap)="onLayoutRootViewReset()"></Button>
89
<Button text="Show Dialog" (tap)="onShowDialog()"></Button>
9-
</StackLayout>
10+
</WrapLayout>

Diff for: e2e/modal-navigation-ng/app/layout.component.ts

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ export class LayoutComponent {
6767
AppModule.platformRef._livesync();
6868
}
6969

70+
onNamedFrameRootViewReset() {
71+
AppModule.root = "named-page-router";
72+
AppModule.platformRef._livesync();
73+
}
74+
7075
onTabRootViewReset() {
7176
AppModule.root = "tab";
7277
AppModule.platformRef._livesync();
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<page-router-outlet name="namedRouter"></page-router-outlet>
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Component, ViewContainerRef } from "@angular/core";
2+
import { Router, NavigationEnd } from "@angular/router";
3+
import { NSLocationStrategy } from "nativescript-angular/router/ns-location-strategy";
4+
5+
import { ViewContainerRefService } from "./shared/ViewContainerRefService";
6+
7+
@Component({
8+
selector: "named-router",
9+
templateUrl: "named-router.component.html",
10+
})
11+
12+
export class NamedRouterComponent {
13+
constructor(
14+
router: Router,
15+
location: NSLocationStrategy,
16+
private _vcRef: ViewContainerRef,
17+
private _viewContainerRefService: ViewContainerRefService) {
18+
router.events.subscribe(e => {
19+
if (e instanceof NavigationEnd) {
20+
console.log("[ROUTER]: " + e.toString());
21+
console.log(location.toString());
22+
}
23+
});
24+
25+
this._viewContainerRefService.root = this._vcRef;
26+
}
27+
}

Diff for: e2e/modal-navigation-ng/e2e/modal-frame.e2e-spec.ts

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { AppiumDriver, createDriver } from "nativescript-dev-appium";
2+
import { Screen } from "./screen"
3+
import {
4+
roots,
5+
modalFrameBackground,
6+
testSecondPageBackground,
7+
testSecondPageClose,
8+
testNestedModalFrameBackground,
9+
testNestedModalPageBackground,
10+
testDialogBackground
11+
} from "./shared.e2e-spec"
12+
13+
describe("modal-frame:", () => {
14+
15+
let driver: AppiumDriver;
16+
let screen: Screen;
17+
18+
before(async () => {
19+
driver = await createDriver();
20+
screen = new Screen(driver);
21+
});
22+
23+
roots.forEach(root => {
24+
describe(`${root} modal frame background scenarios:`, () => {
25+
26+
before(async () => {
27+
await screen[root]();
28+
});
29+
30+
beforeEach(async function () {
31+
await screen.loadModalFrame();
32+
});
33+
34+
afterEach(async function () {
35+
if (this.currentTest.state === "failed") {
36+
await driver.logPageSource(this.currentTest.title);
37+
await driver.logScreenshot(this.currentTest.title);
38+
await driver.resetApp();
39+
await screen[root]();
40+
}
41+
});
42+
43+
after(async () => {
44+
await screen.closeModal();
45+
await screen.loadedHome();
46+
});
47+
48+
it("should show dialog confirm, run in background", async () => {
49+
await testDialogBackground(driver, screen);
50+
});
51+
52+
it("should run modal page with frame in background", async () => {
53+
await modalFrameBackground(driver, screen);
54+
});
55+
56+
it("should navigate to second page, run in background, go back", async () => {
57+
await testSecondPageBackground(driver, screen);
58+
});
59+
60+
it("should show nested modal page with frame, run in background, close", async () => {
61+
await testNestedModalFrameBackground(driver, screen);
62+
});
63+
64+
it("should show nested modal page, run in background, close", async () => {
65+
await testNestedModalPageBackground(driver, screen);
66+
});
67+
68+
it("should navigate to second page, close", async () => {
69+
await testSecondPageClose(driver, screen);
70+
});
71+
72+
it("should navigate to second page, run in background, go back", async () => {
73+
await testSecondPageBackground(driver, screen);
74+
});
75+
});
76+
});
77+
});

Diff for: e2e/modal-navigation-ng/e2e/modal-layout.e2e-spec.ts

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { AppiumDriver, createDriver } from "nativescript-dev-appium";
2+
import { Screen } from "./screen"
3+
import {
4+
roots,
5+
modalFrameBackground,
6+
testSecondPageBackground,
7+
testSecondPageClose,
8+
testNestedModalFrameBackground,
9+
testNestedModalPageBackground,
10+
testDialogBackground,
11+
} from "./shared.e2e-spec"
12+
13+
describe("modal-layout:", () => {
14+
15+
let driver: AppiumDriver;
16+
let screen: Screen;
17+
18+
before(async () => {
19+
driver = await createDriver();
20+
screen = new Screen(driver);
21+
});
22+
23+
roots.forEach(root => {
24+
describe(`${root} modal no frame background scenarios:`, () => {
25+
26+
before(async () => {
27+
await screen[root]();
28+
});
29+
30+
beforeEach(async function () {
31+
await screen.loadModalNoFrame();
32+
});
33+
34+
afterEach(async function () {
35+
if (this.currentTest.state === "failed") {
36+
await driver.logPageSource(this.currentTest.title);
37+
await driver.logScreenshot(this.currentTest.title);
38+
await driver.resetApp();
39+
await screen[root]();
40+
}
41+
});
42+
43+
after(async () => {
44+
await screen.closeModal();
45+
await screen.loadedHome();
46+
});
47+
48+
it("should show dialog confirm inside modal view with no frame, run in background", async () => {
49+
await testDialogBackground(driver, screen, false);
50+
});
51+
});
52+
});
53+
});

Diff for: e2e/modal-navigation-ng/e2e/modal.shared.e2e-spec.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { AppiumDriver, createDriver, SearchOptions } from "nativescript-dev-appium";
22
import { assert } from "chai";
33

4+
const homeComponent = "Home Component";
5+
46
describe("Shared modal from home and back", () => {
57
let driver: AppiumDriver;
68

@@ -22,7 +24,7 @@ describe("Shared modal from home and back", () => {
2224
});
2325

2426
it ("should find home component", async () => {
25-
await assertComponent(driver, "home component");
27+
await assertComponent(driver, homeComponent);
2628
});
2729

2830
it("should open/close shared modal from home component", async () => {
@@ -31,7 +33,7 @@ describe("Shared modal from home and back", () => {
3133
});
3234

3335
it ("should find home component again", async () => {
34-
await assertComponent(driver, "home component");
36+
await assertComponent(driver, homeComponent);
3537
});
3638
});
3739

@@ -56,7 +58,7 @@ describe("Shared modal from second and back", () => {
5658
});
5759

5860
it ("should find home component", async () => {
59-
await assertComponent(driver, "home component");
61+
await assertComponent(driver, homeComponent);
6062
});
6163

6264
it ("should navigate to second component", async() => {
@@ -98,7 +100,7 @@ describe("Shared modal from different components", () => {
98100
});
99101

100102
it ("should find home component", async () => {
101-
await assertComponent(driver, "home component");
103+
await assertComponent(driver, homeComponent);
102104
});
103105

104106
it("should open/close shared modal from home component", async () => {
@@ -107,7 +109,7 @@ describe("Shared modal from different components", () => {
107109
});
108110

109111
it ("should find home component again", async () => {
110-
await assertComponent(driver, "home component");
112+
await assertComponent(driver, homeComponent);
111113
});
112114

113115
it ("should navigate to second component", async() => {
@@ -129,7 +131,7 @@ describe("Shared modal from different components", () => {
129131

130132
it ("should navigate back to home component", async () => {
131133
await goBack(driver);
132-
await assertComponent(driver, "home component");
134+
await assertComponent(driver, homeComponent);
133135
});
134136

135137
it("should open/close shared modal from home component after manipulations with second", async () => {
@@ -138,7 +140,7 @@ describe("Shared modal from different components", () => {
138140
});
139141

140142
it ("should find home component again", async () => {
141-
await assertComponent(driver, "home component");
143+
await assertComponent(driver, homeComponent);
142144
});
143145
});
144146

0 commit comments

Comments
 (0)