• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

juice-shop / juice-shop / 16707578486

03 Aug 2025 05:26PM UTC coverage: 85.111% (+0.04%) from 85.067%
16707578486

push

github

J12934
Pin to typescript 5.8.x

Automatic upgrade to 5.9.x broke the build

1243 of 1674 branches covered (74.25%)

Branch coverage included in aggregate %.

5131 of 5815 relevant lines covered (88.24%)

41.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.91
/frontend/src/app/payment-method/payment-method.component.ts
1
/*
2
 * Copyright (c) 2014-2025 Bjoern Kimminich & the OWASP Juice Shop contributors.
3
 * SPDX-License-Identifier: MIT
4
 */
5

6
import { UntypedFormControl, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms'
7
import { Component, EventEmitter, Input, type OnInit, Output } from '@angular/core'
8
import { PaymentService } from '../Services/payment.service'
9
import { MatTableDataSource, MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, MatCellDef, MatCell, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow } from '@angular/material/table'
10
import { library } from '@fortawesome/fontawesome-svg-core'
11
import { faPaperPlane } from '@fortawesome/free-solid-svg-icons'
12
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons/'
13
import { TranslateService, TranslateModule } from '@ngx-translate/core'
14
import { SnackBarHelperService } from '../Services/snack-bar-helper.service'
15
import { MatInputModule } from '@angular/material/input'
16
import { MatFormFieldModule, MatLabel, MatError, MatHint } from '@angular/material/form-field'
17
import { MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatExpansionPanelDescription } from '@angular/material/expansion'
18
import { MatIconButton, MatButtonModule } from '@angular/material/button'
19
import { MatRadioButton } from '@angular/material/radio'
20
import { NgIf, NgFor } from '@angular/common'
21
import { FlexModule } from '@angular/flex-layout/flex'
22
import { MatIconModule } from '@angular/material/icon'
23

24
library.add(faPaperPlane, faTrashAlt)
1✔
25

26
@Component({
27
  selector: 'app-payment-method',
28
  templateUrl: './payment-method.component.html',
29
  styleUrls: ['./payment-method.component.scss'],
30
  imports: [FlexModule, NgIf, MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, MatCellDef, MatCell, MatRadioButton, MatIconButton, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatExpansionPanelDescription, MatFormFieldModule, MatLabel, TranslateModule, MatInputModule, FormsModule, ReactiveFormsModule, MatError, MatHint, NgFor, MatButtonModule, MatIconModule]
31
})
32

33
export class PaymentMethodComponent implements OnInit {
1✔
34
  @Output() emitSelection = new EventEmitter()
37✔
35
  @Input('allowDelete') public allowDelete: boolean = false
37✔
36
  public displayedColumns = ['Number', 'Name', 'Expiry']
37✔
37
  public nameControl: UntypedFormControl = new UntypedFormControl('', [Validators.required])
37✔
38
  // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
39
  public numberControl: UntypedFormControl = new UntypedFormControl('', [Validators.required, Validators.min(1000000000000000), Validators.max(9999999999999999)])
37✔
40
  public monthControl: UntypedFormControl = new UntypedFormControl('', [Validators.required])
37✔
41
  public yearControl: UntypedFormControl = new UntypedFormControl('', [Validators.required])
37✔
42
  public confirmation: any
43
  public error: any
44
  public storedCards: any
45
  public card: any = {}
37✔
46
  public dataSource
47
  public monthRange: any[]
48
  public yearRange: any[]
49
  public cardsExist: boolean = false
37✔
50
  public paymentId: any = undefined
37✔
51

52
  constructor (public paymentService: PaymentService, private readonly translate: TranslateService, private readonly snackBarHelperService: SnackBarHelperService) { }
37✔
53

54
  ngOnInit (): void {
55
    this.monthRange = Array.from(Array(12).keys()).map(i => i + 1)
444✔
56
    this.yearRange = Array.from(Array(20).keys()).map(i => i + 2080)
740✔
57
    if (this.allowDelete) {
37✔
58
      this.displayedColumns.push('Remove')
1✔
59
    } else {
60
      this.displayedColumns.unshift('Selection')
36✔
61
    }
62
    this.load()
37✔
63
  }
64

65
  load () {
66
    this.paymentService.get().subscribe({
41✔
67
      next: (cards) => {
68
        this.cardsExist = cards.length
15✔
69
        this.storedCards = cards
15✔
70
        this.dataSource = new MatTableDataSource<Element>(this.storedCards)
15✔
71
      },
72
      error: (err) => { console.log(err) }
2✔
73
    })
74
  }
75

76
  save () {
77
    this.card.fullName = this.nameControl.value
2✔
78
    this.card.cardNum = this.numberControl.value
2✔
79
    this.card.expMonth = this.monthControl.value
2✔
80
    this.card.expYear = this.yearControl.value
2✔
81
    this.paymentService.save(this.card).subscribe({
2✔
82
      next: (savedCards) => {
83
        this.error = null
1✔
84
        this.translate.get('CREDIT_CARD_SAVED', { cardnumber: String(savedCards.cardNum).substring(String(savedCards.cardNum).length - 4) }).subscribe({
1✔
85
          next: (creditCardSaved) => {
86
            this.snackBarHelperService.open(creditCardSaved, 'confirmBar')
1✔
87
          },
88
          error: (translationId) => {
89
            this.snackBarHelperService.open(translationId, 'confirmBar')
×
90
          }
91
        })
92
        this.load()
1✔
93
        this.resetForm()
1✔
94
      },
95
      error: (err) => {
96
        this.snackBarHelperService.open(err.error?.error, 'errorBar')
1✔
97
        this.resetForm()
1✔
98
      }
99
    })
100
  }
101

102
  delete (id) {
103
    this.paymentService.del(id).subscribe({
×
104
      next: () => {
105
        this.load()
×
106
      },
107
      error: (err) => { console.log(err) }
×
108
    })
109
  }
110

111
  emitSelectionToParent (id: number) {
112
    this.emitSelection.emit(id)
×
113
  }
114

115
  resetForm () {
116
    this.nameControl.markAsUntouched()
1✔
117
    this.nameControl.markAsPristine()
1✔
118
    this.nameControl.setValue('')
1✔
119
    this.numberControl.markAsUntouched()
1✔
120
    this.numberControl.markAsPristine()
1✔
121
    this.numberControl.setValue('')
1✔
122
    this.monthControl.markAsUntouched()
1✔
123
    this.monthControl.markAsPristine()
1✔
124
    this.monthControl.setValue('')
1✔
125
    this.yearControl.markAsUntouched()
1✔
126
    this.yearControl.markAsPristine()
1✔
127
    this.yearControl.setValue('')
1✔
128
  }
129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc