Differenzansicht 02-inputs
im Vergleich zu 01-components

Zurück zur Übersicht | ← Vorherige | Nächste → | Demo | Quelltext auf GitHub
src/app/app.spec.ts CHANGED
@@ -13,4 +13,19 @@ describe('App', () => {
13
  const app = fixture.componentInstance;
14
  expect(app).toBeTruthy();
15
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  });
 
13
  const app = fixture.componentInstance;
14
  expect(app).toBeTruthy();
15
  });
16
+
17
+ /*
18
+ it(`should have the 'book-manager' title`, () => {
19
+ const fixture = TestBed.createComponent(App);
20
+ const app = fixture.componentInstance;
21
+ expect(app.title).toEqual('book-manager');
22
+ });
23
+
24
+ it('should render title', () => {
25
+ const fixture = TestBed.createComponent(App);
26
+ fixture.detectChanges();
27
+ const compiled = fixture.nativeElement as HTMLElement;
28
+ expect(compiled.querySelector('h1')?.textContent).toContain('Hello, book-manager');
29
+ });
30
+ */
31
  });
src/app/books-portal/book-card/book-card.html ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @let b = book();
2
+
3
+ <article class="book-card">
4
+ <img [src]="b.imageUrl" alt="Cover" />
5
+ <header>
6
+ <h2>{{ b.title }}</h2>
7
+ </header>
8
+ <div>
9
+ @if (b.subtitle) {
10
+ <p role="doc-subtitle">{{ b.subtitle }}</p>
11
+ }
12
+ ISBN: {{ b.isbn }}
13
+ </div>
14
+ </article>
src/app/books-portal/book-card/book-card.ts ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, input } from '@angular/core';
2
+
3
+ import { Book } from '../../shared/book';
4
+
5
+ @Component({
6
+ selector: 'app-book-card',
7
+ imports: [],
8
+ templateUrl: './book-card.html',
9
+ styleUrl: './book-card.scss'
10
+ })
11
+ export class BookCard {
12
+ readonly book = input.required<Book>();
13
+ }
src/app/books-portal/book-card/book-card.variante1.spec.ts ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { BookCard } from './book-card';
4
+ import { Book } from '../../shared/book';
5
+ import { signal, inputBinding } from '@angular/core';
6
+
7
+ describe('BookCard', () => {
8
+ let fixture: ComponentFixture<BookCard>;
9
+ const testBook = signal<Book>({
10
+ isbn: '1111',
11
+ title: 'Testbuch',
12
+ subtitle: 'Test',
13
+ authors: ['Author 1', 'Author 2'],
14
+ imageUrl: 'https://cdn.ng-buch.de/test.png',
15
+ description: 'Dies ist ein Testbuch',
16
+ createdAt: new Date().toISOString()
17
+ });
18
+
19
+ beforeEach(async () => {
20
+ await TestBed.configureTestingModule({
21
+ imports: [BookCard]
22
+ })
23
+ .compileComponents();
24
+
25
+
26
+ fixture = TestBed.createComponent(BookCard, {
27
+ bindings: [inputBinding('book', testBook)]
28
+ });
29
+
30
+ fixture.detectChanges();
31
+ });
32
+
33
+ it('should render book title, subtitle and isbn', () => {
34
+ const compiledElement: HTMLElement = fixture.nativeElement;
35
+ expect(compiledElement.textContent).toContain(testBook().isbn);
36
+ expect(compiledElement.textContent).toContain(testBook().subtitle);
37
+ expect(compiledElement.textContent).toContain(testBook().isbn);
38
+ });
39
+
40
+ it('should display the correct image', () => {
41
+ const compiledElement: HTMLElement = fixture.nativeElement;
42
+ const imageEl = compiledElement.querySelector('img')!;
43
+ expect(imageEl).toBeTruthy();
44
+ expect(imageEl.src).toBe(testBook().imageUrl);
45
+ });
46
+ });
src/app/books-portal/book-card/book-card.variante2.spec.ts ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { BookCard } from './book-card';
4
+ import { Book } from '../../shared/book';
5
+ import { inputBinding } from '@angular/core';
6
+
7
+ describe('BookCard', () => {
8
+ let fixture: ComponentFixture<BookCard>;
9
+ const testBook: Book = {
10
+ isbn: '1111',
11
+ title: 'Testbuch',
12
+ subtitle: 'Test',
13
+ authors: ['Author 1', 'Author 2'],
14
+ imageUrl: 'https://cdn.ng-buch.de/test.png',
15
+ description: 'Dies ist ein Testbuch',
16
+ createdAt: new Date().toISOString()
17
+ };
18
+
19
+ beforeEach(async () => {
20
+ await TestBed.configureTestingModule({
21
+ imports: [BookCard]
22
+ })
23
+ .compileComponents();
24
+
25
+
26
+ fixture = TestBed.createComponent(BookCard, {
27
+ bindings: [inputBinding('book', () => testBook)]
28
+ });
29
+
30
+ fixture.detectChanges();
31
+ });
32
+
33
+ it('should render book title, subtitle and isbn', () => {
34
+ const compiledElement: HTMLElement = fixture.nativeElement;
35
+ expect(compiledElement.textContent).toContain(testBook.isbn);
36
+ expect(compiledElement.textContent).toContain(testBook.subtitle);
37
+ expect(compiledElement.textContent).toContain(testBook.isbn);
38
+ });
39
+
40
+ it('should display the correct image', () => {
41
+ const compiledElement: HTMLElement = fixture.nativeElement;
42
+ const imageEl = compiledElement.querySelector('img')!;
43
+ expect(imageEl).toBeTruthy();
44
+ expect(imageEl.src).toBe(testBook.imageUrl);
45
+ });
46
+ });
src/app/books-portal/books-overview-page/books-overview-page.html CHANGED
@@ -2,17 +2,7 @@
2
  <h1>Books</h1>
