Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(aio): each doc can add/remove class to aio-shell with <aio-context> #16564

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 50 additions & 17 deletions aio/src/app/app.component.spec.ts
Expand Up @@ -31,6 +31,7 @@ describe('AppComponent', () => {

let docViewer: HTMLElement;
let hamburger: HTMLButtonElement;
let http: TestHttp;
let locationService: MockLocationService;
let sidenav: HTMLElement;

Expand Down Expand Up @@ -256,6 +257,10 @@ describe('AppComponent', () => {

describe('currentDocument', () => {

beforeEach(() => {
http = TestBed.get(Http);
});

it('should display a guide page (guide/pipes)', () => {
locationService.go('guide/pipes');
fixture.detectChanges();
Expand All @@ -274,6 +279,22 @@ describe('AppComponent', () => {
expect(docViewer.innerText).toMatch(/Features/i);
});

it('should update the document title', () => {
const titleService = TestBed.get(Title);
spyOn(titleService, 'setTitle');
locationService.go('guide/pipes');
fixture.detectChanges();
expect(titleService.setTitle).toHaveBeenCalledWith('Angular - Pipes');
});

it('should update the document title, with a default value if the document has no title', () => {
const titleService = TestBed.get(Title);
spyOn(titleService, 'setTitle');
locationService.go('no-title');
fixture.detectChanges();
expect(titleService.setTitle).toHaveBeenCalledWith('Angular');
});

const marketingClassName = 'marketing';

it('should not have marketing CSS class on host element for a guide page (guide/pipes)', () => {
Expand All @@ -290,21 +311,28 @@ describe('AppComponent', () => {
expect(classes).toContain(marketingClassName);
});

it('should update the document title', () => {
const titleService = TestBed.get(Title);
spyOn(titleService, 'setTitle');
locationService.go('guide/pipes');
fixture.detectChanges();
expect(titleService.setTitle).toHaveBeenCalledWith('Angular - Pipes');
});
describe('when has <aio-context>', () => {

it('should update the document title, with a default value if the document has no title', () => {
const titleService = TestBed.get(Title);
spyOn(titleService, 'setTitle');
locationService.go('no-title');
fixture.detectChanges();
expect(titleService.setTitle).toHaveBeenCalledWith('Angular');
it('should have marketing context\'s CSS class on host element', () => {
http.contents = '<aio-context class="foo bar"></aio-context>';
locationService.go('features');
fixture.detectChanges();
const classes: string[] = fixture.nativeElement.className;
// Has "marketing" class as well as "foo bar"
expect(classes).toBe(marketingClassName + ' foo bar');
});

it('should have tutorial context\'s CSS on host element when <aio-context> is late in the doc', () => {
const fluff = 'abc'.repeat(100);
http.contents = fluff + '<aio-context class="foo bar">ignored stuff</aio-context>' + fluff;
locationService.go('tutorial/foo');
fixture.detectChanges();
const classes: string[] = fixture.nativeElement.className;
// No "marketing" class this time because is tutorial page
expect(classes).toBe('foo bar');
});
});

});

describe('autoScrolling with AutoScrollService', () => {
Expand Down Expand Up @@ -484,6 +512,8 @@ class TestHttp {
{ title: 'v2', url: 'https://v2.angular.io' }
];

contents: string;

// tslint:disable:quotemark
navJson = {
"TopBar": [
Expand Down Expand Up @@ -544,12 +574,15 @@ class TestHttp {
if (/navigation\.json/.test(url)) {
data = this.navJson;
} else {
let contents = this.contents;
const match = /generated\/docs\/(.+)\.json/.exec(url);
const id = match[1];
// Make up a title for test purposes
const title = id.split('/').pop().replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
const h1 = (id === 'no-title') ? '' : `<h1>${title}</h1>`;
const contents = `${h1}<h2 id="#somewhere">Some heading</h2>`;
if (contents === undefined) {
// Make up a title for test purposes
const title = id.split('/').pop().replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
const h1 = (id === 'no-title') ? '' : `<h1>${title}</h1>`;
contents = `${h1}<h2 id="#somewhere">Some heading</h2>`;
}
data = { id, contents };
}
return of({ json: () => data });
Expand Down
21 changes: 17 additions & 4 deletions aio/src/app/app.component.ts
Expand Up @@ -26,9 +26,6 @@ export class AppComponent implements OnInit {
currentDocument: DocumentContents;
footerNodes: NavigationNode[];

@HostBinding('class.marketing')
isMarketing = false;

isStarting = true;
isSideBySide = false;
private isSideNavDoc = false;
Expand Down Expand Up @@ -60,6 +57,9 @@ export class AppComponent implements OnInit {
@ViewChild(SearchResultsComponent)
searchResults: SearchResultsComponent;

@HostBinding('class')
shellClasses = '';

@ViewChild(MdSidenav)
sidenav: MdSidenav;

Expand All @@ -79,6 +79,7 @@ export class AppComponent implements OnInit {
this.documentService.currentDocument.subscribe(doc => {
this.currentDocument = doc;
this.setPageId(doc.id);
this.shellClasses = this.getShellClasses(doc);
});

this.locationService.currentPath.subscribe(path => {
Expand All @@ -98,7 +99,6 @@ export class AppComponent implements OnInit {
if (this.previousNavView === currentNode.view) { return; }
this.previousNavView = currentNode.view;
this.isSideNavDoc = currentNode.view === sideNavView;
this.isMarketing = !this.isSideNavDoc;
this.sideNavToggle(this.isSideNavDoc && this.isSideBySide);
});

Expand Down Expand Up @@ -174,4 +174,17 @@ export class AppComponent implements OnInit {
// Special case the home page
this.pageId = (id === 'index') ? 'home' : id.replace('/', '-');
}

private getShellClasses(doc: DocumentContents) {
let shellClasses = /^(guide|tutorial)\//.test(doc.id) ? '' : 'marketing ';

const contents = doc.contents || '';
// extract the classes from `<aio-context>`
const contextMatch = contents.match(/<aio-context.*class="([^"]*)/);
if (contextMatch) {
shellClasses += contextMatch[1] || '';
}

return shellClasses;
}
}