Skip to content

Commit

Permalink
Feature #438: Creation of Mobile Navigation Menu
Browse files Browse the repository at this point in the history
- Nav Menu: Create Navigation Service shared for Desktop & Mobile Components.

- Navigation Service: Add initial Test.

- Navigation components: Update Tests.

- Refactor code.

- Update deprecated RouterTestingModule
  • Loading branch information
PacMM79 committed Nov 6, 2024
1 parent a648fd2 commit 1c17d2c
Show file tree
Hide file tree
Showing 18 changed files with 389 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<!-- languageSelect -->
<div>
<label for="languageSelect">
<select class="languageSelect" id="languageSelect" (change)="changeLanguage($event)" [style.width]="selectWidth">
<select class="languageSelect" (change)="changeLanguage($event)" [style.width]="navService.selectWidth">
<option value="ca">CAT</option>
<option value="es">ES</option>
<option value="en">EN</option>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,75 @@
import { type ComponentFixture, TestBed } from '@angular/core/testing'
import { DesktopNavComponent } from './desktop-nav.component'
import { TranslateService } from '@ngx-translate/core'
import { of } from 'rxjs'
import { RouterModule } from '@angular/router'
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DesktopNavComponent } from './desktop-nav.component';
import { NavService } from 'src/app/services/nav.service';
import { TranslateModule } from '@ngx-translate/core';
import { ActivatedRoute, RouterModule } from '@angular/router';

describe('DesktopNavComponent', () => {
let component: DesktopNavComponent
let fixture: ComponentFixture<DesktopNavComponent>
let translateService: TranslateService
let translateServiceUseMock: jest.Mock
// Mock de NavService
class MockNavService {
public selectWidth = '69px';

beforeEach(() => {
translateServiceUseMock = jest.fn()
openLoginModal = jest.fn(); // Simula la función openLoginModal
changeLanguage = jest.fn((language: string) => {
this.selectWidth = language === 'ca' ? '69px' : '57px';
});
}

const translateServiceStub = {
use: translateServiceUseMock,
addLangs: jest.fn(),
setDefaultLang: jest.fn(),
get: jest.fn().mockImplementation((key) => of(key))
// Mock de ActivatedRoute para pruebas
const mockActivatedRoute = {
snapshot: {
paramMap: {
get: jest.fn().mockReturnValue(null)
}
}
};

describe('DesktopNavComponent', () => {
let component: DesktopNavComponent;
let fixture: ComponentFixture<DesktopNavComponent>;
let navService: MockNavService;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [DesktopNavComponent],
imports: [RouterModule.forRoot([])], // Añade esta línea
imports: [TranslateModule.forRoot(), RouterModule.forRoot([])],
providers: [
{ provide: TranslateService, useValue: translateServiceStub }
{ provide: NavService, useClass: MockNavService },
{ provide: ActivatedRoute, useValue: mockActivatedRoute }
]
})
});

fixture = TestBed.createComponent(DesktopNavComponent)
component = fixture.componentInstance
translateService = TestBed.inject(TranslateService)
fixture.detectChanges()
})
fixture = TestBed.createComponent(DesktopNavComponent);
component = fixture.componentInstance;
navService = TestBed.inject(NavService) as unknown as MockNavService;
fixture.detectChanges();
});

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

it('should call openLoginModal when openLoginModal is invoked', () => {
component.openLoginModal();
expect(navService.openLoginModal).toHaveBeenCalled();
});

it('should change language and update selectWidth', () => {
// Limpiar todas las llamadas a la función simulada
translateServiceUseMock.mockClear()
const event = new Event('change');
Object.defineProperty(event, 'target', { value: { value: 'es' }, enumerable: true });

component.changeLanguage(event);

expect(navService.changeLanguage).toHaveBeenCalledWith('es');
expect(navService.selectWidth).toBe('57px'); // Verifica que el selectWidth se actualiza correctamente
});

const event = new Event('change')
Object.defineProperty(event, 'target', { value: { value: 'es' }, enumerable: true })
it('should change language to "ca" and update selectWidth accordingly', () => {
const event = new Event('change');
Object.defineProperty(event, 'target', { value: { value: 'ca' }, enumerable: true });

component.changeLanguage(event)
component.changeLanguage(event);

expect(translateService.use).toHaveBeenCalledWith('es')
expect(component.selectWidth).toBe('57px')
})
})
expect(navService.changeLanguage).toHaveBeenCalledWith('ca');
expect(navService.selectWidth).toBe('69px'); // Verifica que el selectWidth se actualiza correctamente
});
});
30 changes: 10 additions & 20 deletions src/app/core/layout/header/desktop-nav/desktop-nav.component.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
import { Component, inject } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { LoginModalComponent } from './../../../../modules/modals/login-modal/login-modal.component'
import { TranslateService } from '@ngx-translate/core'
import { Component } from '@angular/core';
import { NavService } from 'src/app/services/nav.service';

