Differenzansicht 05-filter
im Vergleich zu 04-services

Zurück zur Übersicht | ← Vorherige | Nächste → | Demo | Quelltext auf GitHub
src/app/books-portal/books-overview-page/books-overview-page.html CHANGED
@@ -13,7 +13,15 @@
13
  <section>
14
  <h1>Books</h1>
15
  <div>
16
- @for (b of books(); track b.isbn) {
 
 
 
 
 
 
 
 
17
  <app-book-card [book]="b" (like)="addLikedBook($event)" />
18
  }
19
  </div>
 
13
  <section>
14
  <h1>Books</h1>
15
  <div>
16
+ <input
17
+ type="search"
18
+ [value]="searchTerm()"
19
+ (input)="this.searchTerm.set($event.target.value)"
20
+ placeholder="Search"
21
+ aria-label="Search"
22
+ />
23
+
24
+ @for (b of filteredBooks(); track b.isbn) {
25
  <app-book-card [book]="b" (like)="addLikedBook($event)" />
26
  }
27
  </div>
src/app/books-portal/books-overview-page/books-overview-page.spec.ts CHANGED
@@ -1,31 +1,47 @@
1
  import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
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]
11
- })
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
  });
 
1
  import { ComponentFixture, TestBed } from '@angular/core/testing';
 
2
  import { BooksOverviewPage } from './books-overview-page';
3
 
4
  describe('BooksOverviewPage', () => {
5
+ let component: BooksOverviewPage;
6
  let fixture: ComponentFixture<BooksOverviewPage>;
7
 
8
  beforeEach(async () => {
9
  await TestBed.configureTestingModule({
10
  imports: [BooksOverviewPage]
11
+ }).compileComponents();
 
12
 
13
  fixture = TestBed.createComponent(BooksOverviewPage);
14
+ component = fixture.componentInstance;
15
  fixture.detectChanges();
16
  });
17
 
18
+ it('should display all books if the search term is empty', () => {
19
+ component['searchTerm'].set('');
20
+
21
+ const books = component['filteredBooks']();
22
+ expect(books.length).toBe(2);
23
+ });
24
+
25
+ it('should filter books based on the search term', () => {
26
+ component['searchTerm'].set('Affe');
27
+
28
+ const books = component['filteredBooks']();
29
+ expect(books.length).toBe(1);
30
+ expect(books[0].title).toBe('Backen mit Affen');
31
+ });
32
+
33
+ it('should filter books ignoring case sensitivity', () => {
34
+ component['searchTerm'].set('AFFEN');
35
+
36
+ const books = component['filteredBooks']();
37
+ expect(books.length).toBe(1);
38
+ expect(books[0].title).toBe('Backen mit Affen');
39
  });
40
 
41
+ it('should return an empty array if no book matches the search term', () => {
42
+ component['searchTerm'].set('unbekannter Titel');
 
43
 
44
+ const books = component['filteredBooks']();
45
+ expect(books.length).toBe(0);
46
  });
47
  });
src/app/books-portal/books-overview-page/books-overview-page.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Component, inject, signal } from '@angular/core';
2
 
3
  import { Book } from '../../shared/book';
4
  import { BookCard } from '../book-card/book-card';
@@ -13,9 +13,20 @@ import { BookStore } from '../../shared/book-store';
13
  export class BooksOverviewPage {
14
  #bookStore = inject(BookStore);
15
 
 
 
16
  protected books = signal<Book[]>([]);
17
  protected likedBooks = signal<Book[]>([]);
18
 
 
 
 
 
 
 
 
 
 
19
  constructor() {
20
  this.books.set(this.#bookStore.getAll());
21
  }
 
1
+ import { Component, computed, inject, signal } from '@angular/core';
2
 
3
  import { Book } from '../../shared/book';
4
  import { BookCard } from '../book-card/book-card';
 
13
  export class BooksOverviewPage {
14
  #bookStore = inject(BookStore);
15
 
16
+ protected searchTerm = signal('');
17
+
18
  protected books = signal<Book[]>([]);
19
  protected likedBooks = signal<Book[]>([]);
20
 
21
+ protected filteredBooks = computed(() => {
22
+ if (!this.searchTerm()) {
23
+ return this.books();
24
+ }
25
+
26
+ const term = this.searchTerm().toLowerCase();
27
+ return this.books().filter((b) => b.title.toLowerCase().includes(term));
28
+ });
29
+
30
  constructor() {
31
  this.books.set(this.#bookStore.getAll());
32
  }
src/app/shared/book-store.plain.spec.ts DELETED
@@ -1,24 +0,0 @@
1
- import { BookStore } from './book-store';
2
- import { Book } from './book';
3
-
4
- describe('BookStore', () => {
5
- let service: BookStore;
6
-
7
- beforeEach(() => {
8
- service = new BookStore();
9
- });
10
-
11
- it('should be created', () => {
12
- expect(service).toBeTruthy();
13
- });
14
-
15
- it('should return a list of books', () => {
16
- const books = service.getAll();
17
-
18
- // Optional: Wir können die Bücher auch noch intensiver prüfen
19
- // Zum Beispiel:
20
- // expect(books[0].isbn).toBe('12345');
21
- // expect(books[1].title).toBe('Backen mit Affen');
22
- expect(books.length).toBeGreaterThan(0);
23
- });
24
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/app/shared/book-store.spec.ts ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { BookStore } from './book-store';
4
+
5
+ describe('BookStore', () => {
6
+ let service: BookStore;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(BookStore);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
src/app/shared/book-store.testbed.spec.ts DELETED
@@ -1,27 +0,0 @@
1
- import { TestBed } from '@angular/core/testing';
2
- import { BookStore } from './book-store';
3
-
4
- describe('BookStore', () => {
5
- let service: BookStore;
6
-
7
- beforeEach(() => {
8
- TestBed.configureTestingModule({
9
- providers: [BookStore]
10
- });
11
- service = TestBed.inject(BookStore);
12
- });
13
-
14
- it('should be created', () => {
15
- expect(service).toBeTruthy();
16
- });
17
-
18
- it('should return a list of books', () => {
19
- const books = service.getAll();
20
- expect(books.length).toBeGreaterThan(0);
21
-
22
- // Optional: Wir können die Bücher auch noch intensiver prüfen
23
- // Zum Beispiel:
24
- // expect(books[0].isbn).toBe('12345');
25
- // expect(books[1].title).toBe('Backen mit Affen');
26
- });
27
- });