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

Release 1.9 #182

Merged
merged 34 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
616bf99
feat: #176 added new styles
pablitoo1 Nov 23, 2024
40c1736
feat: #176 added new animations
pablitoo1 Nov 23, 2024
4c570f0
feat: #176 added rwd
pablitoo1 Nov 23, 2024
3e28d10
refactor: #176 changed functionality of showing options
pablitoo1 Nov 23, 2024
bf52d2e
feat: #173 added directives to all needed parts
pablitoo1 Nov 23, 2024
cebc3a6
Merge pull request #177 from theImmortalCoders/issue-176
pablitoo1 Nov 23, 2024
9ca6ff4
fix: #dev small changes
pablitoo1 Nov 23, 2024
79617b5
feat: #174 added cookie consent component
pablitoo1 Nov 24, 2024
037cfda
feat: #174 added icon and title of modal
pablitoo1 Nov 24, 2024
c50d3d5
Merge pull request #178 from theImmortalCoders/issue-174
pablitoo1 Nov 24, 2024
6406578
feat: #114 added common searchbar component
pablitoo1 Nov 25, 2024
a286284
Merge pull request #179 from theImmortalCoders/issue-114
pablitoo1 Nov 26, 2024
0a38ebe
fix: #148 fixed refresh token error desc during failed login attempt
pablitoo1 Nov 26, 2024
6fd25a8
feat: #148 handle all queryParams for getUsers
pablitoo1 Nov 26, 2024
e93e7c4
feat: #148 added initial filtering and sorting of users
pablitoo1 Nov 27, 2024
66d4100
fix: #148 fixed number typed filters
pablitoo1 Nov 27, 2024
28aa8da
feat: #148 added filtered records table + buttons for admins
pablitoo1 Nov 27, 2024
5650a87
feat: #148 handle accessibility for roles
pablitoo1 Nov 27, 2024
424f63b
feat: #148 divided into another component
pablitoo1 Nov 27, 2024
aeaa99a
fix: #148 visuable fixes
pablitoo1 Nov 27, 2024
697adb6
feat: #148 sorting by click to each column
pablitoo1 Nov 27, 2024
bde1717
feat: #148 added initial state of users table
pablitoo1 Nov 27, 2024
a7c82bb
feat: #148 handle refresh data when user's field changed
pablitoo1 Nov 27, 2024
be7a243
feat: #148 added tests
pablitoo1 Nov 27, 2024
458f700
Merge pull request #180 from theImmortalCoders/issue-148
pablitoo1 Nov 27, 2024
4654c33
fix: #dev fixed y-axis overflow in tables
pablitoo1 Nov 27, 2024
6c2975e
feat: #dev small filters change
pablitoo1 Nov 28, 2024
ee13a72
feat: #146 added filtering to user details page
pablitoo1 Nov 28, 2024
43e27ea
feat: #146 added filters to dashboard user page
pablitoo1 Nov 28, 2024
7c6ae5b
feat: #146 added sorting
pablitoo1 Nov 28, 2024
156e230
feat: #146 added 'minus' icon when field is avalaible to sort
pablitoo1 Nov 28, 2024
374f664
fix: #146 fix tests
pablitoo1 Nov 28, 2024
141c948
Merge pull request #181 from theImmortalCoders/issue-146
pablitoo1 Nov 28, 2024
1aa6c0d
feat: #dev new backend field's name
pablitoo1 Nov 28, 2024
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
27 changes: 21 additions & 6 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { RouterOutlet } from '@angular/router';
import { NavbarComponent } from './shared/components/navbar/navbar.component';
import { FooterComponent } from './shared/components/footer/footer.component';
import { NotificationComponent } from './shared/components/common/notification.component';
import { CookieConsentComponent } from './shared/components/common/cookie-consent.component';
import { CommonModule } from '@angular/common';

