mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
merge release-6.2.7
Release 6.2.7
This commit is contained in:
@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.2.7](https://github.com/ionic-team/ionic/compare/v6.2.6...v6.2.7) (2022-09-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** nav controller can pop views after leaving tabs outlet ([#25690](https://github.com/ionic-team/ionic/issues/25690)) ([725b13f](https://github.com/ionic-team/ionic/commit/725b13fa60775dc9f9c3491cb545c70a5a9162eb)), closes [#18593](https://github.com/ionic-team/ionic/issues/18593)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.6](https://github.com/ionic-team/ionic/compare/v6.2.5...v6.2.6) (2022-09-07)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
18
angular/package-lock.json
generated
18
angular/package-lock.json
generated
@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.6",
|
||||
"version": "6.2.7",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.6",
|
||||
"version": "6.2.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.6",
|
||||
"@ionic/core": "^6.2.7",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
@ -1023,9 +1023,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "6.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.6.tgz",
|
||||
"integrity": "sha512-79VGvJ33YlCX/rhepfamL2YUQnqu3cruKMo0yFbrhyJWzoF3GTT/p371FHu1e+SdIZsMu/xcn+dkcTxQjEEcdA==",
|
||||
"version": "6.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.7.tgz",
|
||||
"integrity": "sha512-pQWcIqr5zfCX5De/MQ9kFs+nhaPCr8HIh5QjmydxvmlLv6WU4vlny/Mg0y1+JwLE0qxPD0T9sMykawWH9e3y5Q==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.17.4",
|
||||
"ionicons": "^6.0.3",
|
||||
@ -7951,9 +7951,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "6.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.6.tgz",
|
||||
"integrity": "sha512-79VGvJ33YlCX/rhepfamL2YUQnqu3cruKMo0yFbrhyJWzoF3GTT/p371FHu1e+SdIZsMu/xcn+dkcTxQjEEcdA==",
|
||||
"version": "6.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.7.tgz",
|
||||
"integrity": "sha512-pQWcIqr5zfCX5De/MQ9kFs+nhaPCr8HIh5QjmydxvmlLv6WU4vlny/Mg0y1+JwLE0qxPD0T9sMykawWH9e3y5Q==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.17.4",
|
||||
"ionicons": "^6.0.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.6",
|
||||
"version": "6.2.7",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@ -44,7 +44,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.6",
|
||||
"@ionic/core": "^6.2.7",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
@ -308,8 +308,19 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
this.activatedView = enteringView;
|
||||
|
||||
/**
|
||||
* The top outlet is set prior to the entering view's transition completing,
|
||||
* so that when we have nested outlets (e.g. ion-tabs inside an ion-router-outlet),
|
||||
* the tabs outlet will be assigned as the top outlet when a view inside tabs is
|
||||
* activated.
|
||||
*
|
||||
* In this scenario, activeWith is called for both the tabs and the root router outlet.
|
||||
* To avoid a race condition, we assign the top outlet synchronously.
|
||||
*/
|
||||
this.navCtrl.setTopOutlet(this);
|
||||
|
||||
this.stackCtrl.setActive(enteringView).then((data) => {
|
||||
this.navCtrl.setTopOutlet(this);
|
||||
this.activateEvents.emit(cmpRef.instance);
|
||||
this.stackEvents.emit(data);
|
||||
});
|
||||
|
@ -2,6 +2,26 @@
|
||||
|
||||
Ionic Framework supports multiple versions of Angular. As a result, we need to verify that Ionic works correctly with each of these Angular versions.
|
||||
|
||||
## Application Cache
|
||||
|
||||
Angular CLI creates a cache of several files on disk by default in the `.angular` directory. This decreases the time taken to build the test application. When testing changes by directly modifying Ionic's source code in `node_modules`, you may need to manually clear the `.angular` cache and restart the local server every time you make a change. As a result, it may be desirable to disable the `.angular` cache while making changes to the code.
|
||||
|
||||
See https://angular.io/cli/cache for more information.
|
||||
|
||||
### Disable Cache
|
||||
|
||||
```
|
||||
ng cache disable
|
||||
```
|
||||
|
||||
> Note: You may need to manually remove the `.angular` directory once after running this command.
|
||||
|
||||
### Enable Cache
|
||||
|
||||
```
|
||||
ng cache enable
|
||||
```
|
||||
|
||||
## Test App Build Structure
|
||||
|
||||
Unlike other test applications, these test apps are broken up into multiple directories. These directories are then combined to create a single application. This allows us to share common application code, tests, etc so that each app is being tested the same way. Below details the different pieces that help create a single test application.
|
||||
|
@ -97,15 +97,27 @@ describe('Tabs', () => {
|
||||
it('should navigate deep then go home', () => {
|
||||
const tab = getSelectedTab();
|
||||
tab.find('#goto-tab1-page2').click();
|
||||
cy.ionPageVisible('app-tabs-tab1-nested');
|
||||
cy.ionPageHidden('app-tabs-tab1');
|
||||
|
||||
testTabTitle('Tab 1 - Page 2 (1)');
|
||||
|
||||
cy.get('#goto-next').click();
|
||||
cy.ionPageVisible('app-tabs-tab1-nested:last-of-type');
|
||||
cy.ionPageHidden('app-tabs-tab1-nested:first-of-type');
|
||||
|
||||
testTabTitle('Tab 1 - Page 2 (2)');
|
||||
|
||||
cy.get('#tab-button-contact').click();
|
||||
cy.ionPageVisible('app-tabs-tab2');
|
||||
cy.ionPageHidden('app-tabs-tab1-nested:last-of-type');
|
||||
|
||||
testTabTitle('Tab 2 - Page 1');
|
||||
|
||||
cy.get('#tab-button-account').click();
|
||||
cy.ionPageVisible('app-tabs-tab1-nested:last-of-type');
|
||||
cy.ionPageHidden('app-tabs-tab2');
|
||||
|
||||
testTabTitle('Tab 1 - Page 2 (2)');
|
||||
cy.testStack('ion-tabs ion-router-outlet', [
|
||||
'app-tabs-tab1',
|
||||
@ -115,6 +127,16 @@ describe('Tabs', () => {
|
||||
]);
|
||||
|
||||
cy.get('#tab-button-account').click();
|
||||
|
||||
/**
|
||||
* Wait for the leaving view to
|
||||
* be unmounted otherwise testTabTitle
|
||||
* may get the leaving view before it
|
||||
* is unmounted.
|
||||
*/
|
||||
cy.ionPageVisible('app-tabs-tab1');
|
||||
cy.ionPageDoesNotExist('app-tabs-tab1-nested');
|
||||
|
||||
testTabTitle('Tab 1 - Page 1');
|
||||
cy.testStack('ion-tabs ion-router-outlet', [
|
||||
'app-tabs-tab1',
|
||||
@ -225,24 +247,113 @@ describe('Tabs', () => {
|
||||
it('should navigate deep then go home and preserve navigation extras', () => {
|
||||
let tab = getSelectedTab();
|
||||
tab.find('#goto-tab1-page2').click();
|
||||
cy.ionPageVisible('app-tabs-tab1-nested');
|
||||
cy.ionPageHidden('app-tabs-tab1');
|
||||
|
||||
tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||
|
||||
tab.find('#goto-next').click();
|
||||
cy.ionPageVisible('app-tabs-tab1-nested:last-of-type');
|
||||
cy.ionPageHidden('app-tabs-tab1-nested:first-of-type');
|
||||
|
||||
testTabTitle('Tab 1 - Page 2 (2)');
|
||||
|
||||
cy.ionTabClick('Tab Two');
|
||||
cy.ionPageVisible('app-tabs-tab2');
|
||||
cy.ionPageHidden('app-tabs-tab1-nested:last-of-type');
|
||||
|
||||
testTabTitle('Tab 2 - Page 1');
|
||||
|
||||
cy.ionTabClick('Tab One');
|
||||
cy.ionPageVisible('app-tabs-tab1-nested:last-of-type');
|
||||
cy.ionPageHidden('app-tabs-tab2');
|
||||
|
||||
testTabTitle('Tab 1 - Page 2 (2)');
|
||||
|
||||
cy.ionTabClick('Tab One');
|
||||
/**
|
||||
* Wait for the leaving view to
|
||||
* be unmounted otherwise testTabTitle
|
||||
* may get the leaving view before it
|
||||
* is unmounted.
|
||||
*/
|
||||
cy.ionPageVisible('app-tabs-tab1');
|
||||
cy.ionPageDoesNotExist('app-tabs-tab1-nested');
|
||||
|
||||
testTabTitle('Tab 1 - Page 1');
|
||||
|
||||
testUrlContains(rootUrl);
|
||||
});
|
||||
})
|
||||
|
||||
describe('entry url - /tabs/account', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/tabs/account');
|
||||
});
|
||||
it('should pop to previous view when leaving tabs outlet', () => {
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');
|
||||
|
||||
cy.get('#goto-tab1-page2').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');
|
||||
|
||||
cy.get('#goto-global').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Global Page');
|
||||
|
||||
cy.get('#goto-prev-pop').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');
|
||||
|
||||
cy.get('#goto-prev').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');
|
||||
|
||||
/**
|
||||
* Verifies that when entering the tabs outlet directly,
|
||||
* the navController.pop() method does not pop the previous view,
|
||||
* when you are at the root of the tabs outlet.
|
||||
*/
|
||||
cy.get('#goto-previous-page').click();
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('entry url - /', () => {
|
||||
it('should pop to the root outlet from the tabs outlet', () => {
|
||||
cy.visit('/');
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Test App');
|
||||
|
||||
cy.get('ion-item').contains('Tabs test').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');
|
||||
|
||||
cy.get('#goto-tab1-page2').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');
|
||||
|
||||
cy.get('#goto-global').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Global Page');
|
||||
|
||||
cy.get('#goto-prev-pop').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');
|
||||
|
||||
cy.get('#goto-prev').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');
|
||||
|
||||
cy.get('#goto-previous-page').click();
|
||||
|
||||
cy.get('ion-title').should('contain.text', 'Test App');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('entry url - /tabs/account/nested/1', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/tabs/account/nested/1');
|
||||
|
@ -55,6 +55,10 @@ const routes: Routes = [
|
||||
path: 'tabs',
|
||||
loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
|
||||
},
|
||||
{
|
||||
path: 'tabs-global',
|
||||
loadChildren: () => import('./tabs-global/tabs-global.module').then(m => m.TabsGlobalModule)
|
||||
},
|
||||
{
|
||||
path: 'nested-outlet',
|
||||
component: NestedOutletComponent,
|
||||
@ -68,7 +72,7 @@ const routes: Routes = [
|
||||
component: NestedOutletPage2Component
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -0,0 +1,16 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { TabsGlobalComponent } from "./tabs-global.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: TabsGlobalComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabsGlobalRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
|
||||
<ion-title>
|
||||
Global Page
|
||||
</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-content>
|
||||
<ion-button id="goto-prev-pop" (click)="navCtrl.pop()">Go To Previous</ion-button>
|
||||
</ion-content>
|
||||
</ion-content>
|
@ -0,0 +1,17 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { NavController } from "@ionic/angular";
|
||||
|
||||
/**
|
||||
* This component is used in conjunction with a tabs router-outlet,
|
||||
* to validate the behavior of different routing APIs (e.g. NavController)
|
||||
* when leaving and re-entering a router-outlet.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-tabs-global',
|
||||
templateUrl: 'tabs-global.component.html'
|
||||
})
|
||||
export class TabsGlobalComponent {
|
||||
|
||||
constructor(public navCtrl: NavController) { }
|
||||
|
||||
}
|
13
angular/test/base/src/app/tabs-global/tabs-global.module.ts
Normal file
13
angular/test/base/src/app/tabs-global/tabs-global.module.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
import { TabsGlobalRoutingModule } from "./tabs-global-routing.module";
|
||||
import { TabsGlobalComponent } from "./tabs-global.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
IonicModule,
|
||||
TabsGlobalRoutingModule
|
||||
],
|
||||
declarations: [TabsGlobalComponent]
|
||||
})
|
||||
export class TabsGlobalModule { }
|
@ -12,6 +12,9 @@
|
||||
<p>
|
||||
<ion-button routerLink="/tabs/account" id="goto-tab1-page1">Go to Tab 1 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs/contact" id="goto-tab2-page1">Go to Tab 2 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs-global" id="goto-global">Go to Global Page</ion-button>
|
||||
<ion-button routerLink="/tabs-global" id="goto-prev" (click)="navCtrl.pop()">Go to Previous Page (NavController).
|
||||
</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/{{next()}}" id="goto-next">Go to Next</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tabs-tab1-nested',
|
||||
@ -9,7 +10,8 @@ export class TabsTab1NestedComponent implements OnInit {
|
||||
id = '';
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
) {}
|
||||
public navCtrl: NavController
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.id = this.route.snapshot.paramMap.get('id');
|
||||
@ -18,4 +20,5 @@ export class TabsTab1NestedComponent implements OnInit {
|
||||
next() {
|
||||
return parseInt(this.id, 10) + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,5 +19,6 @@
|
||||
id="goto-nested-page1-with-query-params">Go to Page 2 with Query Params</ion-button>
|
||||
<ion-button routerLink="/tabs/lazy/nested" id="goto-tab3-page2">Go to Tab 3 - Page 2</ion-button>
|
||||
<ion-button routerLink="/nested-outlet/page" id="goto-nested-page1">Go to nested</ion-button>
|
||||
<ion-button (click)="navCtrl.pop()" id="goto-previous-page">Go to Previous Page</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component, NgZone } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tabs-tab1',
|
||||
@ -9,6 +10,8 @@ export class TabsTab1Component {
|
||||
segment = 'one';
|
||||
changed = 'false';
|
||||
|
||||
constructor(public navCtrl: NavController) {}
|
||||
|
||||
ionViewWillEnter() {
|
||||
NgZone.assertInAngularZone();
|
||||
setTimeout(() => {
|
||||
|
Reference in New Issue
Block a user