3
  <div>
4
  @for (b of books(); track b.isbn) {
5
- <article class="book-card">
6
- <header>
7
- <h2>{{ b.title }}</h2>
8
- </header>
9
- <div>
10
- @if (b.subtitle) {
11
- <p role="doc-subtitle">{{ b.subtitle }}</p>
12
- }
13
- ISBN: {{ b.isbn }}
14
- </div>
15
- </article>
16
  }
17
  </div>
18
  </section>
 
2
  <h1>Books</h1>
3
  <div>
4
  @for (b of books(); track b.isbn) {
5
+ <app-book-card [book]="b" />
 
 
 
 
 
 
 
 
 
 
6
  }
7
  </div>
8
  </section>
src/app/books-portal/books-overview-page/books-overview-page.spec.ts CHANGED
@@ -3,10 +3,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
  import { BooksOverviewPage } from './books-overview-page';
4
 
5
  describe('BooksOverviewPage', () => {
6
- let component: BooksOverviewPage;
7
  let fixture: ComponentFixture<BooksOverviewPage>;
8
 
9
- // Arrange
10
  beforeEach(async () => {
11
  await TestBed.configureTestingModule({
12
  imports: [BooksOverviewPage]
@@ -14,32 +12,20 @@ describe('BooksOverviewPage', () => {
14
  .compileComponents();
15
 
16
  fixture = TestBed.createComponent(BooksOverviewPage);
17
- component = fixture.componentInstance;
18
  });
19
 
20
- it('should have a list of 2 books', () => {
21
- // Act
22
- // Daten aus Signal auslesen, dieses wird bereits im Konstruktor gesetzt
23
- const books = component['books']();
24
-
25
- // Assert
26
- expect(books.length).toBe(2);
27
- expect(books[0].title).toContain('Tierisch gut kochen');
28
- expect(books[1].title).toContain('Backen mit Affen');
29
  });
30
 
31
- it('should render the correct book titles', () => {
32
- // Act
33
- // Durch detectChanges() wird das Template "gerendert"
34
- fixture.detectChanges();
35
-
36
- // Im gerenderten DOM nach dem Tag <article> suchen
37
  const compiledElement: HTMLElement = fixture.nativeElement;
38
- const articleEls = compiledElement.querySelectorAll('article');
39
 
40
- // Assert
41
- expect(articleEls.length).toBe(2);
42
- expect(articleEls[0].textContent).toContain('Tierisch gut kochen');
43
- expect(articleEls[1].textContent).toContain('Backen mit Affen');
44
  });
45
  });
 
3
  import { BooksOverviewPage } from './books-overview-page';
4
 
5
  describe('BooksOverviewPage', () => {
 
6
  let fixture: ComponentFixture<BooksOverviewPage>;
7
 
 
8
  beforeEach(async () => {
9
  await TestBed.configureTestingModule({
10
  imports: [BooksOverviewPage]
 
12
  .compileComponents();
13
 
14
  fixture = TestBed.createComponent(BooksOverviewPage);
15
+ fixture.detectChanges();
16
  });
17
 
18
+ it('should render a BookCard component for each book', () => {
19
+ const compiledElement: HTMLElement = fixture.nativeElement;
20
+ const bookCardEls = compiledElement.querySelectorAll('app-book-card');
21
+ expect(bookCardEls.length).toBe(2);
 
 
 
 
 
22
  });
23
 
24
+ it('should correctly pass book data to BookCard components', () => {
 
 
 
 
 
25
  const compiledElement: HTMLElement = fixture.nativeElement;
26
+ const bookCardEls = compiledElement.querySelectorAll('app-book-card');
27
 
28
+ expect(bookCardEls[0].textContent).toContain('Tierisch gut kochen');
29
+ expect(bookCardEls[1].textContent).toContain('Backen mit Affen');
 
 
30
  });
31
  });
src/app/books-portal/books-overview-page/books-overview-page.ts CHANGED
@@ -1,10 +1,11 @@
1
  import { Component, signal } from '@angular/core';
2
 
3
  import { Book } from '../../shared/book';
 
4
 
5
  @Component({
6
  selector: 'app-books-overview-page',
7
- imports: [],
8
  templateUrl: './books-overview-page.html',
9
  styleUrl: './books-overview-page.scss',
10
  })
 
1
  import { Component, signal } from '@angular/core';
2
 
3
  import { Book } from '../../shared/book';
4
+ import { BookCard } from '../book-card/book-card';
5
 
6
  @Component({
7
  selector: 'app-books-overview-page',
8
+ imports: [BookCard],
9
  templateUrl: './books-overview-page.html',
10
  styleUrl: './books-overview-page.scss',
11
  })