Added some unit tests for navLinkBuilder
Because I could not make jest work with any references to SPFx, I separated the navLinkBuilder into its own component. Also, I set collectCoverage to false, as coverage collection is currently broken and I see no easy way to fix this. Two tests are ignored, since they describe the issue and are currently failing.
This commit is contained in:
parent
5b2e546d9d
commit
3593de26ac
|
@ -0,0 +1 @@
|
|||
v14.20.0
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"preset": "@voitanos/jest-preset-spfx-react16",
|
||||
"rootDir": "../src"
|
||||
"rootDir": "../src",
|
||||
"collectCoverage": false
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
import { IHierarchyEntry, navLinkBuilder } from "./NavLinkBuilder";
|
||||
|
||||
interface IMockLink extends IHierarchyEntry<IMockLink> {
|
||||
name: string;
|
||||
}
|
||||
|
||||
const DEPTH_NO_COLLAPSABLE_HEADER = 0;
|
||||
const DEPTH_COLLAPSABLE_HEADER = 1;
|
||||
|
||||
describe("The NavLinkBuilder without a preceding collapsable header", () => {
|
||||
|
||||
const depth = DEPTH_NO_COLLAPSABLE_HEADER;
|
||||
const h1 = depth;
|
||||
const h2 = h1+1;
|
||||
const h3 = h2+1;
|
||||
const h4 = h3+1;
|
||||
|
||||
it("should add a single item to an empty list", () => {
|
||||
const lnk: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
|
||||
const actual = navLinkBuilder.build([], lnk, h1, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a two items on the same level", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h1, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it("should add a two items on different levels", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a two items on the same level and two items on different levels", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
const lnk11: IMockLink = {
|
||||
name: "xyz.1",
|
||||
};
|
||||
const lnk21: IMockLink = {
|
||||
name: "abc.1",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk11, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk21, h2, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a four items on different levels", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "def",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "geh",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk3, h3, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk4, h4, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it.skip("should not nest two h2", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk3, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk4, h3, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it.skip("should not nest two h3", () => {
|
||||
const lnk0: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk5: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk6: IMockLink = {
|
||||
name: "h4",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([], lnk0, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk3, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk4, h3, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk5, h3, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk6, h4, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("The NavLinkBuilder with a collapsable header", () => {
|
||||
let head: IMockLink;
|
||||
const depth = DEPTH_COLLAPSABLE_HEADER;
|
||||
const h1 = depth;
|
||||
const h2 = h1+1;
|
||||
const h3 = h2+1;
|
||||
const h4 = h3+1;
|
||||
|
||||
beforeEach(() => {
|
||||
head = {
|
||||
name: "head",
|
||||
};
|
||||
});
|
||||
|
||||
it("should add a single item to the heading", () => {
|
||||
const lnk: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
|
||||
const actual = navLinkBuilder.build([ head ], lnk, h1, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a two items on the same level", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([ head ], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h1, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it("should add a one item in a collapsable section two inside that one", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "def",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([ head ], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk3, h2, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it("should not nest two h2", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([ head ], lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk3, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk4, h3, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not nest two h3", () => {
|
||||
const lnk0: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk5: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk6: IMockLink = {
|
||||
name: "h4",
|
||||
};
|
||||
|
||||
let actual = navLinkBuilder.build([ head ], lnk0, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk1, h1, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk2, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk3, h2, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk4, h3, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk5, h3, depth);
|
||||
actual = navLinkBuilder.build(actual, lnk6, h4, depth);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
export interface IHierarchyEntry<T extends IHierarchyEntry<T>> {
|
||||
links?: IHierarchyEntry<T>[];
|
||||
}
|
||||
|
||||
export class navLinkBuilder {
|
||||
/**
|
||||
* Nests a new nav link within the nav links tree
|
||||
* @param currentLinks current nav links
|
||||
* @param newLink the new nav link to be added to the structure
|
||||
* @param order place order of the new link
|
||||
* @param depth sequence depth
|
||||
* @returns navLinks
|
||||
*/
|
||||
public static build<T extends IHierarchyEntry<T>>(currentLinks: T[], newLink: T, order: number, depth: number): T[] {
|
||||
const lastIndex = currentLinks.length - 1;
|
||||
|
||||
if (lastIndex === -1) {
|
||||
return [newLink];
|
||||
}
|
||||
|
||||
const lastTopLevelLink = currentLinks[lastIndex];
|
||||
lastTopLevelLink.links = lastTopLevelLink.links || [];
|
||||
|
||||
if (lastTopLevelLink.links.length === 0 || order === depth) {
|
||||
if (order !== depth || depth !== 0) {
|
||||
lastTopLevelLink.links.push(newLink);
|
||||
} else {
|
||||
currentLinks.push(newLink);
|
||||
}
|
||||
} else {
|
||||
depth++;
|
||||
currentLinks[lastIndex].links.concat(this.build(currentLinks[lastIndex].links, newLink, order, depth));
|
||||
}
|
||||
|
||||
return currentLinks;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { INavLink } from 'office-ui-fabric-react/lib/Nav';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { SPHttpClient } from '@microsoft/sp-http';
|
||||
import { navLinkBuilder } from './NavLinkBuilder';
|
||||
|
||||
export class SPService {
|
||||
/* Array to store all unique anchor URLs */
|
||||
|
@ -37,33 +38,6 @@ export class SPService {
|
|||
return anchorUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nests a new nav link within the nav links tree
|
||||
* @param currentLinks current nav links
|
||||
* @param newLink the new nav link to be added to the structure
|
||||
* @param order place order of the new link
|
||||
* @param depth sequence depth
|
||||
* @returns navLinks
|
||||
*/
|
||||
public static navLinkBuilder(currentLinks: INavLink[], newLink: INavLink, order: number, depth: number): INavLink[] {
|
||||
const lastIndex = currentLinks.length - 1;
|
||||
|
||||
if (lastIndex === -1) {
|
||||
currentLinks.push(newLink);
|
||||
} else if (currentLinks[lastIndex].links.length === 0 || order === depth) {
|
||||
if (order !== depth || depth !== 0) {
|
||||
currentLinks[lastIndex].links.push(newLink);
|
||||
} else {
|
||||
currentLinks.push(newLink);
|
||||
}
|
||||
} else {
|
||||
depth++;
|
||||
currentLinks[lastIndex].links.concat(this.navLinkBuilder(currentLinks[lastIndex].links, newLink, order, depth));
|
||||
}
|
||||
|
||||
return currentLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Anchor Links for Nav element
|
||||
* @param context Web part context
|
||||
|
@ -126,7 +100,7 @@ export class SPService {
|
|||
|
||||
// Add link to nav element
|
||||
const newNavLink: INavLink = { name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true };
|
||||
anchorLinks = this.navLinkBuilder(anchorLinks, newNavLink, headingOrder, hasCollapsableHeader ? 1 : 0);
|
||||
anchorLinks = navLinkBuilder.build<INavLink>(anchorLinks, newNavLink, headingOrder, hasCollapsableHeader ? 1 : 0);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should add a one item in a collapsable section two inside that one 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
Object {
|
||||
"name": "def",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should add a single item to the heading 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should add a two items on the same level 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should not nest two h2 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should not nest two h3 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h1",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h4",
|
||||
},
|
||||
],
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a four items on different levels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "geh",
|
||||
},
|
||||
],
|
||||
"name": "def",
|
||||
},
|
||||
],
|
||||
"name": "abc",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a single item to an empty list 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a two items on different levels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a two items on the same level 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [],
|
||||
"name": "xyz",
|
||||
},
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a two items on the same level and two items on different levels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "xyz.1",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "abc.1",
|
||||
},
|
||||
],
|
||||
"name": "abc",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should not nest two h2 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [],
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should not nest two h3 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [],
|
||||
"name": "h1",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array[],
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h4",
|
||||
},
|
||||
],
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
]
|
||||
`;
|
Loading…
Reference in New Issue