Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

49 comentarios videos #13

Merged
merged 13 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CheckCodeRestPasswordComponent } from './pages/check-code-rest-password
import { AuthGuard } from './services/auth.guard';
import { AuthService } from './services/auth.service';
import { EditUserComponent } from './pages/edit-user/edit-user.component';
import { VideoCommentComponent } from './components/video-comment/video-comment.component';
import { SuggestAgendaComponent } from './pages/suggest-agenda/suggest-agenda.component';
import { ParticipateComponent } from './pages/participate/participate.component';

Expand All @@ -30,7 +31,6 @@ import { ParticipateComponent } from './pages/participate/participate.component'
AppComponent,
LoginComponent,
RegisterComponent,
BackgroundComponent,
LoginSocialComponent,
VideoComponent,
VideoViewerComponent,
Expand All @@ -42,15 +42,15 @@ import { ParticipateComponent } from './pages/participate/participate.component'
ResetPasswordComponent,
CheckCodeRestPasswordComponent,
EditUserComponent,
VideoCommentComponent,
SuggestAgendaComponent,
ParticipateComponent,
ParticipateComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
ReactiveFormsModule,
HttpClientModule,
],
providers: [
AuthGuard,
Expand Down
Empty file.
63 changes: 63 additions & 0 deletions src/app/components/video-comment/video-comment.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<div>
<div *ngIf="!userId">
<p class="text-center">Faça login para comentar</p>
</div>

<div *ngIf="userId" class="flex flex-col gap-2">
<div *ngIf="showComments" class="flex flex-wrap flex-col gap-2">
<div
(click)="toggleComments()"
class="text-blue-brand w-2 min-w-fit cursor-pointer"
>
Recolher comentarios
</div>
<div *ngFor="let comment of comments" class="flex flex-col gap-1">
<hr />
<div class="flex gap-2">
<div class="w-2/12 flex align-middle justify-center">
<img
class="rounded-full w-10 h-10 min-w-max min-h-max"
src="../../../assets/person.png"
alt="avatar"
/>
</div>
<div class="w-10/12 min-w-min">
<div class="font-bold font-custom text-xl max-w-prose">
{{ comment.user_name }}:
</div>
<div class="font-custom text-xl max-w-prose">
<p>{{ comment.content }}</p>
</div>
</div>
</div>
</div>
</div>
<div
*ngIf="!showComments"
(click)="toggleComments()"
class="text-blue-brand w-2 min-w-fit cursor-pointer"
>
{{ comments.length }} Comentários
</div>
<hr />
<form [formGroup]="commentForm" (submit)="addComment()" class="">
<div class="flex flex-col">
<textarea
name="comment"
placeholder="Adicione um comentário"
type="text"
formControlName="comment"
required
class="resize-none h-20 w-full"
>
</textarea>
<button
class="w-20 h-8 bg-blue-brand rounded-lg justify-center my-8 text-white md:h-10 md:w-32"
type="submit"
>
Adicionar
</button>
</div>
</form>
</div>
</div>
152 changes: 152 additions & 0 deletions src/app/components/video-comment/video-comment.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VideoCommentComponent } from './video-comment.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { of, throwError } from 'rxjs';
import { VideoCommentService } from 'src/app/services/video-comment.service';
import { UserService } from 'src/app/services/user.service';

class VideoCommentServiceMock {
constructor() { }
getComments() {
return of({ body: [] });
}
postComment() {
return of({ body: [] });
}
}

class UserServiceMock {
constructor() { }
getUser(userId: number) {
return of({ body: [] });
}
}

describe('VideoCommentComponent', () => {
let component: VideoCommentComponent;
let fixture: ComponentFixture<VideoCommentComponent>;
let videoCommentService: VideoCommentService;
let userService: UserService;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [VideoCommentComponent],
imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule],
providers: [
FormBuilder,
{ provide: VideoCommentService, useValue: new VideoCommentServiceMock() },
{ provide: UserService, useValue: new UserServiceMock() }]
})
.compileComponents();

fixture = TestBed.createComponent(VideoCommentComponent);
component = fixture.componentInstance;
videoCommentService = TestBed.inject(VideoCommentService);
userService = TestBed.inject(UserService);
localStorage.setItem('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJqb2FvMTV2aWN0b3IwOEBnbWFpbC5jb20iLCJleHAiOjE2OTkzMTI5MzV9.1B9qBJt8rErwBKyD5JCdsPozsw86oQ38tdfDuMM2HFI');
});