@Component({
selector: 'app-desktop-nav',
templateUrl: './desktop-nav.component.html',
styleUrl: './desktop-nav.component.scss'
})
export class DesktopNavComponent {
selectWidth = '69px'
private readonly modalService = inject(NgbModal)
private readonly translate = inject(TranslateService)
constructor () {
this.translate.addLangs(['en', 'es', 'ca'])
this.translate.setDefaultLang('ca')
this.translate.use('ca')
}
constructor(public navService: NavService) {}

openLoginModal (): void {
this.modalService.open(LoginModalComponent, { centered: true, size: 'lg' })
openLoginModal(): void {
this.navService.openLoginModal();
}

changeLanguage (event: Event): void {
const selectElement = event.target as HTMLSelectElement
const language = selectElement.value
this.translate.use(language)
this.selectWidth = language === 'ca' ? '69px' : '57px'
changeLanguage(event: Event): void {
const selectElement = event.target as HTMLSelectElement;
const language = selectElement.value;
this.navService.changeLanguage(language);
}
}
}
3 changes: 2 additions & 1 deletion src/app/core/layout/header/header.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { RouterTestingModule } from '@angular/router/testing'
import { HeaderComponent } from './header.component'
import { I18nModule } from '../../../../assets/i18n/i18n.module'
import { MobileNavComponent } from './mobile-nav/mobile-nav.component'
import { DesktopNavComponent } from './desktop-nav/desktop-nav.component'

describe('HeaderComponent', () => {
let component: HeaderComponent
let fixture: ComponentFixture<HeaderComponent>

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HeaderComponent, MobileNavComponent],
declarations: [HeaderComponent, MobileNavComponent, DesktopNavComponent],
imports: [
RouterTestingModule,
I18nModule
Expand Down
64 changes: 55 additions & 9 deletions src/app/core/layout/header/mobile-nav/mobile-nav.component.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
<nav class="navbar navbar-expand-lg align-items-center">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse" id="navbarToggle" data-bs-theme="dark">
<!-- Main menu -->
<div class="navbarToggle bg-black p-4">
<ul class="nav-ul">
<a class="nav-link" [routerLink]="['componentToBuild']" [routerLinkActive]="['active']" data-bs-toggle="collapse" data-bs-target="#navbarToggle">{{
"components.mainMenu.section0.title" | translate }}</a>

<a class="nav-link" [routerLink]="['challenges']" [routerLinkActive]="['active']" data-bs-toggle="collapse" data-bs-target="#navbarToggle">{{
"components.mainMenu.section1.title" | translate }}</a>

<a class="nav-link" [routerLink]="['componentToBuild']" [routerLinkActive]="['active']" data-bs-toggle="collapse" data-bs-target="#navbarToggle">{{
"components.mainMenu.section2.title" | translate }}</a>

<a class="nav-link" [routerLink]="['componentToBuild']" [routerLinkActive]="['active']" data-bs-toggle="collapse" data-bs-target="#navbarToggle">Hackathons</a>

<a class="nav-link" [routerLink]="['componentToBuild']" [routerLinkActive]="['active']" data-bs-toggle="collapse" data-bs-target="#navbarToggle">{{
"components.mainMenu.section4.title" | translate }}</a>

<!--No desenvolupo perquè a Figma encara no hi ha disseny d'aquesta part-->
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-link">item menu</li>
<a class="nav-link" href="https://dev.itawiki.eurecatacademy.org/" target="_blank" rel="noopener">{{
"components.mainMenu.section5.title" | translate }}</a>
</ul>

<div class="d-flex justify-content-end">
<!-- languageSelect -->
<div class="ms-2 pe-3">
<label for="languageSelect">
<select class="languageSelect" (change)="changeLanguage($event)" [style.width]="navService.selectWidth">
<option value="ca">CAT</option>
<option value="es">ES</option>
<option value="en">EN</option>
</select>
</label>
</div>

<!-- Settings -->
<div class="pe-3">
<a class="setting" [routerLink]="['componentToBuild']" [routerLinkActive]="['active']">
<img src="assets/img/icon/setting.svg" alt="Settings" />
</a>
</div>

<!-- User -->
<div>
<button class="user" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{ exact: true }"
(click)="openLoginModal()">
<img src="assets/img/icon/user.svg" alt="User" />
</button>
</div>
</div>
</div>
</div>

<nav class="navbar navbar-expand-md align-items-center">

<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggle"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>

<span class="breadcrumb">{{ "modules.starter.main.section2.title" | translate }}</span>
</nav>
56 changes: 54 additions & 2 deletions src/app/core/layout/header/mobile-nav/mobile-nav.component.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
@import "/src/styles/colors";

nav{
display: none;
position:fixed;
top: 0;
width: 100%;
left:50%;
transform: translate(-50%, 0%);
height: 42px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
Expand Down Expand Up @@ -44,6 +44,58 @@ $navbar-toggler-transition: none;

}

#navbarToggle {
margin-top: -7px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
position: fixed;
width: 100%;
}

.navbarToggle {
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
}

.nav-link {
color: white;
margin: 20px 0 20px 7px;
}

.nav-ul {
padding-left: 0px;
}

.languageSelect {
font-size: 1rem;
border: none;
border-radius: 0.625rem;
font-weight: 500;
background-color: $white;
padding-left: 8px;
color: $gray-6;
height: 41px;
transition: transform 0.3s ease 0s;
}

.user {
border: unset;
width: 48px;
height: 41px;
background: $white;
border-radius: 10px;
}

.setting {
width: 48px;
height: 41px;
background: $white;
border-radius: 10px;
display: flex;
justify-content: center;
align-items: center;
}

@media screen and (max-width: 768px) {
nav {
display: flex;
Expand Down
Loading

0 comments on commit 1c17d2c

Please sign in to comment.