@Component({
selector: 'app-root',
Expand All @@ -12,16 +14,29 @@ import { NotificationComponent } from './shared/components/common/notification.c
NavbarComponent,
FooterComponent,
NotificationComponent,
CookieConsentComponent,
CommonModule,
],
template: `
<app-notification></app-notification>
<app-navbar />
<main class="max-w-full min-h-all overflow-x-hidden relative z-40">
<router-outlet />
</main>
<app-footer />
@if (!isCookiesAccepted) {
<app-cookie-consent />
}
<div
[ngClass]="{ 'filter blur-sm pointer-events-none': !isCookiesAccepted }">
<app-notification></app-notification>
<app-navbar />
<main class="max-w-full min-h-all overflow-x-hidden relative z-40">
<router-outlet />
</main>
<app-footer />
</div>
`,
})
export class AppComponent {
public title = 'RUT-AI GAMES 2';
public isCookiesAccepted = false;

public constructor() {
this.isCookiesAccepted = localStorage.getItem('cookiesAccepted') === 'true';
}
}
Original file line number Diff line number Diff line change
@@ -1,136 +1,144 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { of, throwError } from 'rxjs';
import { AdminSettingsComponent } from './admin-settings.component';
import { AdministrationEndpointsService } from '@endpoints/administration-endpoints.service';
import { NotificationService } from 'app/shared/services/notification.service';
import { of, throwError } from 'rxjs';
import { IUserResponse } from 'app/shared/models/user.models';
import { TRole } from 'app/shared/models/role.enum';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TRole } from 'app/shared/models/role.enum';

