fix(aio): remove links from sub-menu toggles (#21695)
Navigating to a document while trying to expand or collapse a sub-menu is undesirable and confusing. All sub-menu toggles should have no other effect than expanding/collapsing the corresponding sub-menu. PR Close #21695
This commit is contained in:
parent
97dafa8460
commit
89051a0452
@ -74,7 +74,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "tutorial",
|
|
||||||
"title": "Tutorial",
|
"title": "Tutorial",
|
||||||
"tooltip": "The Tour of Heroes tutorial takes you through the steps of creating an Angular application in TypeScript.",
|
"tooltip": "The Tour of Heroes tutorial takes you through the steps of creating an Angular application in TypeScript.",
|
||||||
"children": [
|
"children": [
|
||||||
@ -122,7 +121,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"url": "guide/architecture",
|
|
||||||
"title": "Fundamentals",
|
"title": "Fundamentals",
|
||||||
"tooltip": "The fundamentals of Angular",
|
"tooltip": "The fundamentals of Angular",
|
||||||
"children": [
|
"children": [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { browser, by, element } from 'protractor';
|
import { browser, by, element, ElementFinder } from 'protractor';
|
||||||
import { SitePage } from './app.po';
|
import { SitePage } from './app.po';
|
||||||
|
|
||||||
describe('site App', function() {
|
describe('site App', function() {
|
||||||
@ -11,7 +11,7 @@ describe('site App', function() {
|
|||||||
|
|
||||||
it('should show features text after clicking "Features"', () => {
|
it('should show features text after clicking "Features"', () => {
|
||||||
page.navigateTo('');
|
page.navigateTo('');
|
||||||
page.getTopMenuLink('features').click();
|
page.click(page.getTopMenuLink('features'));
|
||||||
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
|
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -19,28 +19,74 @@ describe('site App', function() {
|
|||||||
page.navigateTo('');
|
page.navigateTo('');
|
||||||
expect(browser.getTitle()).toBe('Angular');
|
expect(browser.getTitle()).toBe('Angular');
|
||||||
|
|
||||||
page.getTopMenuLink('features').click();
|
page.click(page.getTopMenuLink('features'));
|
||||||
expect(browser.getTitle()).toBe('Angular - FEATURES & BENEFITS');
|
expect(browser.getTitle()).toBe('Angular - FEATURES & BENEFITS');
|
||||||
|
|
||||||
page.homeLink.click();
|
page.click(page.homeLink);
|
||||||
expect(browser.getTitle()).toBe('Angular');
|
expect(browser.getTitle()).toBe('Angular');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not navigate when clicking on nav-item headings (sub-menu toggles)', () => {
|
||||||
|
// Show the sidenav.
|
||||||
|
page.navigateTo('docs');
|
||||||
|
expect(page.locationPath()).toBe('/docs');
|
||||||
|
|
||||||
|
// Get the top-level nav-item headings (sub-menu toggles).
|
||||||
|
const navItemHeadings = page.getNavItemHeadings(page.sidenav, 1);
|
||||||
|
|
||||||
|
// Test all headings (and sub-headings).
|
||||||
|
expect(navItemHeadings.count()).toBeGreaterThan(0);
|
||||||
|
navItemHeadings.each(heading => testNavItemHeading(heading!, 1));
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
function expectToBeCollapsed(element: ElementFinder) {
|
||||||
|
expect(element.getAttribute('class')).toMatch(/\bcollapsed\b/);
|
||||||
|
expect(element.getAttribute('class')).not.toMatch(/\bexpanded\b/);
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectToBeExpanded(element: ElementFinder) {
|
||||||
|
expect(element.getAttribute('class')).not.toMatch(/\bcollapsed\b/);
|
||||||
|
expect(element.getAttribute('class')).toMatch(/\bexpanded\b/);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNavItemHeading(heading: ElementFinder, level: number) {
|
||||||
|
const children = page.getNavItemHeadingChildren(heading, level);
|
||||||
|
|
||||||
|
// Headings are initially collapsed.
|
||||||
|
expectToBeCollapsed(children);
|
||||||
|
|
||||||
|
// Ensure heading does not cause navigation when expanding.
|
||||||
|
page.click(heading);
|
||||||
|
expectToBeExpanded(children);
|
||||||
|
expect(page.locationPath()).toBe('/docs');
|
||||||
|
|
||||||
|
// Recursively test child-headings (while this heading is expanded).
|
||||||
|
const nextLevel = level + 1;
|
||||||
|
const childNavItemHeadings = page.getNavItemHeadings(children, nextLevel);
|
||||||
|
childNavItemHeadings.each(childHeading => testNavItemHeading(childHeading!, nextLevel));
|
||||||
|
|
||||||
|
// Ensure heading does not cause navigation when collapsing.
|
||||||
|
page.click(heading);
|
||||||
|
expectToBeCollapsed(children);
|
||||||
|
expect(page.locationPath()).toBe('/docs');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should show the tutorial index page at `/tutorial` after jitterbugging through features', () => {
|
it('should show the tutorial index page at `/tutorial` after jitterbugging through features', () => {
|
||||||
// check that we can navigate directly to the tutorial page
|
// check that we can navigate directly to the tutorial page
|
||||||
page.navigateTo('tutorial');
|
page.navigateTo('tutorial');
|
||||||
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
||||||
|
|
||||||
// navigate to a different page
|
// navigate to a different page
|
||||||
page.getTopMenuLink('features').click();
|
page.click(page.getTopMenuLink('features'));
|
||||||
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
|
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
|
||||||
|
|
||||||
// Show the menu
|
// Show the menu
|
||||||
page.docsMenuLink.click();
|
page.click(page.docsMenuLink);
|
||||||
|
|
||||||
// Tutorial folder should still be expanded because this test runs in wide mode
|
// Tutorial folder should still be expanded because this test runs in wide mode
|
||||||
// Navigate to the tutorial introduction via a link in the sidenav
|
// Navigate to the tutorial introduction via a link in the sidenav
|
||||||
page.getNavItem(/introduction/i).click();
|
page.click(page.getNavItem(/introduction/i));
|
||||||
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
expect(page.getDocViewerText()).toMatch(/Tutorial: Tour of Heroes/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,8 +103,7 @@ describe('site App', function() {
|
|||||||
page.scrollToBottom();
|
page.scrollToBottom();
|
||||||
expect(page.getScrollTop()).toBeGreaterThan(0);
|
expect(page.getScrollTop()).toBeGreaterThan(0);
|
||||||
|
|
||||||
page.getNavItem(/api/i).click();
|
page.click(page.getNavItem(/api/i));
|
||||||
browser.waitForAngular();
|
|
||||||
expect(page.locationPath()).toBe('/api');
|
expect(page.locationPath()).toBe('/api');
|
||||||
expect(page.getScrollTop()).toBe(0);
|
expect(page.getScrollTop()).toBe(0);
|
||||||
});
|
});
|
||||||
@ -69,8 +114,7 @@ describe('site App', function() {
|
|||||||
page.scrollToBottom();
|
page.scrollToBottom();
|
||||||
expect(page.getScrollTop()).toBeGreaterThan(0);
|
expect(page.getScrollTop()).toBeGreaterThan(0);
|
||||||
|
|
||||||
page.getNavItem(/security/i).click();
|
page.click(page.getNavItem(/security/i));
|
||||||
browser.waitForAngular();
|
|
||||||
expect(page.locationPath()).toBe('/guide/security');
|
expect(page.locationPath()).toBe('/guide/security');
|
||||||
expect(page.getScrollTop()).toBe(0);
|
expect(page.getScrollTop()).toBe(0);
|
||||||
});
|
});
|
||||||
@ -102,7 +146,7 @@ describe('site App', function() {
|
|||||||
it('should call ga with new URL on navigation', done => {
|
it('should call ga with new URL on navigation', done => {
|
||||||
let path: string;
|
let path: string;
|
||||||
page.navigateTo('');
|
page.navigateTo('');
|
||||||
page.getTopMenuLink('features').click();
|
page.click(page.getTopMenuLink('features'));
|
||||||
page.locationPath()
|
page.locationPath()
|
||||||
.then(p => path = p)
|
.then(p => path = p)
|
||||||
.then(() => page.ga())
|
.then(() => page.ga())
|
||||||
@ -125,7 +169,7 @@ describe('site App', function() {
|
|||||||
expect(element(by.css('meta[name="googlebot"][content="noindex"]')).isPresent()).toBeTruthy();
|
expect(element(by.css('meta[name="googlebot"][content="noindex"]')).isPresent()).toBeTruthy();
|
||||||
expect(element(by.css('meta[name="robots"][content="noindex"]')).isPresent()).toBeTruthy();
|
expect(element(by.css('meta[name="robots"][content="noindex"]')).isPresent()).toBeTruthy();
|
||||||
|
|
||||||
page.getTopMenuLink('features').click();
|
page.click(page.getTopMenuLink('features'));
|
||||||
expect(element(by.css('meta[name="googlebot"]')).isPresent()).toBeFalsy();
|
expect(element(by.css('meta[name="googlebot"]')).isPresent()).toBeFalsy();
|
||||||
expect(element(by.css('meta[name="robots"]')).isPresent()).toBeFalsy();
|
expect(element(by.css('meta[name="robots"]')).isPresent()).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ export class SitePage {
|
|||||||
links = element.all(by.css('md-toolbar a'));
|
links = element.all(by.css('md-toolbar a'));
|
||||||
homeLink = element(by.css('a.home'));
|
homeLink = element(by.css('a.home'));
|
||||||
docsMenuLink = element(by.cssContainingText('aio-top-menu a', 'Docs'));
|
docsMenuLink = element(by.cssContainingText('aio-top-menu a', 'Docs'));
|
||||||
|
sidenav = element(by.css('mat-sidenav'));
|
||||||
docViewer = element(by.css('aio-doc-viewer'));
|
docViewer = element(by.css('aio-doc-viewer'));
|
||||||
codeExample = element.all(by.css('aio-doc-viewer pre > code'));
|
codeExample = element.all(by.css('aio-doc-viewer pre > code'));
|
||||||
ghLink = this.docViewer
|
ghLink = this.docViewer
|
||||||
@ -24,7 +25,17 @@ export class SitePage {
|
|||||||
.filter(element => element.getText().then(text => pattern.test(text)))
|
.filter(element => element.getText().then(text => pattern.test(text)))
|
||||||
.first();
|
.first();
|
||||||
}
|
}
|
||||||
|
getNavItemHeadings(parent: ElementFinder, level: number) {
|
||||||
|
const targetSelector = `aio-nav-item .vertical-menu-item.heading.level-${level}`;
|
||||||
|
return parent.all(by.css(targetSelector));
|
||||||
|
}
|
||||||
|
getNavItemHeadingChildren(heading: ElementFinder, level: number) {
|
||||||
|
const targetSelector = `.heading-children.level-${level}`;
|
||||||
|
const script = `return arguments[0].parentNode.querySelector('${targetSelector}');`;
|
||||||
|
return element(() => browser.executeScript(script, heading));
|
||||||
|
}
|
||||||
getTopMenuLink(path) { return element(by.css(`aio-top-menu a[href="${path}"]`)); }
|
getTopMenuLink(path) { return element(by.css(`aio-top-menu a[href="${path}"]`)); }
|
||||||
|
|
||||||
ga() { return browser.executeScript('return window["ga"].q') as promise.Promise<any[][]>; }
|
ga() { return browser.executeScript('return window["ga"].q') as promise.Promise<any[][]>; }
|
||||||
locationPath() { return browser.executeScript('return document.location.pathname') as promise.Promise<string>; }
|
locationPath() { return browser.executeScript('return document.location.pathname') as promise.Promise<string>; }
|
||||||
|
|
||||||
@ -53,6 +64,10 @@ export class SitePage {
|
|||||||
return browser.executeScript('window.scrollTo(0, document.body.scrollHeight)');
|
return browser.executeScript('window.scrollTo(0, document.body.scrollHeight)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
click(element: ElementFinder) {
|
||||||
|
return element.click().then(() => browser.waitForAngular());
|
||||||
|
}
|
||||||
|
|
||||||
enterSearch(query: string) {
|
enterSearch(query: string) {
|
||||||
const input = element(by.css('.search-container input[type=search]'));
|
const input = element(by.css('.search-container input[type=search]'));
|
||||||
input.clear();
|
input.clear();
|
||||||
|
@ -128,6 +128,12 @@ button.vertical-menu-item {
|
|||||||
transition-timing-function: ease-out;
|
transition-timing-function: ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-animations {
|
||||||
|
.heading-children.expanded, .heading-children.collapsed {
|
||||||
|
transition: none! important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.level-1 {
|
.level-1 {
|
||||||
font-family: $main-font;
|
font-family: $main-font;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user