it('should create', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
});

it('should have a valid form on initialization', () => {
fixture.detectChanges();
expect(component.commentForm).toBeTruthy();
});

it('should call addComment method when the form is submitted', () => {
fixture.detectChanges();
spyOn(component, 'addComment').and.callThrough();
const form = component.commentForm;
form.setValue({ comment: 'comment content' });

const submitButton = fixture.nativeElement.querySelector(
'button[type="submit"]'
);
submitButton.click();

expect(component.addComment).toHaveBeenCalled();
});

it('should call alert when form is not valid for required field', () => {
spyOn(component, 'addComment').and.callThrough();
const alertSpy = spyOn(window, 'alert');
fixture.detectChanges();

const submitButton = fixture.nativeElement.querySelector(
'button[type="submit"]'
);
submitButton.click();

expect(alertSpy).toHaveBeenCalledWith('Comentário não pode ser vazio');
});

it('should call alert when form is not valid for lenght of field', () => {
fixture.detectChanges();
spyOn(component, 'addComment').and.callThrough();
const alertSpy = spyOn(window, 'alert');
const form = component.commentForm;
form.setValue({ comment: 'Lorem ipsum dolor sit amet. Et dolorem modi aut doloremque quas et perferendis velit non minima culpa sed totam doloribus et tempora necessitatibus. Est ipsum sunt ab repellat excepturi sed fugiat sint ut dicta animi. Non voluptate aperiam ab veniam rerum est omnis assumenda At doloribus quia aut delectus tempora? Eos eligendi numquam est molestiae itaque ut dolor quidem ea optio natus. Qui facere dignissimos in tenetur excepturi ea inventore aliquid qui corporis delectus vel dolor ducimus. A tempora explicabo qui aspernatur quod est iusto laboriosam id molestias delectus 33 eveniet suscipit eos dolores esse. 33 quia totam qui quidem ipsa sit fugiat Quis sit quam doloremque non eius voluptates et voluptas suscipit! Ut dicta saepe rem repellat voluptatem et omnis quod ex tempore rerum non laborum fuga eos voluptate vitae. Aut iusto quam ut dignissimos impedit ut placeat nihil et excepturi consequatur est dolorum harum vel voluptate quae rem eligendi commodi. In eius molestiae non tempora voluptatem sed galisum inventore eum similique incidunt et reiciendis officia. Et quia numquam qui placeat dignissimos eos quia tenetur 33 laboriosam numquam ab omnis ullam. Ut quibusdam aperiam ex dolore ipsa in consectetur tenetur qui vitae fuga. Eum commodi labore eos nemo voluptates eum praesentium laudantium eos delectus enim rem mollitia voluptatem ut numquam voluptatem et obcaecati molestiae! Et esse eveniet eum doloremque sint est commodi fugiat et repellendus totam.' });

const submitButton = fixture.nativeElement.querySelector(
'button[type="submit"]'
);
submitButton.click();

expect(alertSpy).toHaveBeenCalledWith('Comentário não pode ter mais de 1000 caracteres');
});

it('should call toggleComments method when "Comentarios" is clicked', () => {
fixture.detectChanges();
spyOn(component, 'toggleComments').and.callThrough();
const forgotPasswordLink =
fixture.nativeElement.querySelector('.text-blue-brand');
forgotPasswordLink.click();

expect(component.toggleComments).toHaveBeenCalled();

});

it('should call set userId to 0 when not authenticated', () => {
localStorage.clear();
fixture.detectChanges();

expect(component.userId).toBe(0);
localStorage.setItem('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJqb2FvMTV2aWN0b3IwOEBnbWFpbC5jb20iLCJleHAiOjE2OTkzMTI5MzV9.1B9qBJt8rErwBKyD5JCdsPozsw86oQ38tdfDuMM2HFI');

});

it('shoud call getComments', () => {
spyOn(component, 'getComments');
fixture.detectChanges();
expect(component.getComments).toHaveBeenCalled();
expect(component.comments).toBeTruthy();
})

it('should call getComments and return an error', () => {
const mySpy = spyOn(videoCommentService, 'getComments').and.returnValue(throwError(() => new Error('Erro')));
component.getComments();
expect(mySpy).toHaveBeenCalled();
});

