From 937e78a82391f17158e51d3b7f154b407da0d806 Mon Sep 17 00:00:00 2001 From: Ricardo Loureiro Date: Wed, 15 Nov 2023 16:14:22 -0300 Subject: [PATCH 01/21] =?UTF-8?q?#51=20-=20Service=20para=20descri=C3=A7?= =?UTF-8?q?=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gabriela Tiago Co-authored-by: Diego-Carlito --- src/app/services/video.service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/services/video.service.ts b/src/app/services/video.service.ts index 5b31cf0f..6c300151 100644 --- a/src/app/services/video.service.ts +++ b/src/app/services/video.service.ts @@ -41,4 +41,13 @@ export class VideoService { { headers: headers, observe: 'response' } ); } + + findDescriptionByVideoId(idVideo: number): Observable> { + let headers = new HttpHeaders({ clientkey: this.eduplayClientKey }); + + return this.http.get<{description: string}>( + `${this.resourceUrl}/${idVideo}`, + { headers: headers, observe: 'response' } + ); + } } From ad94aeec1daae7e7581afc89d5540ec97ee30b05 Mon Sep 17 00:00:00 2001 From: Ricardo Loureiro Date: Wed, 15 Nov 2023 16:15:14 -0300 Subject: [PATCH 02/21] =?UTF-8?q?#51=20-=20Componente=20viewer=20para=20de?= =?UTF-8?q?scri=C3=A7=C3=A3o=20no=20video?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gabriela Tiago Co-authored-by: Diego-Carlito --- src/app/pages/video-viewer/video-viewer.component.html | 8 ++++++-- src/app/pages/video-viewer/video-viewer.component.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index fc70fe4a..fc65c614 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -1,5 +1,5 @@
-
+
-

+

{{ videoTitle }}

+
+
+
+
diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 6588b956..89d2d97d 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -22,6 +22,7 @@ export class VideoViewerComponent implements OnInit { videoVersion: IVideoVersion = new VideoVersion(); videoMP4: IVideoDetails = new VideoDetails(); videoTitle: string = ''; + videoDescription: string = ''; constructor( private route: ActivatedRoute, @@ -40,6 +41,14 @@ export class VideoViewerComponent implements OnInit { ); this.videoMP4 = !!videoMP4Found ? videoMP4Found : this.videoMP4; + + if (params['idVideo']) { + this.videoService.findDescriptionByVideoId(params['idVideo']).subscribe( + (descriptionRes: HttpResponse<{description: string}>) => { + this.videoDescription = descriptionRes.body?.description || 'Descrição não disponível'; + } + ); + } }); }); From d7798c53faf8e13848b0bf60c2c7c73821373913 Mon Sep 17 00:00:00 2001 From: Ricardo Loureiro Date: Wed, 15 Nov 2023 16:49:19 -0300 Subject: [PATCH 03/21] =?UTF-8?q?#51=20-=20Adicionando=20mostrar=20para=20?= =?UTF-8?q?descri=C3=A7=C3=B5es=20longas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gabriela Tiago Co-authored-by: Diego-Carlito --- .../video-viewer/video-viewer.component.html | 25 ++++++++++++++++--- .../video-viewer/video-viewer.component.ts | 8 +++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index fc65c614..92508d66 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -8,13 +8,30 @@ controls >
-

+

{{ videoTitle }}