describe('AdminSettingsComponent', () => {
let component: AdminSettingsComponent;
let fixture: ComponentFixture<AdminSettingsComponent>;
let adminServiceSpy: jasmine.SpyObj<AdministrationEndpointsService>;

const mockUser: IUserResponse = {
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
role: 'Student' as TRole,
studyCycleYearA: 1,
studyCycleYearB: 2,
banned: false,
lastPlayed: '',
course: { id: 1, name: '' },
group: 'l1',
};
let mockAdminEndpointsService: jasmine.SpyObj<AdministrationEndpointsService>;

beforeEach(async () => {
const adminSpy = jasmine.createSpyObj('AdministrationEndpointsService', [
'getUsers',
'banStatus',
'changeRole',
]);
const notificationSpy = jasmine.createSpyObj('NotificationService', [
'addNotification',
]);
mockAdminEndpointsService = jasmine.createSpyObj(
'AdministrationEndpointsService',
['getUsers']
);

await TestBed.configureTestingModule({
imports: [AdminSettingsComponent, HttpClientTestingModule],
imports: [
AdminSettingsComponent,
ReactiveFormsModule,
HttpClientTestingModule,
],
providers: [
{ provide: AdministrationEndpointsService, useValue: adminSpy },
{ provide: NotificationService, useValue: notificationSpy },
{
provide: AdministrationEndpointsService,
useValue: mockAdminEndpointsService,
},
],
}).compileComponents();

fixture = TestBed.createComponent(AdminSettingsComponent);
component = fixture.componentInstance;

adminServiceSpy = TestBed.inject(
AdministrationEndpointsService
) as jasmine.SpyObj<AdministrationEndpointsService>;

fixture.detectChanges();
// Mock the subscription response
mockAdminEndpointsService.getUsers.and.returnValue(of([]));
});

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

it('should load users list when banUnbanUserModal is called', () => {
adminServiceSpy.getUsers.and.returnValue(of([mockUser]));
component.banUnbanUserModal();
expect(adminServiceSpy.getUsers).toHaveBeenCalled();
expect(component.modalVisibility).toBe('banUnbanUser');
expect(component.modalTitle).toBe('Changing ban status of user');
expect(component.modalButtonText).toBe('Set ban status');
expect(component.usersList).toEqual([mockUser]);
});
describe('ngOnInit', () => {
it('should initialize with users fetched', () => {
const mockUsers: IUserResponse[] = [
{ id: 1, email: 'test@example.com' } as IUserResponse,
];
mockAdminEndpointsService.getUsers.and.returnValue(of(mockUsers));

it('should update ban status and show notification', () => {
component.selectedUserData = mockUser;
component.isBanned = true;
adminServiceSpy.banStatus.and.returnValue(of());
component.ngOnInit();

component.banUnbanUserFunction();
expect(adminServiceSpy.banStatus).toHaveBeenCalledWith(mockUser.id, true);
expect(component.modalVisibility).toBeNull();
});
expect(mockAdminEndpointsService.getUsers).toHaveBeenCalled();
expect(component.filteredUsers).toEqual(mockUsers);
expect(component.errorMessage).toBeNull();
});

it('should display an error message if changing ban status fails', () => {
adminServiceSpy.banStatus.and.returnValue(
throwError('Error changing status')
);
component.selectedUserData = mockUser;
component.isBanned = true;
it('should handle error when fetching users', () => {
const errorMessage = 'Error fetching users';
mockAdminEndpointsService.getUsers.and.returnValue(
throwError(() => errorMessage)
);

component.banUnbanUserFunction();
expect(component.errorMessage).toBe('Error changing status');
component.ngOnInit();

expect(mockAdminEndpointsService.getUsers).toHaveBeenCalled();
expect(component.filteredUsers).toBeNull();
expect(component.errorMessage).toEqual(errorMessage);
});
});

it('should update user role and show notification', () => {
component.selectedUserData = mockUser;
component.newUserRole = TRole.Admin;
adminServiceSpy.changeRole.and.returnValue(of());
describe('showOptions', () => {
it('should toggle isOptionsVisible and emit the event if visible', () => {
spyOn(component.optionsVisibleEmitter, 'emit');

component.changeUserRoleFunction();
expect(adminServiceSpy.changeRole).toHaveBeenCalledWith(
mockUser.id,
TRole.Admin
);
expect(component.modalVisibility).toBeNull();
});
component.showOptions();
expect(component.isOptionsVisible).toBeTrue();
expect(component.optionsVisibleEmitter.emit).toHaveBeenCalledWith(
'admin'
);

it('should set error message if role change fails', () => {
adminServiceSpy.changeRole.and.returnValue(
throwError('Error changing role')
);
component.selectedUserData = mockUser;
component.newUserRole = TRole.Admin;
component.showOptions();
expect(component.isOptionsVisible).toBeFalse();
});
});

component.changeUserRoleFunction();
expect(component.errorMessage).toBe('Error changing role');
describe('applyFilters', () => {
it('should apply filters and fetch filtered users', () => {
const mockUsers: IUserResponse[] = [
{ id: 2, email: 'filtered@example.com' } as IUserResponse,
];
mockAdminEndpointsService.getUsers.and.returnValue(of(mockUsers));

component.filterForm.setValue({
role: 'Student',
email: 'test@example.com',
studyCycleYearA: null,
studyCycleYearB: null,
group: '',
courseName: '',
});

component.applyFilters();

expect(mockAdminEndpointsService.getUsers).toHaveBeenCalledWith(
'Student' as TRole,
'test@example.com',
undefined,
undefined,
'',
'',
'Asc',
'Email'
);
expect(component.filteredUsers).toEqual(mockUsers);
expect(component.errorMessage).toBeNull();
});

it('should handle error when applying filters', () => {
const errorMessage = 'Error applying filters';
mockAdminEndpointsService.getUsers.and.returnValue(
throwError(() => errorMessage)
);

component.applyFilters();

expect(mockAdminEndpointsService.getUsers).toHaveBeenCalled();
expect(component.filteredUsers).toBeNull();
expect(component.errorMessage).toEqual(errorMessage);
});
});

it('should hide modal and reset selected user data when hideModal is called', () => {
component.modalVisibility = 'banUnbanUser';
component.selectedUserData = mockUser;
describe('ngOnDestroy', () => {
it('should unsubscribe from getUsersSubscription', () => {
spyOn(component['_getUsersSubscription'], 'unsubscribe');

component.hideModal();
expect(component.modalVisibility).toBeNull();
expect(component.selectedUserData).toBeNull();
});
component.ngOnDestroy();

it('should unsubscribe from all subscriptions on component destroy', () => {
const subscriptionSpy = jasmine.createSpyObj('Subscription', [
'unsubscribe',
]);
component['_getUsersSubscription'] = subscriptionSpy;
component['_getUserStatsSubscription'] = subscriptionSpy;
component['_changeBanStatusSubscription'] = subscriptionSpy;
component['_changeRoleSubscription'] = subscriptionSpy;

component.ngOnDestroy();
expect(subscriptionSpy.unsubscribe).toHaveBeenCalledTimes(4);
expect(component['_getUsersSubscription'].unsubscribe).toHaveBeenCalled();
});
});
});
Loading