mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
fix(urlSerializer): improve findLinkByComponentData
This commit is contained in:
@ -118,6 +118,7 @@ export interface NavLink {
|
||||
partsLen?: number;
|
||||
staticLen?: number;
|
||||
dataLen?: number;
|
||||
dataKeys?: {[key: string]: boolean};
|
||||
defaultHistory?: any[];
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { NavLink, NavSegment } from '../nav-util';
|
||||
import { UrlSerializer, isPartMatch, fillMatchedUrlParts, parseUrlParts, createMatchedData, normalizeLinks } from '../url-serializer';
|
||||
import { UrlSerializer, isPartMatch, fillMatchedUrlParts, parseUrlParts, createMatchedData, normalizeLinks, findLinkByComponentData } from '../url-serializer';
|
||||
import { mockDeepLinkConfig, noop, MockView1, MockView2, MockView3, MockView4, MockView5 } from '../../util/mock-providers';
|
||||
|
||||
|
||||
@ -7,6 +7,18 @@ describe('UrlSerializer', () => {
|
||||
|
||||
describe('serializeComponent', () => {
|
||||
|
||||
it('should create segement when config has multiple links to same component', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView1, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView1, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
serializer = mockSerializer([link1, link2, link3]);
|
||||
serializer.createSegment = noop;
|
||||
spyOn(serializer, 'createSegment');
|
||||
serializer.serializeComponent(MockView1, null);
|
||||
expect(serializer.createSegment).toHaveBeenCalledWith(link1, null);
|
||||
});
|
||||
|
||||
it('should create segment if component found in links', () => {
|
||||
serializer.createSegment = noop;
|
||||
spyOn(serializer, 'createSegment');
|
||||
@ -533,6 +545,88 @@ describe('UrlSerializer', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('findLinkByComponentData', () => {
|
||||
|
||||
it('should get matching link by component w/ data and multiple links using same component, 2 matches', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView1, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView1, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
let links = normalizeLinks([link1, link2, link3]);
|
||||
|
||||
let foundLink = findLinkByComponentData(links, MockView1, {
|
||||
param1: false,
|
||||
param2: 0,
|
||||
param3: 0
|
||||
});
|
||||
expect(foundLink.name).toEqual('viewthree');
|
||||
});
|
||||
|
||||
it('should get matching link by component w/ data and multiple links using same component, 1 match', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView1, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView1, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
let links = normalizeLinks([link1, link2, link3]);
|
||||
|
||||
let foundLink = findLinkByComponentData(links, MockView1, {
|
||||
param1: false,
|
||||
param3: 0
|
||||
});
|
||||
expect(foundLink.name).toEqual('viewtwo');
|
||||
});
|
||||
|
||||
it('should get matching link by component w/ no data and multiple links using same component', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView1, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView1, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
let links = normalizeLinks([link1, link2, link3]);
|
||||
|
||||
let foundLink = findLinkByComponentData(links, MockView1, null);
|
||||
expect(foundLink.name).toEqual('viewone');
|
||||
});
|
||||
|
||||
it('should get matching link by component data and link data', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView2, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView3, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
let links = normalizeLinks([link1, link2, link3]);
|
||||
|
||||
let foundLink = findLinkByComponentData(links, MockView3, {
|
||||
param1: null,
|
||||
param2: false,
|
||||
param3: 0,
|
||||
param4: 'hello'
|
||||
});
|
||||
expect(foundLink.name).toEqual('viewthree');
|
||||
});
|
||||
|
||||
it('should get matching link by component without data and link without data', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView2, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView3, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
let links = normalizeLinks([link1, link2, link3]);
|
||||
|
||||
let foundLink = findLinkByComponentData(links, MockView1, null);
|
||||
expect(foundLink.name).toEqual('viewone');
|
||||
});
|
||||
|
||||
it('should get no matching link by component without data, but link requires data', () => {
|
||||
const link1 = { component: MockView1, name: 'viewone', segment: 'view' };
|
||||
const link2 = { component: MockView2, name: 'viewtwo', segment: 'view/:param1' };
|
||||
const link3 = { component: MockView3, name: 'viewthree', segment: 'view/:param1/:param2' };
|
||||
|
||||
let links = normalizeLinks([link1, link2, link3]);
|
||||
|
||||
let foundLink = findLinkByComponentData(links, MockView2, null);
|
||||
expect(foundLink).toEqual(null);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('normalizeLinks', () => {
|
||||
|
||||
it('should sort with four parts, the most number of paths w/out data first', () => {
|
||||
|
@ -59,7 +59,7 @@ export class UrlSerializer {
|
||||
*/
|
||||
serializeComponent(component: any, data: any): NavSegment {
|
||||
if (component) {
|
||||
const link = this.links.find(l => component === l.component || component.name === l.name);
|
||||
const link = findLinkByComponentData(this.links, component, data);
|
||||
if (link) {
|
||||
return this.createSegment(link, data);
|
||||
}
|
||||
@ -203,6 +203,41 @@ export const createMatchedData = (matchedUrlParts: string[], link: NavLink): any
|
||||
return data;
|
||||
};
|
||||
|
||||
export const findLinkByComponentData = (links: NavLink[], component: any, instanceData: any): NavLink => {
|
||||
let foundLink: NavLink = null;
|
||||
let foundLinkDataMatches = -1;
|
||||
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var link = links[i];
|
||||
if (link.component === component) {
|
||||
// ok, so the component matched, but multiple links can point
|
||||
// to the same component, so let's make sure this is the right link
|
||||
var dataMatches = 0;
|
||||
if (instanceData) {
|
||||
var instanceDataKeys = Object.keys(instanceData);
|
||||
|
||||
// this link has data
|
||||
for (var j = 0; j < instanceDataKeys.length; j++) {
|
||||
if (isPresent(link.dataKeys[instanceDataKeys[j]])) {
|
||||
dataMatches++;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (link.dataLen) {
|
||||
// this component does not have data but the link does
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dataMatches >= foundLinkDataMatches) {
|
||||
foundLink = link;
|
||||
foundLinkDataMatches = dataMatches;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return foundLink;
|
||||
};
|
||||
|
||||
export const normalizeLinks = (links: NavLink[]): NavLink[] => {
|
||||
for (var i = 0, ilen = links.length; i < ilen; i++) {
|
||||
var link = links[i];
|
||||
@ -211,6 +246,7 @@ export const normalizeLinks = (links: NavLink[]): NavLink[] => {
|
||||
link.segment = link.name;
|
||||
}
|
||||
|
||||
link.dataKeys = {};
|
||||
link.parts = link.segment.split('/');
|
||||
link.partsLen = link.parts.length;
|
||||
|
||||
@ -222,6 +258,7 @@ export const normalizeLinks = (links: NavLink[]): NavLink[] => {
|
||||
if (link.parts[j].charAt(0) === ':') {
|
||||
link.dataLen++;
|
||||
stillCountingStatic = false;
|
||||
link.dataKeys[link.parts[j].substring(1)] = true;
|
||||
|
||||
} else if (stillCountingStatic) {
|
||||
link.staticLen++;
|
||||
|
Reference in New Issue
Block a user