From b9978e516e41df8a96709ee93538129a91269e90 Mon Sep 17 00:00:00 2001 From: Ken Rimple Date: Sun, 28 Feb 2016 21:38:09 -0500 Subject: [PATCH] fixed several line breaks, removed further imports --- db.json | 6 ++ src/app/blog-roll/blog-roll-unit.spec.ts | 92 ++++++++++++++++++++++++ src/app/blog-roll/blog-roll.spec.ts | 40 ++++------- src/app/blog-roll/blog-roll.ts | 7 +- src/app/services/blog-service.ts | 55 +++++++------- 5 files changed, 141 insertions(+), 59 deletions(-) create mode 100644 src/app/blog-roll/blog-roll-unit.spec.ts diff --git a/db.json b/db.json index 33faa11..e3644f7 100644 --- a/db.json +++ b/db.json @@ -11,6 +11,12 @@ "contentRendered": "

TUVWXYZ

\n", "contentMarkdown": "TUVWXYZ", "id": 2 + }, + { + "title": "This is the title", + "contentRendered": "

one

\n

Two

\n\n", + "contentMarkdown": "# one\n## Two\n* A\n* B\n* C", + "id": 3 } ] } \ No newline at end of file diff --git a/src/app/blog-roll/blog-roll-unit.spec.ts b/src/app/blog-roll/blog-roll-unit.spec.ts new file mode 100644 index 0000000..61f6514 --- /dev/null +++ b/src/app/blog-roll/blog-roll-unit.spec.ts @@ -0,0 +1,92 @@ +import {BlogRoll} from './blog-roll'; +import {BlogEntry} from '../domain/blog-entry'; +import {BlogService} from '../services/blog-service'; +import {MarkdownService} from '../services/markdown-service'; +import {Observable} from 'rxjs/Rx'; + +class MockMarkdownService extends MarkdownService { + toHtml(text: string): string { + return text; + } +} + +class MockBlogService extends BlogService { + constructor() { + super(null); + } + + getBlogs() { + console.log('sending fake answers!'); + return Observable.of([ + { + id: 26, + title: 'The title', + contentRendered: '

Hi there

