diff --git a/aio/content/file-not-found.md b/aio/content/file-not-found.md index 46092603ce..9371fe03bf 100644 --- a/aio/content/file-not-found.md +++ b/aio/content/file-not-found.md @@ -7,3 +7,4 @@

We're sorry. The page you are looking for cannot be found.

+ diff --git a/aio/e2e/app.e2e-spec.ts b/aio/e2e/app.e2e-spec.ts index 6abeb1b998..dfcd7c6b53 100644 --- a/aio/e2e/app.e2e-spec.ts +++ b/aio/e2e/app.e2e-spec.ts @@ -100,4 +100,12 @@ describe('site App', function() { expect(page.getSearchResults().map(link => link.getText())).toContain('ControlValueAccessor'); }); }); + + describe('404 page', () => { + it('should search the index for words found in the url', () => { + page.navigateTo('http/router'); + expect(page.getSearchResults().map(link => link.getText())).toContain('Http'); + expect(page.getSearchResults().map(link => link.getText())).toContain('Router'); + }); + }); }); diff --git a/aio/src/app/embedded/embedded.module.ts b/aio/src/app/embedded/embedded.module.ts index ac1426e33e..b65d5bda58 100644 --- a/aio/src/app/embedded/embedded.module.ts +++ b/aio/src/app/embedded/embedded.module.ts @@ -20,6 +20,7 @@ import { CodeTabsComponent } from './code/code-tabs.component'; import { ContributorListComponent } from './contributor/contributor-list.component'; import { ContributorComponent } from './contributor/contributor.component'; import { CurrentLocationComponent } from './current-location.component'; +import { FileNotFoundSearchComponent } from './search/file-not-found-search.component'; import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/live-example.component'; import { ResourceListComponent } from './resource/resource-list.component'; import { ResourceService } from './resource/resource.service'; @@ -30,7 +31,8 @@ import { TocComponent } from './toc/toc.component'; */ export const embeddedComponents: any[] = [ ApiListComponent, CodeExampleComponent, CodeTabsComponent, ContributorListComponent, - CurrentLocationComponent, LiveExampleComponent, ResourceListComponent, TocComponent + CurrentLocationComponent, FileNotFoundSearchComponent, LiveExampleComponent, ResourceListComponent, + TocComponent ]; /** Injectable class w/ property returning components that can be embedded in docs */ diff --git a/aio/src/app/embedded/search/file-not-found-search.component.spec.ts b/aio/src/app/embedded/search/file-not-found-search.component.spec.ts new file mode 100644 index 0000000000..175832ef32 --- /dev/null +++ b/aio/src/app/embedded/search/file-not-found-search.component.spec.ts @@ -0,0 +1,49 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Subject } from 'rxjs/Subject'; +import { LocationService } from 'app/shared/location.service'; +import { MockLocationService } from 'testing/location.service'; +import { SearchResults } from 'app/search/interfaces'; +import { SearchResultsComponent } from 'app/shared/search-results/search-results.component'; +import { SearchService } from 'app/search/search.service'; +import { FileNotFoundSearchComponent } from './file-not-found-search.component'; + + +describe('FileNotFoundSearchComponent', () => { + let element: HTMLElement; + let fixture: ComponentFixture; + let searchService: SearchService; + let searchResultSubject: Subject; + + beforeEach(() => { + + TestBed.configureTestingModule({ + declarations: [ FileNotFoundSearchComponent, SearchResultsComponent ], + providers: [ + { provide: LocationService, useValue: new MockLocationService('base/initial-url?some-query') }, + SearchService + ] + }); + + fixture = TestBed.createComponent(FileNotFoundSearchComponent); + searchService = TestBed.get(SearchService); + searchResultSubject = new Subject(); + spyOn(searchService, 'search').and.callFake(() => searchResultSubject.asObservable()); + fixture.detectChanges(); + element = fixture.nativeElement; + }); + + it('should run a search with a query built from the current url', () => { + expect(searchService.search).toHaveBeenCalledWith('base initial url'); + }); + + it('should pass through any results to the `aio-search-results` component', () => { + const searchResultsComponent = fixture.debugElement.query(By.directive(SearchResultsComponent)).componentInstance; + expect(searchResultsComponent.searchResults).toBe(null); + + const results = { query: 'base initial url', results: []}; + searchResultSubject.next(results); + fixture.detectChanges(); + expect(searchResultsComponent.searchResults).toEqual(results); + }); +}); diff --git a/aio/src/app/embedded/search/file-not-found-search.component.ts b/aio/src/app/embedded/search/file-not-found-search.component.ts new file mode 100644 index 0000000000..119b118739 --- /dev/null +++ b/aio/src/app/embedded/search/file-not-found-search.component.ts @@ -0,0 +1,23 @@ +import { Component, OnInit } from '@angular/core'; +import { Observable } from 'rxjs/Observable'; +import { LocationService } from 'app/shared/location.service'; +import { SearchResults } from 'app/search/interfaces'; +import { SearchService } from 'app/search/search.service'; + +@Component({ + selector: 'aio-file-not-found-search', + template: + `

Let's see if any of these search results help...

+ ` +}) +export class FileNotFoundSearchComponent implements OnInit { + searchResults: Observable; + constructor(private location: LocationService, private search: SearchService) {} + + ngOnInit() { + this.searchResults = this.location.currentPath.switchMap(path => { + const query = path.split(/\W+/).join(' '); + return this.search.search(query); + }); + } +} diff --git a/aio/src/styles/2-modules/_search-results.scss b/aio/src/styles/2-modules/_search-results.scss index 42cc6798ae..fc71cea5dc 100644 --- a/aio/src/styles/2-modules/_search-results.scss +++ b/aio/src/styles/2-modules/_search-results.scss @@ -29,6 +29,24 @@ aio-search-results { } } +aio-search-results.embedded .search-results { + padding: 0; + color: inherit; + width: auto; + max-height: 100%; + position: relative; + background-color: inherit; + box-shadow: none; + box-sizing: border-box; + + .search-area a { + color: lighten($darkgray, 10); + &:hover { + color: $accentblue; + } + } +} + .search-area { display: flex; flex-direction: column;