juice-shop

Форк
0
/
navbar.component.spec.ts 
283 строки · 10.9 Кб
1
/*
2
 * Copyright (c) 2014-2024 Bjoern Kimminich & the OWASP Juice Shop contributors.
3
 * SPDX-License-Identifier: MIT
4
 */
5

6
import { ChallengeService } from '../Services/challenge.service'
7
import { SearchResultComponent } from '../search-result/search-result.component'
8
import { TranslateModule, TranslateService } from '@ngx-translate/core'
9
import { UserService } from '../Services/user.service'
10
import { ConfigurationService } from '../Services/configuration.service'
11
import { type ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'
12
import { HttpClientTestingModule } from '@angular/common/http/testing'
13
import { NavbarComponent } from './navbar.component'
14
import { Location } from '@angular/common'
15

16
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
17
import { MatSelectModule } from '@angular/material/select'
18
import { MatFormFieldModule } from '@angular/material/form-field'
19
import { MatIconModule } from '@angular/material/icon'
20
import { MatToolbarModule } from '@angular/material/toolbar'
21
import { MatButtonModule } from '@angular/material/button'
22
import { AdministrationService } from '../Services/administration.service'
23
import { RouterTestingModule } from '@angular/router/testing'
24
import { MatMenuModule } from '@angular/material/menu'
25
import { MatTooltipModule } from '@angular/material/tooltip'
26
import { CookieModule, CookieService } from 'ngx-cookie'
27
import { SocketIoService } from '../Services/socket-io.service'
28
import { of, throwError } from 'rxjs'
29
import { MatCardModule } from '@angular/material/card'
30
import { MatInputModule } from '@angular/material/input'
31
import { MatTableModule } from '@angular/material/table'
32
import { MatPaginatorModule } from '@angular/material/paginator'
33
import { MatDialogModule } from '@angular/material/dialog'
34
import { MatDividerModule } from '@angular/material/divider'
35
import { MatGridListModule } from '@angular/material/grid-list'
36
import { NgMatSearchBarModule } from 'ng-mat-search-bar'
37
import { LoginGuard } from '../app.guard'
38
import { MatRadioModule } from '@angular/material/radio'
39
import { MatSnackBarModule } from '@angular/material/snack-bar'
40

41
class MockSocket {
42
  on (str: string, callback: any) {
43
    callback(str)
44
  }
45
}
46

47
describe('NavbarComponent', () => {
48
  let component: NavbarComponent
49
  let fixture: ComponentFixture<NavbarComponent>
50
  let administrationService: any
51
  let configurationService: any
52
  let userService: any
53
  let challengeService: any
54
  let translateService: any
55
  let cookieService: any
56
  let mockSocket: any
57
  let socketIoService: any
58
  let location: Location
59
  let loginGuard
60

61
  beforeEach(waitForAsync(() => {
62
    administrationService = jasmine.createSpyObj('AdministrationService', ['getApplicationVersion'])
63
    administrationService.getApplicationVersion.and.returnValue(of(undefined))
64
    configurationService = jasmine.createSpyObj('ConfigurationService', ['getApplicationConfiguration'])
65
    configurationService.getApplicationConfiguration.and.returnValue(of({}))
66
    userService = jasmine.createSpyObj('UserService', ['whoAmI', 'getLoggedInState', 'saveLastLoginIp'])
67
    userService.whoAmI.and.returnValue(of({}))
68
    userService.getLoggedInState.and.returnValue(of(true))
69
    userService.saveLastLoginIp.and.returnValue(of({}))
70
    userService.isLoggedIn = jasmine.createSpyObj('userService.isLoggedIn', ['next'])
71
    userService.isLoggedIn.next.and.returnValue({})
72
    challengeService = jasmine.createSpyObj('ChallengeService', ['find'])
73
    challengeService.find.and.returnValue(of([{ solved: false }]))
74
    cookieService = jasmine.createSpyObj('CookieService', ['remove', 'get', 'put'])
75
    mockSocket = new MockSocket()
76
    socketIoService = jasmine.createSpyObj('SocketIoService', ['socket'])
77
    socketIoService.socket.and.returnValue(mockSocket)
78
    loginGuard = jasmine.createSpyObj('LoginGuard', ['tokenDecode'])
79
    loginGuard.tokenDecode.and.returnValue(of(true))
80

81
    TestBed.configureTestingModule({
82
      declarations: [NavbarComponent, SearchResultComponent],
83
      imports: [
84
        RouterTestingModule.withRoutes([
85
          { path: 'search', component: SearchResultComponent }
86
        ]),
87
        HttpClientTestingModule,
88
        CookieModule.forRoot(),
89
        TranslateModule.forRoot(),
90
        BrowserAnimationsModule,
91
        MatToolbarModule,
92
        MatIconModule,
93
        MatFormFieldModule,
94
        MatSelectModule,
95
        MatButtonModule,
96
        MatMenuModule,
97
        MatTooltipModule,
98
        MatCardModule,
99
        MatInputModule,
100
        MatTableModule,
101
        MatPaginatorModule,
102
        MatDialogModule,
103
        MatDividerModule,
104
        MatGridListModule,
105
        NgMatSearchBarModule,
106
        MatRadioModule,
107
        MatSnackBarModule
108
      ],
109
      providers: [
110
        { provide: AdministrationService, useValue: administrationService },
111
        { provide: ConfigurationService, useValue: configurationService },
112
        { provide: UserService, useValue: userService },
113
        { provide: ChallengeService, useValue: challengeService },
114
        { provide: CookieService, useValue: cookieService },
115
        { provide: SocketIoService, useValue: socketIoService },
116
        { provide: LoginGuard, useValue: loginGuard },
117
        TranslateService
118
      ]
119
    })
120
      .compileComponents()
121

122
    location = TestBed.inject(Location)
123
    translateService = TestBed.inject(TranslateService)
124
  }))
125

126
  beforeEach(() => {
127
    fixture = TestBed.createComponent(NavbarComponent)
128
    component = fixture.componentInstance
129
    localStorage.removeItem('token')
130
    fixture.detectChanges()
131
  })
132

133
  it('should create', () => {
134
    expect(component).toBeTruthy()
135
  })
136

137
  it('should hold application version', () => {
138
    administrationService.getApplicationVersion.and.returnValue(of('x.y.z'))
139
    component.ngOnInit()
140
    expect(component.version).toBe('vx.y.z')
141
  })
142

143
  it('should show nothing on missing application version', () => {
144
    administrationService.getApplicationVersion.and.returnValue(of(undefined))
145
    component.ngOnInit()
146
    expect(component.version).toBe('')
147
  })
148

149
  it('should show nothing on error retrieving application version', fakeAsync(() => {
150
    administrationService.getApplicationVersion.and.returnValue(throwError('Error'))
151
    component.ngOnInit()
152
    expect(component.version).toBe('')
153
  }))
154

155
  it('should log errors directly to browser console', fakeAsync(() => {
156
    administrationService.getApplicationVersion.and.returnValue(throwError('Error'))
157
    console.log = jasmine.createSpy('log')
158
    component.ngOnInit()
159
    expect(console.log).toHaveBeenCalledWith('Error')
160
  }))
161

162
  it('should use default application name if not customized', () => {
163
    configurationService.getApplicationConfiguration.and.returnValue(of({}))
164
    component.ngOnInit()
165
    expect(component.applicationName).toBe('OWASP Juice Shop')
166
  })
167

168
  it('should use custom application name URL if configured', () => {
169
    configurationService.getApplicationConfiguration.and.returnValue(of({ application: { name: 'name' } }))
170
    component.ngOnInit()
171
    expect(component.applicationName).toBe('name')
172
  })
173

174
  it('should set user email on page reload if user is authenticated', () => {
175
    userService.whoAmI.and.returnValue(of({ email: 'dummy@dummy.com' }))
176
    localStorage.setItem('token', 'token')
177
    component.ngOnInit()
178
    expect(component.userEmail).toBe('dummy@dummy.com')
179
  })
180

181
  it('should set user email on getting logged in', () => {
182
    localStorage.removeItem('token')
183
    userService.getLoggedInState.and.returnValue(of(true))
184
    userService.whoAmI.and.returnValue(of({ email: 'dummy@dummy.com' }))
185
    component.ngOnInit()
186
    expect(component.userEmail).toBe('dummy@dummy.com')
187
  })
188

189
  it('should log errors directly to browser console when getting user failed', fakeAsync(() => {
190
    userService.whoAmI.and.returnValue(throwError('Error'))
191
    console.log = jasmine.createSpy('log')
192
    component.ngOnInit()
193
    expect(console.log).toHaveBeenCalledWith('Error')
194
  }))
195

196
  it('should show GitHub button by default', () => {
197
    configurationService.getApplicationConfiguration.and.returnValue(of({}))
198
    component.ngOnInit()
199
    expect(component.showGitHubLink).toBe(true)
200
  })
201

202
  it('should hide GitHub ribbon if so configured', () => {
203
    configurationService.getApplicationConfiguration.and.returnValue(of({ application: { showGitHubLinks: false } }))
204
    component.ngOnInit()
205
    expect(component.showGitHubLink).toBe(false)
206
  })
207

208
  it('should log error while getting application configuration from backend API directly to browser console', fakeAsync(() => {
209
    configurationService.getApplicationConfiguration.and.returnValue(throwError('Error'))
210
    console.log = jasmine.createSpy('log')
211
    component.ngOnInit()
212
    expect(console.log).toHaveBeenCalledWith('Error')
213
  }))
214

215
  it('should hide Score Board menu item when corresponding challenge was not solved yet', () => {
216
    challengeService.find.and.returnValue(of([{ solved: false }]))
217
    component.ngOnInit()
218
    expect(component.scoreBoardVisible).toBeFalsy()
219
  })
220

221
  it('should show Score Board menu item if corresponding challenge has been solved', () => {
222
    challengeService.find.and.returnValue(of([{ solved: true }]))
223
    component.ngOnInit()
224
    expect(component.scoreBoardVisible).toBe(true)
225
  })
226

227
  it('forwards to search result with search query as URL parameter', fakeAsync(() => {
228
    component.search('lemon juice')
229
    tick()
230
    expect(location.path()).toBe(encodeURI('/search?q=lemon juice'))
231
  }))
232

233
  it('forwards to search result with empty search criteria if no search query is present', fakeAsync(() => {
234
    component.search('')
235
    tick()
236
    expect(location.path()).toBe(encodeURI('/search'))
237
  }))
238

239
  it('should remove authentication token from localStorage', () => {
240
    spyOn(localStorage, 'removeItem')
241
    component.logout()
242
    expect(localStorage.removeItem).toHaveBeenCalledWith('token')
243
  })
244

245
  it('should remove authentication token from cookies', () => {
246
    component.logout()
247
    expect(cookieService.remove).toHaveBeenCalledWith('token')
248
  })
249

250
  it('should remove basket id from session storage', () => {
251
    spyOn(sessionStorage, 'removeItem')
252
    component.logout()
253
    expect(sessionStorage.removeItem).toHaveBeenCalledWith('bid')
254
  })
255

256
  it('should remove basket item total from session storage', () => {
257
    spyOn(sessionStorage, 'removeItem')
258
    component.logout()
259
    expect(sessionStorage.removeItem).toHaveBeenCalledWith('itemTotal')
260
  })
261

262
  it('should set the login status to be false via UserService', () => {
263
    component.logout()
264
    expect(userService.isLoggedIn.next).toHaveBeenCalledWith(false)
265
  })
266

267
  it('should save the last login IP address', () => {
268
    component.logout()
269
    expect(userService.saveLastLoginIp).toHaveBeenCalled()
270
  })
271

272
  it('should forward to main page', fakeAsync(() => {
273
    component.logout()
274
    tick()
275
    expect(location.path()).toBe('/')
276
  }))
277

278
  it('should set selected a language', () => {
279
    spyOn(translateService, 'use').and.callFake((lang: any) => lang)
280
    component.changeLanguage('xx')
281
    expect(translateService.use).toHaveBeenCalledWith('xx')
282
  })
283
})
284

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.