-
-
+
+
+ + + ... + + + + + + + + + + + + +
-
+ +
diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 89d2d97d..84fe03be 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -23,6 +23,12 @@ export class VideoViewerComponent implements OnInit { videoMP4: IVideoDetails = new VideoDetails(); videoTitle: string = ''; videoDescription: string = ''; + limiteCaracteres = 100; + mostrarCompleta = false; + + expandirDescricao() { + this.mostrarCompleta = !this.mostrarCompleta; + } constructor( private route: ActivatedRoute, @@ -45,7 +51,7 @@ export class VideoViewerComponent implements OnInit { if (params['idVideo']) { this.videoService.findDescriptionByVideoId(params['idVideo']).subscribe( (descriptionRes: HttpResponse<{description: string}>) => { - this.videoDescription = descriptionRes.body?.description || 'Descrição não disponível'; + this.videoDescription = descriptionRes.body?.description || ''; } ); } From 511341792c04045c1d17b61764caa81735f3eb5c Mon Sep 17 00:00:00 2001 From: Ricardo Loureiro Date: Wed, 15 Nov 2023 17:10:20 -0300 Subject: [PATCH 04/21] =?UTF-8?q?#51=20-=20Arrumando=20visualiza=C3=A7?= =?UTF-8?q?=C3=A3o=20da=20descri=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.css | 7 ++++++ .../video-viewer/video-viewer.component.html | 23 +++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.css b/src/app/pages/video-viewer/video-viewer.component.css index e69de29b..985a2bdf 100644 --- a/src/app/pages/video-viewer/video-viewer.component.css +++ b/src/app/pages/video-viewer/video-viewer.component.css @@ -0,0 +1,7 @@ +.clamped-description { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; + overflow: hidden; + } + \ No newline at end of file diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index 92508d66..99da8bf4 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -14,24 +14,17 @@

- - - ... - - - - - - + + + + +
- - - - - - +
+ + From 6f1c7a7be67b83bfa5db651f2113e77c85604dcd Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Thu, 16 Nov 2023 09:06:06 -0300 Subject: [PATCH 05/21] =?UTF-8?q?Adiciona=20servi=C3=A7o=20para=20realizar?= =?UTF-8?q?=20requi=C3=A7=C3=A3o=20de=20um=20v=C3=ADdeo=20pelo=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/services/video.service.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/services/video.service.ts b/src/app/services/video.service.ts index 6c300151..1bf9545d 100644 --- a/src/app/services/video.service.ts +++ b/src/app/services/video.service.ts @@ -5,7 +5,7 @@ import { EDUPLAY_API_URL, UNB_ID } from 'src/app/app.constant'; import { IVideo } from 'src/shared/model/video.model'; import { IEduplayVideosByInstitution } from 'src/shared/model/eduplay-by-institution.model'; import { IVideoVersion } from 'src/shared/model/video-version.model'; -import { EDUPLAY_CLIENT_KEY } from "../environment/environment"; +import { EDUPLAY_CLIENT_KEY } from '../environment/environment'; type VideoResponseType = HttpResponse; type VideoArrayResponseType = HttpResponse; @@ -50,4 +50,13 @@ export class VideoService { { headers: headers, observe: 'response' } ); } + + findVideoById(idVideo: number): Observable { + let headers = new HttpHeaders({ clientkey: this.eduplayClientKey }); + + return this.http.get(`${this.resourceUrl}/${idVideo}`, { + headers: headers, + observe: 'response', + }); + } } From 73544edd98f821c92a6f48728d6542b3bf38dccc Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Thu, 16 Nov 2023 09:07:51 -0300 Subject: [PATCH 06/21] =?UTF-8?q?Adiciona=20m=C3=A9todo=20para=20buscar=20?= =?UTF-8?q?informa=C3=A7=C3=B5es=20do=20v=C3=ADdeo=20obtidas=20na=20requis?= =?UTF-8?q?i=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 84fe03be..084a466f 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -10,14 +10,13 @@ import { VideoDetails, } from 'src/shared/model/video-details.model'; import { VideoService } from '../../services/video.service'; - +import { IVideo, Video } from 'src/shared/model/video.model'; @Component({ selector: 'app-video-viewer', templateUrl: './video-viewer.component.html', styleUrls: ['./video-viewer.component.css'], }) - export class VideoViewerComponent implements OnInit { videoVersion: IVideoVersion = new VideoVersion(); videoMP4: IVideoDetails = new VideoDetails(); @@ -25,6 +24,7 @@ export class VideoViewerComponent implements OnInit { videoDescription: string = ''; limiteCaracteres = 100; mostrarCompleta = false; + video: IVideo = new Video(); expandirDescricao() { this.mostrarCompleta = !this.mostrarCompleta; @@ -32,11 +32,11 @@ export class VideoViewerComponent implements OnInit { constructor( private route: ActivatedRoute, - private videoService: VideoService, - ) { } + private videoService: VideoService + ) {} ngOnInit(): void { - this.route.params.subscribe((params) => { + this.route.params.subscribe((params: { [x: string]: number }) => { this.videoService .findVideoVersionByVideoId(params['idVideo']) .subscribe((res: HttpResponse) => { @@ -58,9 +58,16 @@ export class VideoViewerComponent implements OnInit { }); }); - this.route.queryParams.subscribe((params) => { - this.videoTitle = params['title']; + this.route.params.subscribe((params: { [x: string]: number }) => { + this.videoService + .findVideoById(params['idVideo']) + .subscribe((res: HttpResponse) => { + this.video = !!res?.body ? res.body : this.video; + }); }); + this.route.queryParams.subscribe((params: { [x: string]: string }) => { + this.videoTitle = params['title']; + }); } } From a2cf9058894fd4b87e4a8919452d18e0deee13c9 Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Thu, 16 Nov 2023 10:45:08 -0300 Subject: [PATCH 07/21] =?UTF-8?q?Adiciona=20teste=20para=20m=C3=A9todo=20d?= =?UTF-8?q?e=20buscar=20video=20pelo=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/services/video.service.spec.ts | 470 ++++++++++++++----------- 1 file changed, 269 insertions(+), 201 deletions(-) diff --git a/src/app/services/video.service.spec.ts b/src/app/services/video.service.spec.ts index 84e13dd8..ccd34e35 100644 --- a/src/app/services/video.service.spec.ts +++ b/src/app/services/video.service.spec.ts @@ -1,5 +1,8 @@ import { TestBed } from '@angular/core/testing'; -import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { + HttpClientTestingModule, + HttpTestingController, +} from '@angular/common/http/testing'; import { EDUPLAY_API_URL, UNB_ID } from 'src/app/app.constant'; import { EDUPLAY_CLIENT_KEY } from '../environment/environment'; import { VideoService } from './video.service'; @@ -11,7 +14,7 @@ describe('VideoService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], - providers: [VideoService] + providers: [VideoService], }); service = TestBed.inject(VideoService); @@ -29,238 +32,248 @@ describe('VideoService', () => { describe('findAll', () => { it('should return all videos by institution', () => { const mockData = { - "qtTotal": 110, - "videoList": [ + qtTotal: 110, + videoList: [ { - "id": 142471, - "title": "Sala de Reunião 04 do NTE", - "description": "Sala de Reunião 04 do NTE", - "keywords": "Sala de Reunião 04 do NTE", - "visibility": "PUBLIC", - "duration": 561835, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 41, - "qtLikes": 0, - "images": [ + id: 142471, + title: 'Sala de Reunião 04 do NTE', + description: 'Sala de Reunião 04 do NTE', + keywords: 'Sala de Reunião 04 do NTE', + visibility: 'PUBLIC', + duration: 561835, + generateLibras: true, + generateSubtitle: true, + qtAccess: 41, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1630091029232.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1630091029232.png', + }, ], - "userOwner": { - "id": 30684, - "name": "Fabio Ferreira de Oliveira" - } + userOwner: { + id: 30684, + name: 'Fabio Ferreira de Oliveira', + }, }, { - "id": 180741, - "title": "Mulheres que inspiram - Profa. Carla Rocha", - "description": "

Entrevista com a Professora Carla Rocha (UnB) como parte do projeto Mulheres que Inspiram. Adeia surgiu através da leitura do texto Eu programo, tu programas, elx hackea: mulheres hackers e perspectivas tecnopolíticas e do interesse em dar visibilidade a mulheres que atuam na área de software livre e educação aberta. Transcrição do áudio disponível..em https://pt.wikiversity.org/wiki/Educa%C3%A7%C3%A3o_Aberta/Mulheres_que_inspiram


Disponível com uma licença CC-BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/).

", - "keywords": "mulheres, computação, professora, ciência da computação, gênero", - "visibility": "PUBLIC", - "duration": 508459, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 36, - "qtLikes": 0, - "images": [ + id: 180741, + title: 'Mulheres que inspiram - Profa. Carla Rocha', + description: + '

Entrevista com a Professora Carla Rocha (UnB) como parte do projeto Mulheres que Inspiram. Adeia surgiu através da leitura do texto Eu programo, tu programas, elx hackea: mulheres hackers e perspectivas tecnopolíticas e do interesse em dar visibilidade a mulheres que atuam na área de software livre e educação aberta. Transcrição do áudio disponível..em https://pt.wikiversity.org/wiki/Educa%C3%A7%C3%A3o_Aberta/Mulheres_que_inspiram


Disponível com uma licença CC-BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/).

', + keywords: + 'mulheres, computação, professora, ciência da computação, gênero', + visibility: 'PUBLIC', + duration: 508459, + generateLibras: true, + generateSubtitle: true, + qtAccess: 36, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1679168690066.jpg" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1679168690066.jpg', + }, ], - "userOwner": { - "id": 44590, - "name": "Tel Amiel", - "avatar": "https://eduplay.rnp.br/portal/assets/users/images/1683107832084.jpg" - } + userOwner: { + id: 44590, + name: 'Tel Amiel', + avatar: + 'https://eduplay.rnp.br/portal/assets/users/images/1683107832084.jpg', + }, }, { - "id": 184760, - "title": "Dia 4: Minicurso de Extensão - UnB - Racontez-nous votre histoire", - "keywords": "mconf", - "visibility": "PUBLIC", - "duration": 5161003, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 24, - "qtLikes": 0, - "images": [ + id: 184760, + title: + 'Dia 4: Minicurso de Extensão - UnB - Racontez-nous votre histoire', + keywords: 'mconf', + visibility: 'PUBLIC', + duration: 5161003, + generateLibras: true, + generateSubtitle: true, + qtAccess: 24, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1687455434581.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1687455434581.png', + }, ], - "userOwner": { - "id": 45799, - "name": "Denise Gisele de Britto Damasco" - } + userOwner: { + id: 45799, + name: 'Denise Gisele de Britto Damasco', + }, }, { - "id": 184518, - "title": "Dia 1: Minicurso de Extensão - UnB - Présentation Denise Damasco", - "keywords": "mconf", - "visibility": "PUBLIC", - "duration": 3532366, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 24, - "qtLikes": 0, - "images": [ + id: 184518, + title: + 'Dia 1: Minicurso de Extensão - UnB - Présentation Denise Damasco', + keywords: 'mconf', + visibility: 'PUBLIC', + duration: 3532366, + generateLibras: true, + generateSubtitle: true, + qtAccess: 24, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1686872273578.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1686872273578.png', + }, ], - "userOwner": { - "id": 45799, - "name": "Denise Gisele de Britto Damasco" - } + userOwner: { + id: 45799, + name: 'Denise Gisele de Britto Damasco', + }, }, { - "id": 111840, - "title": "Aulas Síncronas ás 14 horas as terças-feiras e quintas-feiras", - "description": "Aulas Síncronas ás 14 horas as terças-feiras e quintas-feiras", - "keywords": "Aulas Síncronas ás 14 horas as terças-feiras e quintas-feiras", - "visibility": "PUBLIC", - "duration": 6111573, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 38, - "qtLikes": 0, - "images": [ + id: 111840, + title: + 'Aulas Síncronas ás 14 horas as terças-feiras e quintas-feiras', + description: + 'Aulas Síncronas ás 14 horas as terças-feiras e quintas-feiras', + keywords: + 'Aulas Síncronas ás 14 horas as terças-feiras e quintas-feiras', + visibility: 'PUBLIC', + duration: 6111573, + generateLibras: true, + generateSubtitle: true, + qtAccess: 38, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1621608406505.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1621608406505.png', + }, ], - "userOwner": { - "id": 28703, - "name": "Jorlandio Francisco Felix" - } + userOwner: { + id: 28703, + name: 'Jorlandio Francisco Felix', + }, }, { - "id": 141981, - "title": "Liliane Campos Machado", - "description": "Liliane Campos Machado", - "keywords": "Liliane Campos Machado", - "visibility": "PUBLIC", - "duration": 6482260, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 162, - "qtLikes": 0, - "images": [ + id: 141981, + title: 'Liliane Campos Machado', + description: 'Liliane Campos Machado', + keywords: 'Liliane Campos Machado', + visibility: 'PUBLIC', + duration: 6482260, + generateLibras: true, + generateSubtitle: true, + qtAccess: 162, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1629828306049.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1629828306049.png', + }, ], - "userOwner": { - "id": 29754, - "name": "Liliane Campos Machado" - } + userOwner: { + id: 29754, + name: 'Liliane Campos Machado', + }, }, { - "id": 111535, - "title": "NTE videoconferências", - "description": "NTE videoconferências", - "keywords": "NTE videoconferências", - "visibility": "PUBLIC", - "duration": 7508000, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 73, - "qtLikes": 0, - "images": [ + id: 111535, + title: 'NTE videoconferências', + description: 'NTE videoconferências', + keywords: 'NTE videoconferências', + visibility: 'PUBLIC', + duration: 7508000, + generateLibras: true, + generateSubtitle: true, + qtAccess: 73, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1621383436732.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1621383436732.png', + }, ], - "userOwner": { - "id": 19994, - "name": "Endryl Francelino de Souza" - } + userOwner: { + id: 19994, + name: 'Endryl Francelino de Souza', + }, }, { - "id": 184759, - "title": "Dia 3: Minicurso de Extensão - UnB - Racontez-nous votre histoire", - "keywords": "mconf", - "visibility": "PUBLIC", - "duration": 5175560, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 24, - "qtLikes": 0, - "images": [ + id: 184759, + title: + 'Dia 3: Minicurso de Extensão - UnB - Racontez-nous votre histoire', + keywords: 'mconf', + visibility: 'PUBLIC', + duration: 5175560, + generateLibras: true, + generateSubtitle: true, + qtAccess: 24, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1687454416354.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1687454416354.png', + }, ], - "userOwner": { - "id": 45799, - "name": "Denise Gisele de Britto Damasco" - } + userOwner: { + id: 45799, + name: 'Denise Gisele de Britto Damasco', + }, }, { - "id": 179217, - "title": "Patricia Tuxi dos Santos", - "description": "Patricia Tuxi dos Santos", - "keywords": "Patricia Tuxi dos Santos", - "visibility": "PUBLIC", - "duration": 109163, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 42, - "qtLikes": 0, - "images": [ + id: 179217, + title: 'Patricia Tuxi dos Santos', + description: 'Patricia Tuxi dos Santos', + keywords: 'Patricia Tuxi dos Santos', + visibility: 'PUBLIC', + duration: 109163, + generateLibras: true, + generateSubtitle: true, + qtAccess: 42, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1675876887636.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1675876887636.png', + }, ], - "userOwner": { - "id": 44725, - "name": "Patricia Tuxi dos Santos" - } + userOwner: { + id: 44725, + name: 'Patricia Tuxi dos Santos', + }, }, { - "id": 142458, - "title": "Sala de Reunião 04 do NTE", - "description": "Sala de Reunião 04 do NTE", - "keywords": "Sala de Reunião 04 do NTE", - "visibility": "PUBLIC", - "duration": 2750269, - "generateLibras": true, - "generateSubtitle": true, - "qtAccess": 75, - "qtLikes": 0, - "images": [ + id: 142458, + title: 'Sala de Reunião 04 do NTE', + description: 'Sala de Reunião 04 do NTE', + keywords: 'Sala de Reunião 04 do NTE', + visibility: 'PUBLIC', + duration: 2750269, + generateLibras: true, + generateSubtitle: true, + qtAccess: 75, + qtLikes: 0, + images: [ { - "type": "DEFAULT", - "href": "https://eduplay.rnp.br/portal/assets/videos/images/1630088527294.png" - } + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1630088527294.png', + }, ], - "userOwner": { - "id": 30684, - "name": "Fabio Ferreira de Oliveira" - } - } - ] + userOwner: { + id: 30684, + name: 'Fabio Ferreira de Oliveira', + }, + }, + ], }; - service.findAll().subscribe(response => { + service.findAll().subscribe((response) => { expect(response.body).toEqual(mockData); }); - const req = httpMock.expectOne(`${EDUPLAY_API_URL}video?institution=${UNB_ID}`); + const req = httpMock.expectOne( + `${EDUPLAY_API_URL}video?institution=${UNB_ID}` + ); expect(req.request.method).toBe('GET'); expect(req.request.headers.get('clientkey')).toBe(EDUPLAY_CLIENT_KEY); - req.flush(mockData); }); }); @@ -269,28 +282,30 @@ describe('VideoService', () => { it('should return video version by video ID', () => { const mockId = 137155; const mockData = { - "videoVersionList": [ + videoVersionList: [ { - "id": 198889, - "fileFormat": "MP4", - "bitRate": 400, - "frameRate": 0.0, - "frameWidth": 640, - "frameHeight": 360, - "url": "https://cdn.eduplay.rnp.br/route/GFo4bTLBMlME/1625266532841.mp4?s=aHR0cHM6Ly9tZWRpYS5lZHVwbGF5LnJucC5ici9tZWRpYS9HRm80YlRMQk1sTUUvMTYyNTI2NjUzMjg0MS5tcDQ_bT1hOHRCay1Ed1ZIX2thOGllMlBoRkxB&p=0&m=9xeIa_Ss6Z_kmZ-wjeczWg" + id: 198889, + fileFormat: 'MP4', + bitRate: 400, + frameRate: 0.0, + frameWidth: 640, + frameHeight: 360, + url: 'https://cdn.eduplay.rnp.br/route/GFo4bTLBMlME/1625266532841.mp4?s=aHR0cHM6Ly9tZWRpYS5lZHVwbGF5LnJucC5ici9tZWRpYS9HRm80YlRMQk1sTUUvMTYyNTI2NjUzMjg0MS5tcDQ_bT1hOHRCay1Ed1ZIX2thOGllMlBoRkxB&p=0&m=9xeIa_Ss6Z_kmZ-wjeczWg', }, { - "fileFormat": "HLS", - "url": "https://cdn.eduplay.rnp.br/route/GFo4bTLBMlME/index.m3u8?s=aHR0cHM6Ly9tZWRpYS5lZHVwbGF5LnJucC5ici9tZWRpYS9HRm80YlRMQk1sTUUvaW5kZXgubTN1OD94PTEmbT01Zi04czV1TmJRelM5V3BrblpSRTRn&x=1&p=0&m=q_L7ZIxmqATQnM0n7KREyg" - } - ] + fileFormat: 'HLS', + url: 'https://cdn.eduplay.rnp.br/route/GFo4bTLBMlME/index.m3u8?s=aHR0cHM6Ly9tZWRpYS5lZHVwbGF5LnJucC5ici9tZWRpYS9HRm80YlRMQk1sTUUvaW5kZXgubTN1OD94PTEmbT01Zi04czV1TmJRelM5V3BrblpSRTRn&x=1&p=0&m=q_L7ZIxmqATQnM0n7KREyg', + }, + ], }; - service.findVideoVersionByVideoId(mockId).subscribe(response => { + service.findVideoVersionByVideoId(mockId).subscribe((response) => { expect(response.body).toEqual(mockData); }); - const req = httpMock.expectOne(`${EDUPLAY_API_URL}video/versions/${mockId}`); + const req = httpMock.expectOne( + `${EDUPLAY_API_URL}video/versions/${mockId}` + ); expect(req.request.method).toBe('GET'); expect(req.request.headers.get('clientkey')).toBe(EDUPLAY_CLIENT_KEY); @@ -298,4 +313,57 @@ describe('VideoService', () => { }); }); + describe('findVideoById', () => { + it('should return a video', () => { + const mockId = 185814; + const mockData = { + id: 185814, + title: 'Tutorial - Etherpad', + description: + '

Tutorial do projeto Escolha Livre (escolhalivre.org.br) apresentando o Etherpad (como o pad.riseup.net), um software livre.


Produzido pela Iniciativa Educação Aberta (aberta.org.br).


Licença de uso: CC-BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/).



', + keywords: 'software livre, escrita colaborativa, FOSS, colaboração', + visibility: 'PUBLIC', + duration: 250367, + embed: + '', + generateLibras: true, + generateSubtitle: true, + qtAccess: 28, + qtLikes: 0, + images: [ + { + type: 'DEFAULT', + href: 'https://eduplay.rnp.br/portal/assets/videos/images/1689705451523.jpg', + }, + ], + institution: { + id: 216, + name: 'Universidade de Brasilia', + code: 'UNB', + }, + userOwner: { + id: 44590, + name: 'Tel Amiel', + avatar: + 'https://eduplay.rnp.br/portal/assets/users/images/1683107832084.jpg', + }, + channels: [ + { + id: 183065, + name: 'Cátedra UNESCO em EaD', + }, + ], + }; + + service.findVideoById(mockId).subscribe((response) => { + expect(response.body).toEqual(mockData); + }); + + const req = httpMock.expectOne(`${EDUPLAY_API_URL}video/${mockId}`); + expect(req.request.method).toBe('GET'); + expect(req.request.headers.get('clientkey')).toBe(EDUPLAY_CLIENT_KEY); + + req.flush(mockData); + }); + }); }); From 71cd86e678ddac5080d309ec9ae0b1f25779e419 Mon Sep 17 00:00:00 2001 From: Diego Carlito Date: Thu, 16 Nov 2023 18:53:25 -0300 Subject: [PATCH 08/21] =?UTF-8?q?Adiciona=20teste=20para=20m=C3=A9todo=20d?= =?UTF-8?q?e=20expandir=20descri=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/app/pages/video-viewer/video-viewer.component.spec.ts b/src/app/pages/video-viewer/video-viewer.component.spec.ts index e682490b..d0017a9b 100644 --- a/src/app/pages/video-viewer/video-viewer.component.spec.ts +++ b/src/app/pages/video-viewer/video-viewer.component.spec.ts @@ -26,4 +26,17 @@ describe('VideoViewerComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should toggle mostrarCompleta property', () => { + expect(component.mostrarCompleta).toBe(false); + + component.expandirDescricao(); + + expect(component.mostrarCompleta).toBe(true); + + component.expandirDescricao(); + + expect(component.mostrarCompleta).toBe(false); + }); + }); From 76c0ef1d2d2b9ed3513c010fb6a2bfd3a304be75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vit=C3=B3ria=20Aquere=20Matos?= Date: Fri, 17 Nov 2023 08:22:17 -0300 Subject: [PATCH 09/21] =?UTF-8?q?remo=C3=A7=C3=A3o=20do=20t=C3=ADtulo=20pe?= =?UTF-8?q?lo=20par=C3=A2metro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/pages/video-viewer/video-viewer.component.html | 2 +- src/app/pages/video-viewer/video-viewer.component.ts | 4 +--- src/app/pages/video/video.component.html | 4 ++-- src/shared/model/video.model.ts | 5 +++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index 99da8bf4..42d4ae01 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -9,7 +9,7 @@ >

- {{ videoTitle }} + {{ video.title }}

diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 084a466f..846c3c19 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -66,8 +66,6 @@ export class VideoViewerComponent implements OnInit { }); }); - this.route.queryParams.subscribe((params: { [x: string]: string }) => { - this.videoTitle = params['title']; - }); + } } diff --git a/src/app/pages/video/video.component.html b/src/app/pages/video/video.component.html index 09bc3e7e..7e7c71b5 100644 --- a/src/app/pages/video/video.component.html +++ b/src/app/pages/video/video.component.html @@ -4,8 +4,8 @@
+ class="cursor-pointer" + > {{ video.title }} Date: Fri, 17 Nov 2023 09:14:29 -0300 Subject: [PATCH 10/21] =?UTF-8?q?altera=20link=20de=20exibi=C3=A7=C3=A3o?= =?UTF-8?q?=20do=20v=C3=ADdeo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.html | 16 ++++++++++++++-- .../pages/video-viewer/video-viewer.component.ts | 10 ++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index acb98070..a46aac0e 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -1,17 +1,29 @@
- + > --> +

{{ video.title }}

+
+
+ + + + +
+ +
+
+
diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 846c3c19..3b310daa 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -11,6 +11,7 @@ import { } from 'src/shared/model/video-details.model'; import { VideoService } from '../../services/video.service'; import { IVideo, Video } from 'src/shared/model/video.model'; +import {DomSanitizer, SafeHtml} from '@angular/platform-browser'; @Component({ selector: 'app-video-viewer', @@ -25,6 +26,7 @@ export class VideoViewerComponent implements OnInit { limiteCaracteres = 100; mostrarCompleta = false; video: IVideo = new Video(); + videoUrl!: SafeHtml; expandirDescricao() { this.mostrarCompleta = !this.mostrarCompleta; @@ -32,7 +34,8 @@ export class VideoViewerComponent implements OnInit { constructor( private route: ActivatedRoute, - private videoService: VideoService + private videoService: VideoService, + private domSanitizer:DomSanitizer ) {} ngOnInit(): void { @@ -63,9 +66,12 @@ export class VideoViewerComponent implements OnInit { .findVideoById(params['idVideo']) .subscribe((res: HttpResponse) => { this.video = !!res?.body ? res.body : this.video; + this.videoUrl = this.domSanitizer.bypassSecurityTrustHtml(this.video.embed as string); + this.videoDescription = this.video.description?this.video.description:''; + console.log(this.video) }); }); - + } } From 7bcc712998ee7d935486c1e6add08bd481d83f98 Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Fri, 17 Nov 2023 11:07:36 -0300 Subject: [PATCH 11/21] =?UTF-8?q?Remove=20m=C3=A9todos=20que=20n=C3=A3o=20?= =?UTF-8?q?s=C3=A3o=20mais=20utilizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.html | 33 ++++++++----- .../video-viewer/video-viewer.component.ts | 49 ++++--------------- src/app/services/video.service.spec.ts | 35 ------------- src/app/services/video.service.ts | 20 -------- 4 files changed, 29 insertions(+), 108 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index a46aac0e..c484ee09 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -1,31 +1,38 @@
-
-

+

{{ video.title }}

-
+
- - + +
- +
- +
diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 3b310daa..ae34e2e2 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -1,17 +1,9 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; -import { - IVideoVersion, - VideoVersion, -} from 'src/shared/model/video-version.model'; -import { - IVideoDetails, - VideoDetails, -} from 'src/shared/model/video-details.model'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { VideoService } from '../../services/video.service'; import { IVideo, Video } from 'src/shared/model/video.model'; -import {DomSanitizer, SafeHtml} from '@angular/platform-browser'; @Component({ selector: 'app-video-viewer', @@ -19,9 +11,6 @@ import {DomSanitizer, SafeHtml} from '@angular/platform-browser'; styleUrls: ['./video-viewer.component.css'], }) export class VideoViewerComponent implements OnInit { - videoVersion: IVideoVersion = new VideoVersion(); - videoMP4: IVideoDetails = new VideoDetails(); - videoTitle: string = ''; videoDescription: string = ''; limiteCaracteres = 100; mostrarCompleta = false; @@ -35,43 +24,23 @@ export class VideoViewerComponent implements OnInit { constructor( private route: ActivatedRoute, private videoService: VideoService, - private domSanitizer:DomSanitizer + private domSanitizer: DomSanitizer ) {} ngOnInit(): void { - this.route.params.subscribe((params: { [x: string]: number }) => { - this.videoService - .findVideoVersionByVideoId(params['idVideo']) - .subscribe((res: HttpResponse) => { - this.videoVersion = !!res.body ? res.body : this.videoVersion; - - const videoMP4Found = this.videoVersion.videoVersionList?.find( - (video) => video.fileFormat === 'MP4' - ); - - this.videoMP4 = !!videoMP4Found ? videoMP4Found : this.videoMP4; - - if (params['idVideo']) { - this.videoService.findDescriptionByVideoId(params['idVideo']).subscribe( - (descriptionRes: HttpResponse<{description: string}>) => { - this.videoDescription = descriptionRes.body?.description || ''; - } - ); - } - }); - }); - this.route.params.subscribe((params: { [x: string]: number }) => { this.videoService .findVideoById(params['idVideo']) .subscribe((res: HttpResponse) => { this.video = !!res?.body ? res.body : this.video; - this.videoUrl = this.domSanitizer.bypassSecurityTrustHtml(this.video.embed as string); - this.videoDescription = this.video.description?this.video.description:''; - console.log(this.video) + + this.videoUrl = this.domSanitizer.bypassSecurityTrustHtml( + this.video.embed as string + ); + this.videoDescription = this.video.description + ? this.video.description + : ''; }); }); - - } } diff --git a/src/app/services/video.service.spec.ts b/src/app/services/video.service.spec.ts index ccd34e35..accb7896 100644 --- a/src/app/services/video.service.spec.ts +++ b/src/app/services/video.service.spec.ts @@ -278,41 +278,6 @@ describe('VideoService', () => { }); }); - describe('findVideoVersionByVideoId', () => { - it('should return video version by video ID', () => { - const mockId = 137155; - const mockData = { - videoVersionList: [ - { - id: 198889, - fileFormat: 'MP4', - bitRate: 400, - frameRate: 0.0, - frameWidth: 640, - frameHeight: 360, - url: 'https://cdn.eduplay.rnp.br/route/GFo4bTLBMlME/1625266532841.mp4?s=aHR0cHM6Ly9tZWRpYS5lZHVwbGF5LnJucC5ici9tZWRpYS9HRm80YlRMQk1sTUUvMTYyNTI2NjUzMjg0MS5tcDQ_bT1hOHRCay1Ed1ZIX2thOGllMlBoRkxB&p=0&m=9xeIa_Ss6Z_kmZ-wjeczWg', - }, - { - fileFormat: 'HLS', - url: 'https://cdn.eduplay.rnp.br/route/GFo4bTLBMlME/index.m3u8?s=aHR0cHM6Ly9tZWRpYS5lZHVwbGF5LnJucC5ici9tZWRpYS9HRm80YlRMQk1sTUUvaW5kZXgubTN1OD94PTEmbT01Zi04czV1TmJRelM5V3BrblpSRTRn&x=1&p=0&m=q_L7ZIxmqATQnM0n7KREyg', - }, - ], - }; - - service.findVideoVersionByVideoId(mockId).subscribe((response) => { - expect(response.body).toEqual(mockData); - }); - - const req = httpMock.expectOne( - `${EDUPLAY_API_URL}video/versions/${mockId}` - ); - expect(req.request.method).toBe('GET'); - expect(req.request.headers.get('clientkey')).toBe(EDUPLAY_CLIENT_KEY); - - req.flush(mockData); - }); - }); - describe('findVideoById', () => { it('should return a video', () => { const mockId = 185814; diff --git a/src/app/services/video.service.ts b/src/app/services/video.service.ts index 1bf9545d..896b483b 100644 --- a/src/app/services/video.service.ts +++ b/src/app/services/video.service.ts @@ -31,26 +31,6 @@ export class VideoService { ); } - findVideoVersionByVideoId( - idVideo: number - ): Observable { - let headers = new HttpHeaders({ clientkey: this.eduplayClientKey }); - - return this.http.get( - `${this.resourceUrl}/versions/${idVideo}`, - { headers: headers, observe: 'response' } - ); - } - - findDescriptionByVideoId(idVideo: number): Observable> { - let headers = new HttpHeaders({ clientkey: this.eduplayClientKey }); - - return this.http.get<{description: string}>( - `${this.resourceUrl}/${idVideo}`, - { headers: headers, observe: 'response' } - ); - } - findVideoById(idVideo: number): Observable { let headers = new HttpHeaders({ clientkey: this.eduplayClientKey }); From 2921b851b8dbae96f89cfa1fc542722595296407 Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Fri, 17 Nov 2023 22:47:21 -0300 Subject: [PATCH 12/21] =?UTF-8?q?Separa=20a=20url=20do=20v=C3=ADdeo=20prov?= =?UTF-8?q?eniente=20da=20propriedade=20embed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index ae34e2e2..90880e8d 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -21,6 +21,12 @@ export class VideoViewerComponent implements OnInit { this.mostrarCompleta = !this.mostrarCompleta; } + extractVideoUrl(embedCode: string): string | null { + const regex = /) => { this.video = !!res?.body ? res.body : this.video; - this.videoUrl = this.domSanitizer.bypassSecurityTrustHtml( - this.video.embed as string - ); + const embedCode = this.video.embed as string; + const url = this.extractVideoUrl(embedCode); + + if (url) { + this.videoUrl = + this.domSanitizer.bypassSecurityTrustResourceUrl(url); + } + this.videoDescription = this.video.description ? this.video.description : ''; From e61413bbab96e1a9bcb7e1edb19643aeb3b0ec4f Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Fri, 17 Nov 2023 22:47:51 -0300 Subject: [PATCH 13/21] =?UTF-8?q?Altera=C3=A7=C3=B5es=20de=20responsividad?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer/video-viewer.component.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index c484ee09..60e31d90 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -1,14 +1,19 @@
-
-
+
+

{{ video.title }}

-
+
Date: Fri, 17 Nov 2023 23:06:06 -0300 Subject: [PATCH 14/21] =?UTF-8?q?Adiciona=20teste=20para=20o=20m=C3=A9todo?= =?UTF-8?q?=20de=20extra=C3=A7=C3=A3o=20de=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../video-viewer.component.spec.ts | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.spec.ts b/src/app/pages/video-viewer/video-viewer.component.spec.ts index 5e0db1f7..2e0c18de 100644 --- a/src/app/pages/video-viewer/video-viewer.component.spec.ts +++ b/src/app/pages/video-viewer/video-viewer.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { RouterTestingModule } from "@angular/router/testing"; +import { RouterTestingModule } from '@angular/router/testing'; import { VideoViewerComponent } from './video-viewer.component'; import { SafePipe } from 'src/app/pipes/safe.pipe'; import { VideoCommentComponent } from 'src/app/components/video-comment/video-comment.component'; @@ -14,11 +14,13 @@ describe('VideoViewerComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [VideoViewerComponent, SafePipe, VideoCommentComponent], - imports: [HttpClientTestingModule, RouterTestingModule, ReactiveFormsModule], - providers: [{ provide: VideoService }, FormBuilder] - - }) - .compileComponents(); + imports: [ + HttpClientTestingModule, + RouterTestingModule, + ReactiveFormsModule, + ], + providers: [{ provide: VideoService }, FormBuilder], + }).compileComponents(); fixture = TestBed.createComponent(VideoViewerComponent); component = fixture.componentInstance; @@ -40,5 +42,23 @@ describe('VideoViewerComponent', () => { expect(component.mostrarCompleta).toBe(false); }); - + + describe('Getting the video url', () => { + it('should extract video URL from embed code', () => { + const embedCode = + ''; + const extractedUrl = component.extractVideoUrl(embedCode); + + expect(extractedUrl).toBe( + 'https://eduplay.rnp.br/portal/video/embed/190486' + ); + }); + + it('should return null for invalid embed code', () => { + const invalidEmbedCode = ''; + const extractedUrl = component.extractVideoUrl(invalidEmbedCode); + + expect(extractedUrl).toBeNull(); + }); + }); }); From adc0a4a9d249da6cb2dc521cea93c95607f62ded Mon Sep 17 00:00:00 2001 From: Marcos Castilhos <221008300@aluno.unb.br> Date: Sat, 18 Nov 2023 14:13:32 -0300 Subject: [PATCH 15/21] corrige ativar conta tela de login --- src/app/app-routing.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 79b9bea2..e78cb473 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -24,7 +24,7 @@ const routes: Routes = [ { path: 'changePassword', component: ResetPasswordComponent, canActivate: [WithTokenGuard], }, { path: 'videos', component: VideoComponent, canActivate: [AuthGuard], }, { path: 'video/:idVideo', component: VideoViewerComponent, canActivate: [AuthGuard], }, - { path: 'activeAccount', component: ActiveAccountComponent, canActivate: [AuthGuard], }, + { path: 'activeAccount', component: ActiveAccountComponent, canActivate: [WithTokenGuard], }, { path: 'suggestAgenda', component: SuggestAgendaComponent, canActivate: [AuthGuard], }, { path: 'participate', component: ParticipateComponent, canActivate: [AuthGuard], }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard], }, From 8868493a1587a3dcd5242009be88f47cd3a3d264 Mon Sep 17 00:00:00 2001 From: GabrielaTiago Date: Sat, 18 Nov 2023 18:44:36 -0300 Subject: [PATCH 16/21] Merge 'fix-tests' into 51-descricao --- src/app/app-routing.module.ts | 2 +- src/app/app.component.spec.ts | 8 +- .../background/background.component.spec.ts | 7 +- .../video-comment/video-comment.component.ts | 4 +- src/app/guard/with-token.guard.spec.ts | 21 ++++- .../active-account.component.spec.ts | 80 +++++++++++++++++- .../active-account.component.ts | 9 +- ...check-code-rest-password.component.spec.ts | 30 +++++-- .../check-code-rest-password.component.ts | 5 +- .../edit-user/edit-user.component.spec.ts | 54 +++++++++--- .../pages/edit-user/edit-user.component.ts | 17 ++-- src/app/pages/login/login.component.spec.ts | 42 +++++----- src/app/pages/login/login.component.ts | 13 ++- src/app/pages/profile/profile.component.html | 5 +- .../pages/profile/profile.component.spec.ts | 84 ++++++++++++++++--- src/app/pages/profile/profile.component.ts | 15 ++-- .../pages/register/register.component.spec.ts | 56 ++++++++++--- src/app/pages/register/register.component.ts | 23 +++-- .../reset-password.component.spec.ts | 19 ++++- .../suggest-agenda.component.spec.ts | 17 +++- .../video-viewer.component.spec.ts | 10 ++- .../video-viewer/video-viewer.component.ts | 41 ++++----- src/app/services/alert.service.spec.ts | 21 ++++- src/app/services/alert.service.ts | 22 +++-- src/app/services/auth.service.spec.ts | 7 +- src/app/services/email.service.spec.ts | 33 +++++++- src/shared/model/http-error.model.ts | 3 + 27 files changed, 505 insertions(+), 143 deletions(-) create mode 100644 src/shared/model/http-error.model.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 79b9bea2..e78cb473 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -24,7 +24,7 @@ const routes: Routes = [ { path: 'changePassword', component: ResetPasswordComponent, canActivate: [WithTokenGuard], }, { path: 'videos', component: VideoComponent, canActivate: [AuthGuard], }, { path: 'video/:idVideo', component: VideoViewerComponent, canActivate: [AuthGuard], }, - { path: 'activeAccount', component: ActiveAccountComponent, canActivate: [AuthGuard], }, + { path: 'activeAccount', component: ActiveAccountComponent, canActivate: [WithTokenGuard], }, { path: 'suggestAgenda', component: SuggestAgendaComponent, canActivate: [AuthGuard], }, { path: 'participate', component: ParticipateComponent, canActivate: [AuthGuard], }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard], }, diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 3e256296..4f69703d 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -2,6 +2,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; import { BackgroundComponent } from './components/background/background.component'; +import { ToastModule } from 'primeng/toast'; +import { ConfirmationService, MessageService } from 'primeng/api'; +import { ConfirmDialogModule } from 'primeng/confirmdialog'; +import { MenuModule } from 'primeng/menu'; + describe('AppComponent', () => { let component: AppComponent; @@ -9,8 +14,9 @@ describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [RouterTestingModule], + imports: [RouterTestingModule, ToastModule, ConfirmDialogModule, MenuModule], declarations: [AppComponent, BackgroundComponent], + providers: [MessageService, ConfirmationService], }).compileComponents(); fixture = TestBed.createComponent(AppComponent); diff --git a/src/app/components/background/background.component.spec.ts b/src/app/components/background/background.component.spec.ts index 53021daf..ef9c0a4c 100644 --- a/src/app/components/background/background.component.spec.ts +++ b/src/app/components/background/background.component.spec.ts @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BackgroundComponent } from './background.component'; import { RouterTestingModule } from '@angular/router/testing'; +import { MenuModule } from 'primeng/menu'; describe('BackgroundComponent', () => { let component: BackgroundComponent; @@ -9,10 +10,10 @@ describe('BackgroundComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ BackgroundComponent ], - imports: [RouterTestingModule] + declarations: [BackgroundComponent], + imports: [RouterTestingModule, MenuModule] }) - .compileComponents(); + .compileComponents(); fixture = TestBed.createComponent(BackgroundComponent); component = fixture.componentInstance; diff --git a/src/app/components/video-comment/video-comment.component.ts b/src/app/components/video-comment/video-comment.component.ts index aac764ea..88b26108 100644 --- a/src/app/components/video-comment/video-comment.component.ts +++ b/src/app/components/video-comment/video-comment.component.ts @@ -35,9 +35,7 @@ export class VideoCommentComponent implements OnInit { comment: ['', [Validators.required, Validators.maxLength(1000)]], }, ); - this.route.params.subscribe((params) => { - this.video_id = params['idVideo']; - }) + this.video_id = this.route.snapshot.params['idVideo']; if (this.authService.isAuthenticated()) { this.setUserIdFromToken(localStorage.getItem('token') as string); } else { diff --git a/src/app/guard/with-token.guard.spec.ts b/src/app/guard/with-token.guard.spec.ts index 15c88049..e49f3ec7 100644 --- a/src/app/guard/with-token.guard.spec.ts +++ b/src/app/guard/with-token.guard.spec.ts @@ -1,16 +1,35 @@ import { TestBed } from '@angular/core/testing'; import { WithTokenGuard } from './with-token.guard'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { VideoComponent } from '../pages/video/video.component'; describe('WithTokenGuard', () => { let guard: WithTokenGuard; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, RouterTestingModule.withRoutes( + [{ path: 'videos', component: VideoComponent }] + )], providers: [WithTokenGuard], declarations: [VideoComponent] + }); guard = TestBed.inject(WithTokenGuard); }); it('should be created', () => { expect(guard).toBeTruthy(); }); + + it('should return false for a logged in user', () => { + localStorage.setItem('token', 'testtoken'); + expect(guard.canActivate()).toBe(false); + } + ); + + it('should return true for a logged out user', () => { + localStorage.removeItem('token'); + expect(guard.canActivate()).toBe(true); + } + ); }); diff --git a/src/app/pages/active-account/active-account.component.spec.ts b/src/app/pages/active-account/active-account.component.spec.ts index 2a087ab8..c65b875b 100644 --- a/src/app/pages/active-account/active-account.component.spec.ts +++ b/src/app/pages/active-account/active-account.component.spec.ts @@ -6,12 +6,19 @@ import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { of, throwError } from 'rxjs'; import { RouterTestingModule } from '@angular/router/testing'; import { LoginComponent } from '../login/login.component'; +import { MessageService } from 'primeng/api'; +import { AlertService } from 'src/app/services/alert.service'; const mockData: any = { "email": "mario@gmail.com", "code": 123456, } +const mockDataError: any = { + "email": "", + "code": 123456, +} + class AuthServiceMock { constructor() { } activeAccount() { @@ -22,10 +29,21 @@ class AuthServiceMock { } } +class AlertServiceMock { + constructor() { } + showMessage() { + return of({ success: true }); + } + errorMessage() { + return of({ success: true }); + } +} + describe('ActiveAccountComponent', () => { let component: ActiveAccountComponent; let fixture: ComponentFixture; let authService: AuthService; + let alertService: AlertService; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -34,7 +52,11 @@ describe('ActiveAccountComponent', () => { { path: 'login', component: LoginComponent }, ] ), ReactiveFormsModule], - providers: [{ provide: AuthService, useValue: new AuthServiceMock() }, FormBuilder], + providers: [ + { provide: AlertService, useValue: new AlertServiceMock() }, + { provide: AuthService, useValue: new AuthServiceMock() }, + FormBuilder, + MessageService], declarations: [ActiveAccountComponent] }) .compileComponents(); @@ -43,6 +65,8 @@ describe('ActiveAccountComponent', () => { component = fixture.componentInstance; fixture.detectChanges(); authService = TestBed.inject(AuthService); + alertService = TestBed.inject(AlertService); + }); it('should create', () => { @@ -63,17 +87,36 @@ describe('ActiveAccountComponent', () => { expect(component.activeAccount).toHaveBeenCalled(); }); - it('should call alert when form is not valid', () => { + it('should call AlertServiceShowMessage when form is valid', () => { + spyOn(component, 'activeAccount').and.callThrough(); + const form = component.userForm; + form.setValue(mockData); + fixture.detectChanges(); + const mySpy = spyOn(authService, 'activeAccount').and.returnValue(of({ status: "error" })); + const alertSpy = spyOn(alertService, 'showMessage').and.callThrough(); + + const submitButton = fixture.nativeElement.querySelector( + 'button[type="submit"]' + ); + submitButton.click(); + + expect(alertSpy).toHaveBeenCalled(); + expect(mySpy).toHaveBeenCalled(); + }); + + it('should call AlertServiceShowMessage when form is not valid', () => { spyOn(component, 'activeAccount').and.callThrough(); - const alertSpy = spyOn(window, 'alert'); fixture.detectChanges(); + const form = component.userForm; + form.setValue(mockDataError); + const alertSpy = spyOn(alertService, 'showMessage').and.callThrough(); const submitButton = fixture.nativeElement.querySelector( 'button[type="submit"]' ); submitButton.click(); - expect(alertSpy).toHaveBeenCalledWith('Preencha todos os campos corretamente!'); + expect(alertSpy).toHaveBeenCalled(); }); it('should call activeAccount and return an error', () => { @@ -85,4 +128,33 @@ describe('ActiveAccountComponent', () => { expect(mySpy).toHaveBeenCalled(); }); + it('should call resendCode', () => { + fixture.detectChanges(); + const form = component.userForm; + form.setValue(mockData); + const mySpy = spyOn(authService, 'resendCode').and.callThrough(); + component.resendCode(); + expect(mySpy).toHaveBeenCalled(); + }); + + it('should call resendCode with invalid form', () => { + const form = component.userForm; + form.setValue(mockDataError); + fixture.detectChanges(); + spyOn(authService, 'resendCode').and.callThrough(); + const alertSpy = spyOn(alertService, 'showMessage').and.callThrough(); + component.resendCode(); + expect(alertSpy).toHaveBeenCalled(); + }); + + it('should call resendCode and return an error', () => { + const form = component.userForm; + form.setValue(mockData); + fixture.detectChanges(); + const myspy = spyOn(authService, 'resendCode').and.returnValue(throwError(() => new Error('Erro'))); + const alertSpy = spyOn(alertService, 'showMessage').and.callThrough(); + component.resendCode(); + expect(myspy).toHaveBeenCalled(); + }); + }); diff --git a/src/app/pages/active-account/active-account.component.ts b/src/app/pages/active-account/active-account.component.ts index b1b3f450..5484e2fe 100644 --- a/src/app/pages/active-account/active-account.component.ts +++ b/src/app/pages/active-account/active-account.component.ts @@ -3,6 +3,9 @@ import { FormGroup, FormBuilder, Validators } from "@angular/forms"; import { Router } from "@angular/router"; import { AuthService } from "../../services/auth.service"; import { AlertService } from "../../services/alert.service"; +import { HttpErrorResponse } from '@angular/common/http'; + +type ErrorResponseType = HttpErrorResponse; @Component({ selector: "app-active-account", @@ -17,7 +20,7 @@ export class ActiveAccountComponent implements OnInit { private fb: FormBuilder, private authService: AuthService, private alertService: AlertService, - ) {} + ) { } ngOnInit(): void { this.userForm = this.fb.group({ @@ -55,9 +58,9 @@ export class ActiveAccountComponent implements OnInit { next: (data) => { this.alertService.showMessage("success", "Sucesso", "Email reenviado com sucesso!"); }, - error: (error) => { + error: (error: ErrorResponseType) => { console.log(error); - this.alertService.showMessage("error", "Erro", error.error.detail); + this.alertService.errorMessage(error.error); }, }); } else { diff --git a/src/app/pages/check-code-rest-password/check-code-rest-password.component.spec.ts b/src/app/pages/check-code-rest-password/check-code-rest-password.component.spec.ts index 46e0fc16..c2f32493 100644 --- a/src/app/pages/check-code-rest-password/check-code-rest-password.component.spec.ts +++ b/src/app/pages/check-code-rest-password/check-code-rest-password.component.spec.ts @@ -6,6 +6,8 @@ import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { of, throwError } from 'rxjs'; import { RouterTestingModule } from '@angular/router/testing'; import { ResetPasswordComponent } from '../reset-password/reset-password.component'; +import { MessageService } from 'primeng/api'; +import { AlertService } from 'src/app/services/alert.service'; const mockData: any = { "email": "mario@gmail.com", @@ -22,10 +24,18 @@ class AuthServiceMock { } } +class AlertServiceMock { + errorMessage(){ + } + showMessage() { + } +} + describe('CheckCodeRestPasswordComponent', () => { let component: CheckCodeRestPasswordComponent; let fixture: ComponentFixture; let authService: AuthService; + let alertService: AlertService; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -34,7 +44,7 @@ describe('CheckCodeRestPasswordComponent', () => { { path: 'changePassword', component: ResetPasswordComponent }, ] ), ReactiveFormsModule], - providers: [{ provide: AuthService, useValue: new AuthServiceMock() }, FormBuilder], + providers: [{ provide: AuthService, useValue: new AuthServiceMock() }, { provide: AlertService, useValue: new AlertServiceMock() }, FormBuilder, MessageService], declarations: [CheckCodeRestPasswordComponent] }) .compileComponents(); @@ -43,6 +53,7 @@ describe('CheckCodeRestPasswordComponent', () => { component = fixture.componentInstance; fixture.detectChanges(); authService = TestBed.inject(AuthService); + alertService = TestBed.inject(AlertService); }); it('should create', () => { @@ -63,10 +74,10 @@ describe('CheckCodeRestPasswordComponent', () => { expect(component.sendEmail).toHaveBeenCalled(); }); - it('should call alert when form is not valid', () => { + it('should call showMessage when form is not valid', () => { fixture.detectChanges(); spyOn(component, 'sendEmail').and.callThrough(); - const alertSpy = spyOn(window, 'alert'); + const alertSpy = spyOn(alertService, 'showMessage'); const form = component.userForm; form.setValue({ "email": '', code: '' }); @@ -75,7 +86,9 @@ describe('CheckCodeRestPasswordComponent', () => { ); submitButton.click(); - expect(alertSpy).toHaveBeenCalledWith('Preencha todos os campos corretamente!'); + expect(alertSpy).toHaveBeenCalledWith('info', + 'Alerta', + 'Preencha todos os campos corretamente!'); }); it('should call sendEmail and return an error', () => { @@ -103,10 +116,9 @@ describe('CheckCodeRestPasswordComponent', () => { expect(component.checkCode).toHaveBeenCalled(); }); - it('should call alert when form is not valid', () => { - fixture.detectChanges(); + it('should call showMessage when form is not valid', () => { spyOn(component, 'checkCode').and.callThrough(); - const alertSpy = spyOn(window, 'alert'); + const alertSpy = spyOn(alertService, 'showMessage'); component.activeCode = true; fixture.detectChanges(); const submitButton = fixture.nativeElement.querySelector( @@ -114,7 +126,9 @@ describe('CheckCodeRestPasswordComponent', () => { ); submitButton.click(); - expect(alertSpy).toHaveBeenCalledWith('Preencha todos os campos corretamente!'); + expect(alertSpy).toHaveBeenCalledWith('info', + 'Alerta', + 'Preencha todos os campos corretamente!'); }); it('should call checkCode and return an error', () => { diff --git a/src/app/pages/check-code-rest-password/check-code-rest-password.component.ts b/src/app/pages/check-code-rest-password/check-code-rest-password.component.ts index 11123a92..7575eb06 100644 --- a/src/app/pages/check-code-rest-password/check-code-rest-password.component.ts +++ b/src/app/pages/check-code-rest-password/check-code-rest-password.component.ts @@ -3,6 +3,7 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { AlertService } from 'src/app/services/alert.service'; import { AuthService } from 'src/app/services/auth.service'; +import { HttpErrorResponse } from '@angular/common/http'; @Component({ selector: 'app-check-code-rest-password', @@ -53,8 +54,8 @@ export class CheckCodeRestPasswordComponent { this.alertService.showMessage("success", "Sucesso", "Código válido!"); this.navigator('/changePassword'); }, - error: (error) => { - this.alertService.showMessage("error", "Erro", error.error.detail); + error: (error: HttpErrorResponse) => { + this.alertService.errorMessage(error.error); }, }); } else { diff --git a/src/app/pages/edit-user/edit-user.component.spec.ts b/src/app/pages/edit-user/edit-user.component.spec.ts index 41d290bb..89ae28b7 100644 --- a/src/app/pages/edit-user/edit-user.component.spec.ts +++ b/src/app/pages/edit-user/edit-user.component.spec.ts @@ -6,6 +6,9 @@ import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { of, throwError } from 'rxjs'; import { UserService } from 'src/app/services/user.service'; import { ProfileComponent } from '../profile/profile.component'; +import { MessageService } from 'primeng/api'; +import { DropdownModule } from 'primeng/dropdown'; +import { AlertService } from 'src/app/services/alert.service'; const mockData: any = { "name": "Mario", @@ -18,12 +21,26 @@ class UserServiceMock { updateUser() { return of({ success: true }); } + getUser() { + return of({ success: true }); + } + getVinculo() { + return of({ success: true }); + } +} + +class AlertServiceMock { + errorMessage() { + } + showMessage() { + } } describe('EditUserComponent', () => { let component: EditUserComponent; let fixture: ComponentFixture; let userService: UserService; + let alertService: AlertService beforeEach(async () => { await TestBed.configureTestingModule({ @@ -31,22 +48,37 @@ describe('EditUserComponent', () => { [ { path: 'profile', component: ProfileComponent }, ] - ), ReactiveFormsModule], + ), ReactiveFormsModule, DropdownModule], declarations: [EditUserComponent], - providers: [{ provide: UserService, useValue: new UserServiceMock() }, FormBuilder], + providers: [{ provide: UserService, useValue: new UserServiceMock() }, { provide: AlertService, useValue: new AlertServiceMock() }, FormBuilder, MessageService], }) .compileComponents(); fixture = TestBed.createComponent(EditUserComponent); component = fixture.componentInstance; - fixture.detectChanges(); userService = TestBed.inject(UserService); + alertService = TestBed.inject(AlertService); + fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + it('should call getUser and return an error', () => { + fixture.detectChanges(); + const mySpy = spyOn(userService, 'getUser').and.returnValue(throwError(() => new Error('Erro'))); + component.getUser(); + expect(mySpy).toHaveBeenCalled(); + }); + + it('should call getVinculo and return an error', () => { + fixture.detectChanges(); + const mySpy = spyOn(userService, 'getVinculo').and.returnValue(throwError(() => new Error('Erro'))); + component.getVinculo(); + expect(mySpy).toHaveBeenCalled(); + }); + it('should call updateUser method when the form is submitted', () => { fixture.detectChanges(); spyOn(component, 'updateUser').and.callThrough(); @@ -62,17 +94,13 @@ describe('EditUserComponent', () => { expect(component.updateUser).toHaveBeenCalled(); }); - it('should call alert when form is not valid', () => { - spyOn(component, 'updateUser').and.callThrough(); - const alertSpy = spyOn(window, 'alert'); + it('should call showMessage when form is not valid', () => { fixture.detectChanges(); - - const submitButton = fixture.nativeElement.querySelector( - 'button[type="submit"]' - ); - submitButton.click(); - - expect(alertSpy).toHaveBeenCalledWith('Preencha todos os campos corretamente!'); + const mySpy = spyOn(alertService, 'showMessage'); + component.updateUser(); + expect(mySpy).toHaveBeenCalledWith('info', + 'Alerta', + 'Preencha todos os campos corretamente!'); }); it('should call updateUser and return an error', () => { diff --git a/src/app/pages/edit-user/edit-user.component.ts b/src/app/pages/edit-user/edit-user.component.ts index e1daf288..f96db7a5 100644 --- a/src/app/pages/edit-user/edit-user.component.ts +++ b/src/app/pages/edit-user/edit-user.component.ts @@ -3,6 +3,9 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { AlertService } from 'src/app/services/alert.service'; import { UserService } from 'src/app/services/user.service'; +import { HttpErrorResponse } from '@angular/common/http'; + +type ErrorResponseType = HttpErrorResponse; @Component({ selector: 'app-edit-user', @@ -21,7 +24,7 @@ export class EditUserComponent implements OnInit { private userService: UserService, private route: ActivatedRoute, private alertService: AlertService - ) {} + ) { } ngOnInit(): void { const userId = this.route.snapshot.params['id']; @@ -42,8 +45,8 @@ export class EditUserComponent implements OnInit { this.initializeForm(); } }, - error: (error) => { - this.alertService.showMessage('error', 'Erro', error.error.detail); + error: (error: ErrorResponseType) => { + this.alertService.errorMessage(error.error); }, }); } @@ -75,8 +78,8 @@ export class EditUserComponent implements OnInit { }; }); }, - error: (error) => { - this.alertService.showMessage('error', 'Erro', error.error.detail); + error: (error: ErrorResponseType) => { + this.alertService.errorMessage(error.error); }, }); } @@ -97,8 +100,8 @@ export class EditUserComponent implements OnInit { ); this.navigator('/profile'); }, - error: (error) => { - this.alertService.showMessage('error', 'Erro', error.error.detail); + error: (error: ErrorResponseType) => { + this.alertService.errorMessage(error.error); }, }); } else { diff --git a/src/app/pages/login/login.component.spec.ts b/src/app/pages/login/login.component.spec.ts index 899796b2..c890b38a 100644 --- a/src/app/pages/login/login.component.spec.ts +++ b/src/app/pages/login/login.component.spec.ts @@ -9,8 +9,10 @@ import { CheckCodeRestPasswordComponent } from '../check-code-rest-password/chec import { RegisterComponent } from '../register/register.component'; import { of, throwError } from 'rxjs'; import { AlertService } from '../../services/alert.service'; -import { MessageService } from 'primeng/api'; import { VideoComponent } from '../video/video.component'; +import { HttpErrorResponse } from '@angular/common/http'; +import { ActiveAccountComponent } from '../active-account/active-account.component'; + const mockUserReturn = { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJqb2FvMTV2aWN0b3IwOEBnbWFpbC5jb20iLCJleHAiOjE2OTkzMTI5MzV9.1B9qBJt8rErwBKyD5JCdsPozsw86oQ38tdfDuMM2HFI", @@ -21,19 +23,17 @@ class AuthServiceMock { constructor() { } loginUser() { - return throwError({ error: { message: 'Erro' } }); + return of({ success: true }); } } -class MessageServiceMock { - messages: any[] = []; - - add(message: any) { - this.messages.push(message); +class AlertServiceMock { + constructor() { } + showMessage() { + return of({ success: true }); } - - clear() { - this.messages = []; + errorMessage() { + return of({ success: true }); } } @@ -42,7 +42,6 @@ describe('LoginComponent', () => { let fixture: ComponentFixture; let authService: AuthService; let alertService: AlertService; - let messageService: MessageServiceMock; // Use the mock class beforeEach(async () => { TestBed.configureTestingModule({ @@ -51,15 +50,16 @@ describe('LoginComponent', () => { { path: 'profile', component: ProfileComponent }, { path: 'sendCodeResetPassword', component: CheckCodeRestPasswordComponent }, { path: 'register', component: RegisterComponent }, - { path: 'videos', component: VideoComponent } + { path: 'videos', component: VideoComponent }, + { path: 'activeAccount', component: ActiveAccountComponent } ] )], providers: [ FormBuilder, AuthService, AlertService, - { provide: MessageService, useClass: MessageServiceMock }, // Provide the mock class - { provide: AuthService, useClass: AuthServiceMock } + { provide: AlertService, useValue: new AlertServiceMock() }, // Provide the mock class + { provide: AuthService, useValue: new AuthServiceMock() } ], declarations: [LoginComponent], }).compileComponents(); @@ -68,7 +68,6 @@ describe('LoginComponent', () => { component = fixture.componentInstance; authService = TestBed.inject(AuthService); alertService = TestBed.inject(AlertService); - messageService = TestBed.inject(MessageService) as unknown as MessageServiceMock; // Inject the mock class }); it('should create', () => { @@ -121,16 +120,15 @@ describe('LoginComponent', () => { expect(component.navigator).toHaveBeenCalledWith('/register'); }); - it('should call login and handle error', fakeAsync(() => { + it('should call login and return an error', () => { fixture.detectChanges(); const form = component.userForm; form.setValue({ email: 'test@example.com', password: 'password' }); - - const mySpy = spyOn(authService, 'loginUser').and.returnValue(throwError({ error: { message: 'Erro' } })); - + const mySpy = spyOn(authService, 'loginUser').and.returnValue(throwError(() => new HttpErrorResponse({ error: { detail: 'A sua conta ainda não foi ativada.' } }))); + spyOn(component, 'navigator').and.callThrough(); component.login(); - tick(); - expect(mySpy).toHaveBeenCalled(); - })); + expect(component.navigator).toHaveBeenCalledWith('/activeAccount'); + }); + }); diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts index 09abe4a6..5a2ecb8c 100644 --- a/src/app/pages/login/login.component.ts +++ b/src/app/pages/login/login.component.ts @@ -4,8 +4,12 @@ import { Router } from '@angular/router'; import { MustMatch } from 'src/app/helper/must-match.validator'; import { AuthService } from '../../services/auth.service'; import { AlertService } from 'src/app/services/alert.service'; +import { HttpErrorResponse } from '@angular/common/http'; - +type ErrorResponseType = HttpErrorResponse; +interface IDetails { + detail: string; +} @Component({ selector: 'app-login', templateUrl: './login.component.html', @@ -36,9 +40,10 @@ export class LoginComponent implements OnInit { localStorage.setItem('token', data.access_token); this.navigator('/videos'); }, - error: (error) => { - this.alertService.showMessage("error", "Erro", error.error.detail); - if(error.error.detail === 'A sua conta ainda não foi ativada.') { + error: (error: ErrorResponseType) => { + this.alertService.errorMessage(error.error); + let errorDetail: IDetails = { ...error.error }; + if (errorDetail.detail === 'A sua conta ainda não foi ativada.') { this.navigator('/activeAccount'); } }, diff --git a/src/app/pages/profile/profile.component.html b/src/app/pages/profile/profile.component.html index 895c6359..3ca69385 100644 --- a/src/app/pages/profile/profile.component.html +++ b/src/app/pages/profile/profile.component.html @@ -17,7 +17,7 @@ {{ user.email }}
-
-
- -
-
diff --git a/src/app/pages/video-viewer/video-viewer.component.spec.ts b/src/app/pages/video-viewer/video-viewer.component.spec.ts index cbe56386..fe1b9a19 100644 --- a/src/app/pages/video-viewer/video-viewer.component.spec.ts +++ b/src/app/pages/video-viewer/video-viewer.component.spec.ts @@ -7,10 +7,12 @@ import { VideoCommentComponent } from 'src/app/components/video-comment/video-co import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { VideoService } from 'src/app/services/video.service'; import { ActivatedRoute } from '@angular/router'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; describe('VideoViewerComponent', () => { let component: VideoViewerComponent; let fixture: ComponentFixture; + let domSanitizer: DomSanitizer; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -27,6 +29,10 @@ describe('VideoViewerComponent', () => { }, { provide: VideoService }, FormBuilder, + { + provide: DomSanitizer, + useValue: { bypassSecurityTrustResourceUrl: (value: string) => value } + } ], }).compileComponents(); @@ -34,24 +40,26 @@ describe('VideoViewerComponent', () => { component = fixture.componentInstance; localStorage.setItem('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJqb2FvMTV2aWN0b3IwOEBnbWFpbC5jb20iLCJleHAiOjE2OTkzMTI5MzV9.1B9qBJt8rErwBKyD5JCdsPozsw86oQ38tdfDuMM2HFI'); fixture.detectChanges(); + domSanitizer = TestBed.inject(DomSanitizer); }); it('should create', () => { expect(component).toBeTruthy(); }); + describe('expand Description', () => { + it('should toggle showDescription when expandDescription is called', () => { + + expect(component.showDescription).toBe(false); + + component.expandDescription(); + + expect(component.showDescription).toBe(true); + + component.expandDescription(); - it('should toggle mostrarCompleta property', () => { - expect(component.mostrarCompleta).toBe(false); - - component.expandirDescricao(); - - expect(component.mostrarCompleta).toBe(true); - - component.expandirDescricao(); - - expect(component.mostrarCompleta).toBe(false); - }); - + expect(component.showDescription).toBe(false); + }); + }); describe('Getting the video url', () => { it('should extract video URL from embed code', () => { const embedCode = @@ -69,5 +77,8 @@ describe('VideoViewerComponent', () => { expect(extractedUrl).toBeNull(); }); + }); -}); + + +}); diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 5f1c4daf..47487c52 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -12,14 +12,14 @@ import { IVideo, Video } from 'src/shared/model/video.model'; }) export class VideoViewerComponent implements OnInit { videoDescription: string = ''; - limiteCaracteres = 100; - mostrarCompleta = false; + characterLimit = 100; + showDescription = false; video: IVideo = new Video(); videoUrl!: SafeHtml; idVideo!: number; - expandirDescricao() { - this.mostrarCompleta = !this.mostrarCompleta; + expandDescription() { + this.showDescription = !this.showDescription; } extractVideoUrl(embedCode: string): string | null { @@ -46,11 +46,9 @@ export class VideoViewerComponent implements OnInit { const embedCode = this.video.embed as string; const url = this.extractVideoUrl(embedCode); - if (url) { this.videoUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(url); } - this.videoDescription = this.video.description ? this.video.description : ''; From c5052ddd2bd9bb2ad79a946f9a6911ac7f00a06b Mon Sep 17 00:00:00 2001 From: Marcos Castilhos <221008300@aluno.unb.br> Date: Sun, 19 Nov 2023 15:28:33 -0300 Subject: [PATCH 18/21] apaga safe pipe --- src/app/app.module.ts | 2 -- .../video-viewer/video-viewer.component.spec.ts | 5 ++--- src/app/pipes/safe.pipe.spec.ts | 8 -------- src/app/pipes/safe.pipe.ts | 14 -------------- 4 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 src/app/pipes/safe.pipe.spec.ts delete mode 100644 src/app/pipes/safe.pipe.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ec322a40..d22a3cd1 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -19,7 +19,6 @@ import { LoginComponent } from './pages/login/login.component'; import { RegisterComponent } from './pages/register/register.component'; import { VideoComponent } from './pages/video/video.component'; import { VideoViewerComponent } from './pages/video-viewer/video-viewer.component'; -import { SafePipe } from './pipes/safe.pipe'; import { BackgroundComponent } from './components/background/background.component'; import { LoginSocialComponent } from './pages/login-social/login-social.component'; import { ActiveAccountComponent } from './pages/active-account/active-account.component'; @@ -58,7 +57,6 @@ import { MessageService } from 'primeng/api'; LoginSocialComponent, VideoComponent, VideoViewerComponent, - SafePipe, BackgroundComponent, ActiveAccountComponent, ProfileComponent, diff --git a/src/app/pages/video-viewer/video-viewer.component.spec.ts b/src/app/pages/video-viewer/video-viewer.component.spec.ts index fe1b9a19..5be9c393 100644 --- a/src/app/pages/video-viewer/video-viewer.component.spec.ts +++ b/src/app/pages/video-viewer/video-viewer.component.spec.ts @@ -2,12 +2,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { VideoViewerComponent } from './video-viewer.component'; -import { SafePipe } from 'src/app/pipes/safe.pipe'; import { VideoCommentComponent } from 'src/app/components/video-comment/video-comment.component'; import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { VideoService } from 'src/app/services/video.service'; import { ActivatedRoute } from '@angular/router'; -import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; describe('VideoViewerComponent', () => { let component: VideoViewerComponent; @@ -16,7 +15,7 @@ describe('VideoViewerComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [VideoViewerComponent, SafePipe, VideoCommentComponent], + declarations: [VideoViewerComponent, VideoCommentComponent], imports: [ HttpClientTestingModule, RouterTestingModule, diff --git a/src/app/pipes/safe.pipe.spec.ts b/src/app/pipes/safe.pipe.spec.ts deleted file mode 100644 index 49ee0ad1..00000000 --- a/src/app/pipes/safe.pipe.spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SafePipe } from './safe.pipe'; - -describe('SafePipe', () => { - it('create an instance', () => { - const pipe = new SafePipe(); - expect(pipe).toBeTruthy(); - }); -}); diff --git a/src/app/pipes/safe.pipe.ts b/src/app/pipes/safe.pipe.ts deleted file mode 100644 index 2fe5c315..00000000 --- a/src/app/pipes/safe.pipe.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { DomSanitizer } from "@angular/platform-browser"; - -@Pipe({ - name: 'safe' -}) -export class SafePipe implements PipeTransform { - constructor(private _sanitizer?: DomSanitizer) { } - - transform(url: any) { - return this._sanitizer?.bypassSecurityTrustResourceUrl(url); - } - -} \ No newline at end of file From 959abafc8516fac8e4bf1d700b8ebc6847b4668e Mon Sep 17 00:00:00 2001 From: Marcos Castilhos <221008300@aluno.unb.br> Date: Sun, 19 Nov 2023 15:28:48 -0300 Subject: [PATCH 19/21] altera safehtml --- src/app/pages/video-viewer/video-viewer.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 47487c52..39a3b41c 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; -import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { VideoService } from '../../services/video.service'; import { IVideo, Video } from 'src/shared/model/video.model'; @@ -15,7 +15,7 @@ export class VideoViewerComponent implements OnInit { characterLimit = 100; showDescription = false; video: IVideo = new Video(); - videoUrl!: SafeHtml; + videoUrl!: SafeResourceUrl; idVideo!: number; expandDescription() { @@ -46,9 +46,9 @@ export class VideoViewerComponent implements OnInit { const embedCode = this.video.embed as string; const url = this.extractVideoUrl(embedCode); - if (url) { + if (url) { this.videoUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(url); - } + } this.videoDescription = this.video.description ? this.video.description : ''; From 8fd739eb203b439d5c1cafb98ca93f90d5dcc9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Sun, 19 Nov 2023 21:37:49 -0300 Subject: [PATCH 20/21] Altera chamada da api para passar nos testes --- .../background/background.component.html | 2 +- .../video-viewer/video-viewer.component.html | 12 ++-- .../video-viewer.component.spec.ts | 62 ++++++++----------- .../video-viewer/video-viewer.component.ts | 22 ++----- 4 files changed, 37 insertions(+), 61 deletions(-) diff --git a/src/app/components/background/background.component.html b/src/app/components/background/background.component.html index 820a6c50..58118799 100644 --- a/src/app/components/background/background.component.html +++ b/src/app/components/background/background.component.html @@ -32,7 +32,7 @@
-
+
diff --git a/src/app/pages/video-viewer/video-viewer.component.html b/src/app/pages/video-viewer/video-viewer.component.html index aeb46abc..b53d2ed6 100644 --- a/src/app/pages/video-viewer/video-viewer.component.html +++ b/src/app/pages/video-viewer/video-viewer.component.html @@ -1,13 +1,13 @@ -
-
+
+
+
+

{{ video.title }} diff --git a/src/app/pages/video-viewer/video-viewer.component.spec.ts b/src/app/pages/video-viewer/video-viewer.component.spec.ts index 5be9c393..fbb393f4 100644 --- a/src/app/pages/video-viewer/video-viewer.component.spec.ts +++ b/src/app/pages/video-viewer/video-viewer.component.spec.ts @@ -6,12 +6,19 @@ import { VideoCommentComponent } from 'src/app/components/video-comment/video-co import { FormBuilder, ReactiveFormsModule } from '@angular/forms'; import { VideoService } from 'src/app/services/video.service'; import { ActivatedRoute } from '@angular/router'; -import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; +import { of } from 'rxjs'; + +class VideoServiceMock { + constructor() { } + findVideoById() { + return of({}); + } +} describe('VideoViewerComponent', () => { let component: VideoViewerComponent; let fixture: ComponentFixture; - let domSanitizer: DomSanitizer; + let videoService: VideoService; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -24,14 +31,10 @@ describe('VideoViewerComponent', () => { providers: [ { provide: ActivatedRoute, - useValue: { snapshot: { params: { id: 1 } } }, + useValue: { snapshot: { params: { id: 190329 } } }, }, - { provide: VideoService }, + { provide: VideoService, useValue: new VideoServiceMock() }, FormBuilder, - { - provide: DomSanitizer, - useValue: { bypassSecurityTrustResourceUrl: (value: string) => value } - } ], }).compileComponents(); @@ -39,45 +42,30 @@ describe('VideoViewerComponent', () => { component = fixture.componentInstance; localStorage.setItem('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJqb2FvMTV2aWN0b3IwOEBnbWFpbC5jb20iLCJleHAiOjE2OTkzMTI5MzV9.1B9qBJt8rErwBKyD5JCdsPozsw86oQ38tdfDuMM2HFI'); fixture.detectChanges(); - domSanitizer = TestBed.inject(DomSanitizer); + videoService = TestBed.inject(VideoService); }); it('should create', () => { expect(component).toBeTruthy(); }); - describe('expand Description', () => { - it('should toggle showDescription when expandDescription is called', () => { - - expect(component.showDescription).toBe(false); - - component.expandDescription(); - - expect(component.showDescription).toBe(true); - - component.expandDescription(); - expect(component.showDescription).toBe(false); - }); - }); - describe('Getting the video url', () => { - it('should extract video URL from embed code', () => { - const embedCode = - ''; - const extractedUrl = component.extractVideoUrl(embedCode); + it('should toggle showDescription when expandDescription is called', () => { + + expect(component.showDescription).toBe(false); - expect(extractedUrl).toBe( - 'https://eduplay.rnp.br/portal/video/embed/190486' - ); - }); + component.expandDescription(); - it('should return null for invalid embed code', () => { - const invalidEmbedCode = ''; - const extractedUrl = component.extractVideoUrl(invalidEmbedCode); + expect(component.showDescription).toBe(true); - expect(extractedUrl).toBeNull(); - }); + component.expandDescription(); + + expect(component.showDescription).toBe(false); + }); + it('should call findVideoById and return video', () => { + const mySpy = spyOn(videoService, 'findVideoById').and.callThrough(); + component.findVideoById(); + expect(mySpy).toHaveBeenCalled(); }); - }); diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 39a3b41c..278478ee 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -1,7 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, SecurityContext } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; -import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { VideoService } from '../../services/video.service'; import { IVideo, Video } from 'src/shared/model/video.model'; @@ -15,40 +14,29 @@ export class VideoViewerComponent implements OnInit { characterLimit = 100; showDescription = false; video: IVideo = new Video(); - videoUrl!: SafeResourceUrl; idVideo!: number; + eduplayVideoUrl = "https://eduplay.rnp.br/portal/video/embed/"; expandDescription() { this.showDescription = !this.showDescription; } - extractVideoUrl(embedCode: string): string | null { - const regex = / { this.videoService.findVideoById(this.idVideo).subscribe({ next: (data: HttpResponse) => { this.video = data.body ? data.body : this.video; - - const embedCode = this.video.embed as string; - const url = this.extractVideoUrl(embedCode); - if (url) { - this.videoUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(url); - } this.videoDescription = this.video.description ? this.video.description : ''; From 473f515a0bfabecdf5cb62222ccc8d760b025c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Mon, 20 Nov 2023 14:36:45 -0300 Subject: [PATCH 21/21] Remove import sem uso --- src/app/pages/video-viewer/video-viewer.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/pages/video-viewer/video-viewer.component.ts b/src/app/pages/video-viewer/video-viewer.component.ts index 278478ee..06cbbfc5 100644 --- a/src/app/pages/video-viewer/video-viewer.component.ts +++ b/src/app/pages/video-viewer/video-viewer.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, SecurityContext } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; import { VideoService } from '../../services/video.service';