', + contentMarkdown: '*Hi there*' + }]); + } +} + +describe('Blog Roll unit test', () => { + var blogRoll: BlogRoll, + blogService: BlogService, + markdownService: MarkdownService; + + beforeEach(() => { + blogService = new MockBlogService(); + markdownService = new MockMarkdownService(); + blogRoll = new BlogRoll(blogService, markdownService); + }); + + it('shows list of blog items by default - unit', () => { + blogRoll.ngOnInit(); + expect(blogRoll.blogs.length).toBe(1); + expect(blogRoll.blog).toBeUndefined(); + expect(blogRoll.editing).toBe(false); + }); + + it('should show blog editor div when newBlogEntry is triggered...', () => { + blogRoll.ngOnInit(); + // we start with the blog roll panel visible + expect(blogRoll.editing).toBe(false); + + // trigger the 'new' event + blogRoll.newBlogEntry(); + expect(blogRoll.editing).toBe(true); + expect(blogRoll.blog).toBeDefined(); + }); + + it('should pass data to the blogService during save', () => { + blogRoll.ngOnInit(); + // make this a synchronous instantaneous call + // and since we only look for successful resolution it + // doesn't matter what we stub back + spyOn(blogService, 'saveBlog') + .and.returnValue(Observable.of({ complete: true})); + + let entry = new BlogEntry('I am new', '

The content

', 'The content', undefined); + blogRoll.saveBlogEntry(entry); + expect(blogService.saveBlog).toHaveBeenCalledWith(entry); + }); + + it('should pass a blog item to remove to the blogService during delete', () => { + blogRoll.ngOnInit(); + // alerts/confirm are an awful idea (short timeframe for this demo) + // but we can deal with the confirm message box by mocking it away, + // and returning true to continue processing - thanks Jasmine! + spyOn(window, 'confirm') + .and.callFake(() => { return true; }); + + // now mock the actual call to + spyOn(blogService, 'deleteBlogEntry') + .and.returnValue(Observable.of({ complete: true})); + let entry = new BlogEntry(null ,null, null, 15); + blogRoll.deleteBlogEntry(entry); + + // collaborator behavior check + expect(window.confirm).toHaveBeenCalled(); + expect(blogService.deleteBlogEntry).toHaveBeenCalledWith(15); + }); +}); + + diff --git a/src/app/blog-roll/blog-roll.spec.ts b/src/app/blog-roll/blog-roll.spec.ts index f763e78..77d4685 100644 --- a/src/app/blog-roll/blog-roll.spec.ts +++ b/src/app/blog-roll/blog-roll.spec.ts @@ -1,6 +1,5 @@ import { it, - xit, describe, expect, inject, @@ -14,7 +13,6 @@ import {BlogRoll} from './blog-roll'; import {BlogEntry} from '../domain/blog-entry'; import {BlogService} from '../services/blog-service'; import {MarkdownService} from '../services/markdown-service'; -import {MockBackend} from 'angular2/src/http/backends/mock_backend'; import {Observable} from 'rxjs/Rx'; class MockMarkdownService extends MarkdownService { @@ -47,21 +45,7 @@ describe('Blog Roll Component...', () => { mockBlogService = new MockBlogService(); }); - it('shows list of blog items by default - unit', () => { - let blogRoll: BlogRoll = new BlogRoll(null, null); - blogRoll.ngOnInit().then( - () => { - expect(blogRoll.blogs.length).toBe(1); - expect(blogRoll.blog).toBeUndefined(); - expect(blogRoll.editing).toBe(false); - }, - (error) => { - console.log('promise rejected, error is', error); - }); - - }); - - it('shows list of blog items by default - tcb', injectAsync([TestComponentBuilder], (tcb) => { + it('shows list of blog items by default', injectAsync([TestComponentBuilder], (tcb) => { return tcb .overrideProviders(BlogRoll, [provide(BlogService, {useValue: mockBlogService})]) .createAsync(BlogRoll) @@ -74,12 +58,14 @@ describe('Blog Roll Component...', () => { expect(nativeElement.querySelector('#blog-editor-panel') === null).toBe(true); expect(nativeElement.querySelector('#blog-roll-panel') === null).toBe(false); - // trigger the 'new' button and swap visible panels - fixture.nativeElement.querySelector('i.glyphicon-plus-sign').click(); - fixture.detectChanges(); - expect(fixture.componentInstance.editing).toBe(true); - expect(nativeElement.querySelector('#blog-editor-panel') === null).toBe(false); - expect(nativeElement.querySelector('#blog-roll-panel') === null).toBe(true); + let trs = nativeElement.querySelectorAll('tr'); + expect(trs.length).toBe(2); + + let tdTitleContent = trs[1].children[1].innerHTML; + let tdRenderedContent = trs[1].children[2].innerHTML; + expect(tdTitleContent).toContain('The title'); + expect(tdRenderedContent).toContain('Hi there'); + }); })); @@ -92,14 +78,12 @@ describe('Blog Roll Component...', () => { let nativeElement = fixture.nativeElement; fixture.detectChanges(); - // we start with the blog roll panel visible - expect(fixture.componentInstance.editing).toBe(false); - expect(nativeElement.querySelector('#blog-editor-panel') === null).toBe(true); - expect(nativeElement.querySelector('#blog-roll-panel') === null).toBe(false); - // trigger the 'new' button and swap visible panels fixture.nativeElement.querySelector('i.glyphicon-plus-sign').click(); + + // process the click event fixture.detectChanges(); + expect(fixture.componentInstance.editing).toBe(true); expect(nativeElement.querySelector('#blog-editor-panel') === null).toBe(false); expect(nativeElement.querySelector('#blog-roll-panel') === null).toBe(true); diff --git a/src/app/blog-roll/blog-roll.ts b/src/app/blog-roll/blog-roll.ts index 078c049..2eebf81 100644 --- a/src/app/blog-roll/blog-roll.ts +++ b/src/app/blog-roll/blog-roll.ts @@ -4,6 +4,7 @@ import {BlogEntry} from '../domain/blog-entry.ts'; import {BlogService} from '../services/blog-service'; import {MarkdownService} from '../services/markdown-service'; import {OnInit} from 'angular2/core'; +import {Observable} from 'rxjs/Observable'; @Component({ providers: [BlogService, MarkdownService], @@ -96,19 +97,15 @@ export class BlogRoll implements OnInit { } loadBlogEntries() { - return new Promise((resolve, reject) => { this.blogService.getBlogs().subscribe( (data: Array) => { console.log('blog data arrived', data); this.blogs = data; - resolve(); }, (error: Object) => { console.log('error!', error); - reject(error); } ); - }); } render(blog: BlogEntry) { @@ -128,7 +125,7 @@ export class BlogRoll implements OnInit { } saveBlogEntry(blog: BlogEntry) { - this.blogService.saveBlog(blog) + return this.blogService.saveBlog(blog) .subscribe( () => { this.editing = false; this.blog = null; diff --git a/src/app/services/blog-service.ts b/src/app/services/blog-service.ts index 3830db2..927439b 100644 --- a/src/app/services/blog-service.ts +++ b/src/app/services/blog-service.ts @@ -8,40 +8,43 @@ import {RequestOptionsArgs} from 'angular2/http'; @Injectable() export class BlogService { - constructor(private http: Http) { } + constructor(private http: Http) { + } - private getOptions() : RequestOptions { - var headers: Headers = new Headers(); - headers.append('content-type', 'application/json; charset=utf-8'); - let opts = new RequestOptions({headers: headers}); - opts.headers = headers; - return opts; - } + private getOptions(): RequestOptions { + var headers: Headers = new Headers(); + headers.append('content-type', 'application/json; charset=utf-8'); + let opts = new RequestOptions({headers: headers}); + opts.headers = headers; + return opts; + } - getBlogs(): Observable { - return this.http.get('/api/blogs') - .map((res: Response) => { return BlogEntry.asBlogEntries(res.json()); }, this.getOptions()); - } + getBlogs(): Observable { + return this.http.get('/api/blogs') + .map((res: Response) => { + return BlogEntry.asBlogEntries(res.json()); + }, this.getOptions()); + } - saveBlog(blog: BlogEntry): Observable { - console.log('saving', blog.json()); - if (blog.id) { - return this.http.put('/api/blogs/' + blog.id, blog.json(), this.getOptions()); - } else { - return this.http.post('/api/blogs', blog.json(), this.getOptions()); - } + saveBlog(blog: BlogEntry): Observable { + console.log('saving', blog.json()); + if (blog.id) { + return this.http.put('/api/blogs/' + blog.id, blog.json(), this.getOptions()); + } else { + return this.http.post('/api/blogs', blog.json(), this.getOptions()); } + } - deleteBlogEntry(id: number): Observable { - return this.http.delete('/api/blogs/' + id); - } + deleteBlogEntry(id: number): Observable { + return this.http.delete('/api/blogs/' + id) + } getBlog(id: number): any { return this.http.get('/api/blogs/' + id) - .map((res: Response) => { - console.log(res); - return BlogEntry.asBlogEntry(res.json()); - }); + .map((res: Response) => { + console.log(res); + return BlogEntry.asBlogEntry(res.json()); + }); } }