juice-shop

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

6
import { TranslateModule, TranslateService } from '@ngx-translate/core'
7
import { HttpClientTestingModule } from '@angular/common/http/testing'
8
import { MatCardModule } from '@angular/material/card'
9
import { MatFormFieldModule } from '@angular/material/form-field'
10
import { type ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing'
11
import { PaymentComponent } from './payment.component'
12
import { MatInputModule } from '@angular/material/input'
13
import { ReactiveFormsModule } from '@angular/forms'
14
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
15

16
import { of, throwError } from 'rxjs'
17
import { MatTableModule } from '@angular/material/table'
18
import { MatExpansionModule } from '@angular/material/expansion'
19
import { MatDividerModule } from '@angular/material/divider'
20
import { MatRadioModule } from '@angular/material/radio'
21
import { ConfigurationService } from '../Services/configuration.service'
22
import { EventEmitter } from '@angular/core'
23
import { BasketService } from '../Services/basket.service'
24
import { QrCodeComponent } from '../qr-code/qr-code.component'
25
import { MatDialog, MatDialogModule } from '@angular/material/dialog'
26
import { PaymentMethodComponent } from '../payment-method/payment-method.component'
27
import { RouterTestingModule } from '@angular/router/testing'
28
import { OrderSummaryComponent } from '../order-summary/order-summary.component'
29
import { PurchaseBasketComponent } from '../purchase-basket/purchase-basket.component'
30
import { CookieService } from 'ngx-cookie'
31
import { WalletService } from '../Services/wallet.service'
32
import { DeliveryService } from '../Services/delivery.service'
33
import { UserService } from '../Services/user.service'
34
import { LoginComponent } from '../login/login.component'
35
import { Location } from '@angular/common'
36
import { WalletComponent } from '../wallet/wallet.component'
37
import { MatIconModule } from '@angular/material/icon'
38
import { MatCheckboxModule } from '@angular/material/checkbox'
39
import { MatTooltipModule } from '@angular/material/tooltip'
40
import { MatSnackBar } from '@angular/material/snack-bar'
41

42
describe('PaymentComponent', () => {
43
  let component: PaymentComponent
44
  let fixture: ComponentFixture<PaymentComponent>
45
  let configurationService
46
  let translateService
47
  let basketService
48
  let dialog
49
  let cookieService: any
50
  let walletService: any
51
  let deliveryService: any
52
  let userService: any
53
  let snackBar: any
54

55
  beforeEach(waitForAsync(() => {
56
    configurationService = jasmine.createSpyObj('ConfigurationService', ['getApplicationConfiguration'])
57
    configurationService.getApplicationConfiguration.and.returnValue(of({}))
58
    translateService = jasmine.createSpyObj('TranslateService', ['get'])
59
    translateService.get.and.returnValue(of({}))
60
    translateService.onLangChange = new EventEmitter()
61
    translateService.onTranslationChange = new EventEmitter()
62
    translateService.onDefaultLangChange = new EventEmitter()
63
    basketService = jasmine.createSpyObj('BasketService', ['applyCoupon'])
64
    basketService.applyCoupon.and.returnValue(of({}))
65
    dialog = jasmine.createSpyObj('MatDialog', ['open'])
66
    dialog.open.and.returnValue(null)
67
    cookieService = jasmine.createSpyObj('CookieService', ['remove', 'put'])
68
    walletService = jasmine.createSpyObj('AddressService', ['get', 'put'])
69
    walletService.get.and.returnValue(of({}))
70
    walletService.put.and.returnValue(of({}))
71
    deliveryService = jasmine.createSpyObj('DeliveryService', ['getById'])
72
    deliveryService.getById.and.returnValue(of({ price: 10 }))
73
    userService = jasmine.createSpyObj('UserService', ['deluxeStatus', 'upgradeToDeluxe', 'saveLastLoginIp'])
74
    userService.deluxeStatus.and.returnValue(of({}))
75
    userService.upgradeToDeluxe.and.returnValue(of({}))
76
    userService.isLoggedIn = jasmine.createSpyObj('userService.isLoggedIn', ['next'])
77
    userService.isLoggedIn.next.and.returnValue({})
78
    userService.saveLastLoginIp.and.returnValue(of({}))
79
    snackBar = jasmine.createSpyObj('MatSnackBar', ['open'])
80

81
    TestBed.configureTestingModule({
82
      imports: [
83
        RouterTestingModule.withRoutes([
84
          { path: 'order-summary', component: OrderSummaryComponent },
85
          { path: 'login', component: LoginComponent },
86
          { path: 'wallet', component: WalletComponent }
87
        ]),
88
        TranslateModule.forRoot(),
89
        HttpClientTestingModule,
90
        ReactiveFormsModule,
91

92
        BrowserAnimationsModule,
93
        MatCardModule,
94
        MatTableModule,
95
        MatFormFieldModule,
96
        MatInputModule,
97
        MatExpansionModule,
98
        MatDividerModule,
99
        MatRadioModule,
100
        MatDialogModule,
101
        MatIconModule,
102
        MatCheckboxModule,
103
        MatTooltipModule
104
      ],
105
      declarations: [PaymentComponent, PaymentMethodComponent, OrderSummaryComponent, PurchaseBasketComponent, LoginComponent, WalletComponent],
106
      providers: [
107
        { provide: BasketService, useValue: basketService },
108
        { provide: MatDialog, useValue: dialog },
109
        { provide: TranslateService, useValue: translateService },
110
        { provide: ConfigurationService, useValue: configurationService },
111
        { provide: CookieService, useValue: cookieService },
112
        { provide: WalletService, useValue: walletService },
113
        { provide: DeliveryService, useValue: deliveryService },
114
        { provide: UserService, useValue: userService },
115
        { provide: MatSnackBar, useValue: snackBar }
116

117
      ]
118
    })
119
      .compileComponents()
120
    TestBed.inject(Location)
121
  }))
122

123
  beforeEach(() => {
124
    fixture = TestBed.createComponent(PaymentComponent)
125
    component = fixture.componentInstance
126
    fixture.detectChanges()
127
  })
128

129
  it('should create', () => {
130
    expect(component).toBeTruthy()
131
  })
132

133
  it('should not hold twitter or facebook URL if not defined in configuration', () => {
134
    configurationService.getApplicationConfiguration.and.returnValue(of({}))
135
    expect(component.twitterUrl).toBeNull()
136
    expect(component.facebookUrl).toBeNull()
137
  })
138

139
  it('should hold the default applicationName if not defined in configuration', () => {
140
    configurationService.getApplicationConfiguration.and.returnValue(of({}))
141
    expect(component.applicationName).toBe('OWASP Juice Shop')
142
  })
143

144
  it('should use custom twitter URL if configured', () => {
145
    configurationService.getApplicationConfiguration.and.returnValue(of({ application: { social: { twitterUrl: 'twitter' } } }))
146
    component.ngOnInit()
147
    expect(component.twitterUrl).toBe('twitter')
148
  })
149

150
  it('should use custom facebook URL if configured', () => {
151
    configurationService.getApplicationConfiguration.and.returnValue(of({ application: { social: { facebookUrl: 'facebook' } } }))
152
    component.ngOnInit()
153
    expect(component.facebookUrl).toBe('facebook')
154
  })
155

156
  it('should log error while getting application configuration from backend API directly to browser console', fakeAsync(() => {
157
    configurationService.getApplicationConfiguration.and.returnValue(throwError('Error'))
158
    console.log = jasmine.createSpy('log')
159
    component.ngOnInit()
160
    expect(console.log).toHaveBeenCalledWith('Error')
161
  }))
162

163
  it('should reinitizalise coupon code form by calling resetCouponForm', () => {
164
    component.couponControl.setValue('1234567890')
165
    component.resetCouponForm()
166
    expect(component.couponControl.value).toBe('')
167
    expect(component.couponControl.pristine).toBe(true)
168
    expect(component.couponControl.untouched).toBe(true)
169
  })
170

171
  it('should reject an invalid coupon code', fakeAsync(() => {
172
    basketService.applyCoupon.and.returnValue(throwError('Error'))
173

174
    component.couponControl.setValue('')
175
    component.couponControl.markAsPristine()
176
    component.couponControl.markAsUntouched()
177

178
    component.couponControl.setValue('invalid_base85')
179
    component.applyCoupon()
180

181
    expect(component.couponConfirmation).toBeUndefined()
182
    expect(component.couponError).toBe('Error')
183
  }))
184

185
  it('should accept a valid coupon code', () => {
186
    basketService.applyCoupon.and.returnValue(of(42))
187
    translateService.get.and.returnValue(of('DISCOUNT_APPLIED'))
188

189
    component.couponControl.setValue('')
190
    component.couponControl.markAsPristine()
191
    component.couponControl.markAsUntouched()
192

193
    component.couponControl.setValue('valid_base85')
194
    component.applyCoupon()
195

196
    expect(translateService.get).toHaveBeenCalledWith('DISCOUNT_APPLIED', { discount: 42 })
197
    expect(component.couponError).toBeUndefined()
198
  })
199

200
  it('should translate DISCOUNT_APPLIED message', () => {
201
    basketService.applyCoupon.and.returnValue(of(42))
202
    translateService.get.and.returnValue(of('Translation of DISCOUNT_APPLIED'))
203
    component.couponControl.setValue('')
204
    component.couponControl.markAsPristine()
205
    component.couponControl.markAsUntouched()
206

207
    component.couponControl.setValue('valid_base85')
208
    component.applyCoupon()
209

210
    expect(component.couponConfirmation).toBe('Translation of DISCOUNT_APPLIED')
211
    expect(component.couponError).toBeUndefined()
212
  })
213

214
  it('should store discount percent in session storage', () => {
215
    translateService.get.and.returnValue(of('Translation of DISCOUNT_APPLIED'))
216
    spyOn(sessionStorage, 'setItem')
217
    component.showConfirmation(70)
218
    expect(sessionStorage.setItem).toHaveBeenCalledWith('couponDiscount', 70 as any)
219
  })
220

221
  it('should store payment id on calling getMessage', () => {
222
    component.getMessage(1)
223
    expect(component.paymentId).toBe(1)
224
    expect(component.paymentMode).toEqual('card')
225
  })
226

227
  it('should open QrCodeComponent for Bitcoin', () => {
228
    component.showBitcoinQrCode()
229
    const data = {
230
      data: {
231
        data: 'bitcoin:1AbKfgvw9psQ41NbLi8kufDQTezwG8DRZm',
232
        url: './redirect?to=https://blockchain.info/address/1AbKfgvw9psQ41NbLi8kufDQTezwG8DRZm',
233
        address: '1AbKfgvw9psQ41NbLi8kufDQTezwG8DRZm',
234
        title: 'TITLE_BITCOIN_ADDRESS'
235
      }
236
    }
237
    expect(dialog.open).toHaveBeenCalledWith(QrCodeComponent, data)
238
  })
239

240
  it('should open QrCodeComponent for Dash', () => {
241
    component.showDashQrCode()
242
    const data = {
243
      data: {
244
        data: 'dash:Xr556RzuwX6hg5EGpkybbv5RanJoZN17kW',
245
        url: './redirect?to=https://explorer.dash.org/address/Xr556RzuwX6hg5EGpkybbv5RanJoZN17kW',
246
        address: 'Xr556RzuwX6hg5EGpkybbv5RanJoZN17kW',
247
        title: 'TITLE_DASH_ADDRESS'
248
      }
249
    }
250
    expect(dialog.open).toHaveBeenCalledWith(QrCodeComponent, data)
251
  })
252

253
  it('should open QrCodeComponent for Ether', () => {
254
    component.showEtherQrCode()
255
    const data = {
256
      data: {
257
        data: '0x0f933ab9fCAAA782D0279C300D73750e1311EAE6',
258
        url: './redirect?to=https://etherscan.io/address/0x0f933ab9fcaaa782d0279c300d73750e1311eae6',
259
        address: '0x0f933ab9fCAAA782D0279C300D73750e1311EAE6',
260
        title: 'TITLE_ETHER_ADDRESS'
261
      }
262
    }
263
    expect(dialog.open).toHaveBeenCalledWith(QrCodeComponent, data)
264
  })
265

266
  it('should call initTotal on calling ngOnInit', () => {
267
    spyOn(component, 'initTotal')
268
    component.ngOnInit()
269
    expect(component.initTotal).toHaveBeenCalled()
270
  })
271

272
  it('should call initTotal on calling showConfirmation', () => {
273
    spyOn(component, 'initTotal')
274
    component.showConfirmation(10)
275
    expect(component.initTotal).toHaveBeenCalled()
276
  })
277

278
  it('should make paymentMode wallet on calling useWallet', () => {
279
    component.useWallet()
280
    expect(component.paymentMode).toEqual('wallet')
281
  })
282

283
  it('should store paymentId in session storage on calling choosePayment in shop mode', () => {
284
    component.mode = 'shop'
285
    component.paymentMode = 'card'
286
    component.paymentId = 1
287
    spyOn(sessionStorage, 'setItem')
288
    component.choosePayment()
289
    expect(sessionStorage.setItem).toHaveBeenCalledWith('paymentId', 1 as any)
290
  })
291

292
  it('should store wallet as paymentId in session storage on calling choosePayment while paymentMode is equal to wallet', () => {
293
    component.mode = 'shop'
294
    component.paymentMode = 'wallet'
295
    spyOn(sessionStorage, 'setItem')
296
    component.choosePayment()
297
    expect(sessionStorage.setItem).toHaveBeenCalledWith('paymentId', 'wallet')
298
  })
299

300
  it('should log error from upgrade to deluxe API call directly to browser console', fakeAsync(() => {
301
    component.mode = 'deluxe'
302
    userService.upgradeToDeluxe.and.returnValue(throwError('Error'))
303
    console.log = jasmine.createSpy('log')
304
    component.choosePayment()
305
    fixture.detectChanges()
306
    expect(console.log).toHaveBeenCalledWith('Error')
307
  }))
308

309
  it('should remove walletTotal from session storage on calling choosePayment in wallet mode', () => {
310
    component.mode = 'wallet'
311
    walletService.put.and.returnValue(of({}))
312
    spyOn(sessionStorage, 'removeItem')
313
    component.choosePayment()
314
    expect(sessionStorage.removeItem).toHaveBeenCalledWith('walletTotal')
315
  })
316

317
  it('should add token to local storage and cookie on calling choosePayment in deluxe mode', () => {
318
    component.mode = 'deluxe'
319
    userService.upgradeToDeluxe.and.returnValue(of({ token: 'tokenValue' }))
320
    spyOn(localStorage, 'setItem')
321
    component.choosePayment()
322
    expect(localStorage.setItem).toHaveBeenCalledWith('token', 'tokenValue')
323
    expect(cookieService.put).toHaveBeenCalledWith('token', 'tokenValue')
324
  })
325
})
326

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

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

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

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