diff --git a/client/src/app/posts/post-details/post-details.component.spec.ts b/client/src/app/posts/post-details/post-details.component.spec.ts index 42603d5568ce4350023a4129d448992301039b81..dd08767ab534fe61aad83da494d6cfd33f4e6b32 100644 --- a/client/src/app/posts/post-details/post-details.component.spec.ts +++ b/client/src/app/posts/post-details/post-details.component.spec.ts @@ -3,6 +3,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ActivatedRoute } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { Post } from 'src/app/models/post.model'; +import { SharedModule } from 'src/app/shared/shared.module'; +import { PostListComponent } from '../post-list/post-list.component'; import { PostService } from '../post.service'; import { PostDetailsComponent } from './post-details.component'; @@ -39,7 +41,13 @@ describe('PostDetailsComponent', () => { await TestBed.configureTestingModule({ declarations: [ PostDetailsComponent ], - imports: [ HttpClientTestingModule, RouterTestingModule ], + imports: [ + HttpClientTestingModule, + SharedModule, + RouterTestingModule.withRoutes([ + { path: 'annonse', component: PostListComponent} + ]) + ], providers: [ { provide: ActivatedRoute, useValue: { snapshot: {params: {id: 5}}}}, { provide: PostService, useValue: mockPostService } @@ -60,6 +68,8 @@ describe('PostDetailsComponent', () => { it('should get post with id from url parameter', async () => { // Waits for ngOnInit and checks that we get post + expect(component.post).not.toBeNull(); + fixture.whenStable().then(() => { expect(mockPostService.getPost).toHaveBeenCalledWith(5); expect(component.post).toEqual(new Post({ @@ -77,6 +87,8 @@ describe('PostDetailsComponent', () => { it('should delete post with id', async () => { // Waits for ngOnInit and checks that we can delete post + expect(component.post).not.toBeNull(); + fixture.whenStable().then(() => { component.deletePost(); expect(mockPostService.deletePost).toHaveBeenCalledWith(5); diff --git a/client/src/app/posts/post-form/post-form.component.spec.ts b/client/src/app/posts/post-form/post-form.component.spec.ts index ac94cf73d7f117ce4d9799466e22a58ec224a381..b16d0c1d0f8cf6a09db3e50c254b9fac775f73d3 100644 --- a/client/src/app/posts/post-form/post-form.component.spec.ts +++ b/client/src/app/posts/post-form/post-form.component.spec.ts @@ -5,6 +5,7 @@ import { Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { Category } from 'src/app/models/category.model'; import { SharedModule } from 'src/app/shared/shared.module'; +import { PostListComponent } from '../post-list/post-list.component'; import { PostService } from '../post.service'; import { PostFormComponent } from './post-form.component'; @@ -39,7 +40,14 @@ describe('PostFormComponent', () => { await TestBed.configureTestingModule({ declarations: [ PostFormComponent ], - imports: [ HttpClientTestingModule, RouterTestingModule, FormsModule, SharedModule ], + imports: [ + HttpClientTestingModule, + FormsModule, + SharedModule, + RouterTestingModule.withRoutes([ + { path: 'annonse', component: PostListComponent} + ]) + ], providers: [ { provide: PostService, useValue: mockPostService } ] }) .compileComponents(); @@ -118,6 +126,7 @@ describe('PostFormComponent', () => { it('should delete post with id', async () => { component.id = 5; + expect(component.id).toBe(5); // Waits for ngOnInit and checks that we can delete post fixture.whenStable().then(() => { @@ -128,6 +137,7 @@ describe('PostFormComponent', () => { it('should not delete new post', async () => { // Waits for ngOnInit and checks that we can delete post + expect(component.id).toBe(0); fixture.whenStable().then(() => { component.deletePost(); expect(mockPostService.deletePost).not.toHaveBeenCalledWith(5); diff --git a/client/src/app/posts/post-list/post-list.component.html b/client/src/app/posts/post-list/post-list.component.html index 49aa9a1fd89cf255bf9400e1339c1ad261950e86..728cdeef4c2b8b01e7d76c9955a40c6184a7d285 100644 --- a/client/src/app/posts/post-list/post-list.component.html +++ b/client/src/app/posts/post-list/post-list.component.html @@ -1,3 +1,8 @@ <div> + <app-select [(inputModel)]="selectedCategory" (change)="filterCategory()"> + <option value="0" selected>Ingen kategori</option> + <option *ngFor="let category of categories" [value]="category.getCategoryId">{{category.getName}}</option> + </app-select> + <app-post-thumbnail *ngFor="let post of allPosts" [post]="post"></app-post-thumbnail> </div> diff --git a/client/src/app/posts/post-list/post-list.component.spec.ts b/client/src/app/posts/post-list/post-list.component.spec.ts index 464c09fe2d5d9261f2ae08d144b4a0c5063c314c..c7ac545160f9ddba6ef7dc13b6099cb94801f788 100644 --- a/client/src/app/posts/post-list/post-list.component.spec.ts +++ b/client/src/app/posts/post-list/post-list.component.spec.ts @@ -1,5 +1,6 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { SharedModule } from 'src/app/shared/shared.module'; import { PostListComponent } from './post-list.component'; @@ -10,7 +11,7 @@ describe('PostListComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ PostListComponent ], - imports: [ HttpClientTestingModule ] + imports: [ HttpClientTestingModule, SharedModule ] }) .compileComponents(); }); diff --git a/client/src/app/posts/post-list/post-list.component.ts b/client/src/app/posts/post-list/post-list.component.ts index 2bd3302dcdd9662c616bd358e90b1e1f7f72240f..3910d07fc4a50c899528a3c4377722b2de10dd86 100644 --- a/client/src/app/posts/post-list/post-list.component.ts +++ b/client/src/app/posts/post-list/post-list.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import { Category } from 'src/app/models/category.model'; import { Post } from 'src/app/models/post.model'; import { PostService } from '../post.service'; @@ -9,11 +10,25 @@ import { PostService } from '../post.service'; }) export class PostListComponent implements OnInit { - allPosts: Array<Post> = [] + allPosts: Array<Post> = []; + categories: Array<Category> = []; + + selectedCategory: number; constructor(private postService: PostService) { } ngOnInit(): void { + // Gets all categories from database and displays them in dropdown + this.postService.getAllCategories().then(categories => { + this.categories = categories; + }).catch(error => { + console.log(error); + }); + + this.getPosts(); + } + + getPosts() { // Gets all posts from database, and displays them this.postService.getAllPosts().then(posts => { this.allPosts = posts; @@ -22,4 +37,17 @@ export class PostListComponent implements OnInit { }); } + filterCategory() { + if (this.selectedCategory > 0) { + // Gets all posts by selected category + this.postService.getPostsByCategory(this.selectedCategory).then(posts => { + this.allPosts = posts; + }).catch(error => { + console.log(error); + }); + } else { + this.getPosts(); + } + } + } diff --git a/client/src/app/posts/post.service.spec.ts b/client/src/app/posts/post.service.spec.ts index eaf36787ea6d30889a5b08e9927672306d5f613a..5242cf4b29290bae5b2120df809f8551d5e6cb9b 100644 --- a/client/src/app/posts/post.service.spec.ts +++ b/client/src/app/posts/post.service.spec.ts @@ -260,5 +260,76 @@ describe('PostService', () => { req.error(new ErrorEvent("400")); }); }); + + describe('getPostsByCategory', () => { + it('should get posts by category', () => { + // Gets posts by category and checks values + service.getPostsByCategory(2).then(posts => { + for (let i = 0; i < posts.length; i++) { + expect(posts[i].getId).toBe(i + 1); + expect(posts[i].getTitle).toBe("Test" + (i + 1)); + expect(posts[i].getCategory).toBe(2); + } + }).catch(error => { + fail(); + }); + + // Mocks and checks HTTP request + const req = httpMock.expectOne("api/post/?categoryid=2"); + expect(req.request.method).toBe("GET"); + req.flush({ + data: [{ + id: 1, + title: "Test1", + description: "TestDescription", + timestamp: 23947298234, + owner: "user", + imageUrl: null, + price: 49, + categoryid: 2 + }, { + id: 2, + title: "Test2", + description: "TestDescription", + timestamp: 23453246527, + owner: "user", + imageUrl: null, + price: 159, + categoryid: 2 + }] + }); + }); + + it('should reject on invalid post', () => { + // Gets invalid post, should go to catch + service.getPostsByCategory(52).then(posts => { + fail(); + }).catch(error => {}); + + // Mocks and checks HTTP request + const req = httpMock.expectOne("api/post/?categoryid=52"); + expect(req.request.method).toBe("GET"); + req.flush({ + data: [{ + id: 0, + title: "Test", + description: "TestDescription", + timestamp: 23947298 + }] + }); + }); + + it('should reject on http error', () => { + // Gets HTTP error instead of post, should catch + service.getPostsByCategory(35).then(post => { + fail(); + }).catch(error => {}); + + // Mocks and checks HTTP request + const req = httpMock.expectOne("api/post/?categoryid=35"); + expect(req.request.method).toBe("GET"); + req.error(new ErrorEvent("400")); + }); + }); }); diff --git a/client/src/app/posts/post.service.ts b/client/src/app/posts/post.service.ts index 3a09b533c6da23da313072008c1dc922976f133e..be13c643d012dc097c7faa76f2c4bb5bef4198ec 100644 --- a/client/src/app/posts/post.service.ts +++ b/client/src/app/posts/post.service.ts @@ -27,7 +27,7 @@ export class PostService { for (let post of data.data) { outputPosts.push(new Post(post)); - if (post.getId == 0) { + if (!post.id || post.id == 0) { reject("Could not deserialize Post"); return; } @@ -196,5 +196,40 @@ export class PostService { private update_post(id: number, post: Post) { return this.http.put(this.postUrl + id, post.serialize()); + } + + /** + * Get all posts in database by specified category. + */ + getPostsByCategory(categoryId: number): Promise<Array<Post>> { + return new Promise<Array<Post>>( + (resolve, reject) => { + this.get_posts_by_category(categoryId).subscribe((data: any) => { + try { + let outputPosts = []; + for (let post of data.data) { + outputPosts.push(new Post(post)); + + if (!post.id || post.id == 0) { + reject("Could not deserialize Post"); + return; + } + } + + resolve(outputPosts); + } catch (err: any) { + reject(err); + } + }, + (err: any) => { + console.log(err.message); + reject(err); + }); + } + ); + } + + private get_posts_by_category(categoryId: number) { + return this.http.get(this.postUrl, {params: {categoryid: String(categoryId)}}); } } diff --git a/client/src/app/users/user-login-form/user-login-form.component.spec.ts b/client/src/app/users/user-login-form/user-login-form.component.spec.ts index e680f03e5b6d7cfbb17b3ce59431f26a5fcd6e7c..0371849739edbfa6576cdd5570e960cc15991353 100644 --- a/client/src/app/users/user-login-form/user-login-form.component.spec.ts +++ b/client/src/app/users/user-login-form/user-login-form.component.spec.ts @@ -1,6 +1,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; +import { SharedModule } from 'src/app/shared/shared.module'; import { UserLoginFormComponent } from './user-login-form.component'; @@ -11,7 +12,7 @@ describe('UserLoginFormComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ UserLoginFormComponent ], - imports: [ HttpClientTestingModule, RouterTestingModule ] + imports: [ HttpClientTestingModule, RouterTestingModule, SharedModule ] }) .compileComponents(); }); diff --git a/client/src/app/users/user-registration-form/user-registration-form.component.spec.ts b/client/src/app/users/user-registration-form/user-registration-form.component.spec.ts index cc0d6286c96ad09899b00e8605843b3670043f26..fba63e13bffeb844158a7c4bbe0ea8dc85bb73f0 100644 --- a/client/src/app/users/user-registration-form/user-registration-form.component.spec.ts +++ b/client/src/app/users/user-registration-form/user-registration-form.component.spec.ts @@ -1,6 +1,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; +import { SharedModule } from 'src/app/shared/shared.module'; import { UserRegistrationFormComponent } from './user-registration-form.component'; @@ -11,7 +12,7 @@ describe('UserRegistrationFormComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ UserRegistrationFormComponent ], - imports: [ HttpClientTestingModule, RouterTestingModule ] + imports: [ HttpClientTestingModule, RouterTestingModule, SharedModule ] }) .compileComponents(); }); diff --git a/server/src/controllers/postController/tests/postController.test.ts b/server/src/controllers/postController/tests/postController.test.ts index 265b2c09cd89060d7e2d757a0ab57490e4438682..c54df5312f60e80b9affba5de5952a76ca6bfdfc 100644 --- a/server/src/controllers/postController/tests/postController.test.ts +++ b/server/src/controllers/postController/tests/postController.test.ts @@ -22,14 +22,14 @@ describe("Test postController", () => { const result = await request(app).get("/api/post/1").send(); expect(result.status).toBe(200); - expect(result.body.data[0]?.title).toBe("test"); + expect(result.body.data[0]?.title).toBe("Skrik"); }); - it('Request /api/post/?categoryid=1 should return datas with categoryname = "Antikviteter og Kunst"', async () => { + it('Request /api/post/?categoryid=1 should return datas with categoryid = 1', async () => { const result = await request(app).get("/api/post/1").send(); expect(result.status).toBe(200); - expect(result.body.data[0]?.name).toBe("Antikviteter og Kunst"); + expect(result.body.data[0]?.categoryid).toBe(1); }); }); diff --git a/server/src/controllers/userController/tests/userController.test.ts b/server/src/controllers/userController/tests/userController.test.ts index 000014a281dbff84224cd11690b15b7dd88ca865..a2bed0323cbcd7b6715223418fc9bfae3613af7c 100644 --- a/server/src/controllers/userController/tests/userController.test.ts +++ b/server/src/controllers/userController/tests/userController.test.ts @@ -10,7 +10,7 @@ describe('Test userController', () => { console.log("...Test ending"); }); - it('Request /api/category should return request of 200!', async () => { + it('Request /api/user should return request of 200!', async () => { const result = await request(app) .get('/api/user') .send() @@ -18,8 +18,8 @@ describe('Test userController', () => { expect(result.status).toBe(200); }); - it('Request /api/category/1 should return data with name "zorg"!', async () => { - const result = await request(app).get('/api/user/1').send(); + it('Request /api/user/1 should return data with name "zorg"!', async () => { + const result = await request(app).get('/api/user').send(); expect(result.status).toBe(200); expect(result.body.data[0]?.username).toBe('zorg');