it('should call addComment and return an error', () => {
fixture.detectChanges();
const form = component.commentForm;
form.setValue({ comment: 'comment content' });
const mySpy = spyOn(videoCommentService, 'postComment').and.returnValue(throwError(() => new Error('Erro')));
component.addComment();
expect(mySpy).toHaveBeenCalled();
});

it('should call getUserName and return an error', () => {
const mySpy = spyOn(userService, 'getUser').and.returnValue(throwError(() => new Error('Erro')));
component.getUserName(1);
expect(mySpy).toHaveBeenCalled();
});


});
119 changes: 119 additions & 0 deletions src/app/components/video-comment/video-comment.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { VideoCommentService } from '../../services/video-comment.service';
import { ActivatedRoute } from '@angular/router';
import jwt_decode from 'jwt-decode';
import { AuthService } from '../../services/auth.service';
import { Comment } from '../../../shared/model/comment.model';
import { UserService } from 'src/app/services/user.service';

@Component({
selector: 'app-video-comment',
templateUrl: './video-comment.component.html',
styleUrls: ['./video-comment.component.css']
})
export class VideoCommentComponent implements OnInit {
commentForm!: FormGroup;
comment: string = '';
video_id: number = 0;
userId: any;
comments: Comment[] = [];
userName: string = '';
showComments: boolean = false;


constructor(
private fb: FormBuilder,
private vcs: VideoCommentService,
private route: ActivatedRoute,
private authService: AuthService,
private userService: UserService
) { }

ngOnInit(): void {
this.commentForm = this.fb.group({
comment: ['', [Validators.required, Validators.maxLength(1000)]],
},
);
this.route.params.subscribe((params) => {
this.video_id = params['idVideo'];
})
if (this.authService.isAuthenticated()) {
this.setUserIdFromToken(localStorage.getItem('token') as string);
} else {
this.userId = 0;
}

this.getUserName(this.userId);

this.getComments();


}

getComments() {
this.vcs.getComments(this.video_id).subscribe({
next: (data) => {
this.comments = data.body as Comment[];
console.log(this.comments);
},
error: (error) => {
console.log(error)
}
});
}

setUserIdFromToken(token: string) {
const decodedToken: any = jwt_decode(token);
this.userId = decodedToken.id;
// console.log(this.userId);
}

getUserName(userId: number) {
this.userService.getUser(userId).subscribe({
next: (data) => {
this.userName = data.name;
},
error: (error) => {
console.log(error)
}
});
}

addComment() {
if (this.commentForm.valid) {
this.comment = this.commentForm.value.comment;
this.vcs.postComment({
user_id: this.userId,
video_id: this.video_id,
user_name: this.userName,
content: this.comment
}).subscribe({
next: (data) => {
console.log(data);
},
error: (error) => {
console.log(error)
}
});
this.comments.push({
user_id: this.userId,
video_id: this.video_id,
content: this.comment,
user_name: this.userName
});
this.commentForm.reset();
} else if (this.commentForm.get('comment')?.hasError('required')) {
alert("Comentário não pode ser vazio");
}
else if (this.commentForm.get('comment')?.hasError('maxlength')) {
alert("Comentário não pode ter mais de 1000 caracteres");
}
}

toggleComments() {
this.showComments = !this.showComments;
}

}

1 change: 1 addition & 0 deletions src/app/environment/environment.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const EDUPLAY_CLIENT_KEY = "a1cdba06226408fcda63b49c50223c68d56005d234cc98bcdc1ae787d2b4de1d";
export const environment = {
videoAPIURL: 'https://unb-tv-video-service-2023-2-1246521a8eef.herokuapp.com',
usersAPIURL: 'https://unb-tv-backend-2be1ed3a0485.herokuapp.com/api',
adminAPIURL: 'https://admin-unb-tv-2023-2-dc0dd53d3aca.herokuapp.com/api'
};
4 changes: 3 additions & 1 deletion src/app/pages/register/register.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ describe('RegisterComponent', () => {
});

it('should call register method when the form is submitted', () => {
fixture.detectChanges();
spyOn(component, 'register').and.callThrough();
const alertSpy = spyOn(window, 'alert');
fixture.detectChanges();
const form = component.userForm;
form.setValue(mockData);

Expand All @@ -68,6 +69,7 @@ describe('RegisterComponent', () => {
submitButton.click();

expect(component.register).toHaveBeenCalled();
expect(alertSpy).toHaveBeenCalledWith('Usuário cadastrado com sucesso!');
});

it('should call alert when form is not valid', () => {
Expand Down
Loading
Loading