Skip to content

Commit 4bf4306

Browse files
authored
Merge pull request #2 from quacklabs/card_validation
Card validation fully complete
2 parents 4aaa5e7 + 91ef7c3 commit 4bf4306

File tree

4 files changed

+83
-10
lines changed

4 files changed

+83
-10
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//
2+
// CardExpiryRule.swift
3+
// SwiftValidator
4+
//
5+
// Created by Mark Boleigha on 13/03/2019.
6+
// Copyright © 2019 jpotts18. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
12+
13+
/**
14+
`CardExpiryRule` is a subclass of `Rule` that defines how a credit/debit's card number field is validated
15+
*/
16+
public class CardExpiryRule: Rule {
17+
/// Error message to be displayed if validation fails.
18+
private var message : String
19+
/**
20+
Initializes `CardExpiryRule` object with error message. Used to validate a card's expiry year.
21+
22+
- parameter message: String of error message.
23+
- returns: An initialized `CardExpiryRule` object, or nil if an object could not be created for some reason that would not result in an exception.
24+
*/
25+
public init(message : String = "Card expiry date is invalid"){
26+
self.message = message
27+
}
28+
29+
/**
30+
Validates a field.
31+
32+
- parameter value: String to check for validation. must be a card expiry date in MM/YY format
33+
- returns: Boolean value. True on successful validation, otherwise False on failed Validation.
34+
*/
35+
public func validate(_ value: String) -> Bool {
36+
let date = value.replacingOccurrences(of: "/", with: "")
37+
let Index = date.index(date.startIndex, offsetBy: 2)
38+
//let yearIndex = date.index(date.endIndex, offsetBy: -2)
39+
let Month = Int(date[..<Index])
40+
let Year = Int(date[Index...])
41+
42+
///Holds the current year
43+
let thisYear = String(NSCalendar.current.component(Calendar.Component.year, from: Date()))
44+
let thisYearLast2 = thisYear.index(thisYear.startIndex, offsetBy: 2)
45+
let thisYearTwoDigits = Int(thisYear[thisYearLast2...])!
46+
47+
48+
return Month! < 12 && Year! >= thisYearTwoDigits
49+
50+
}
51+
52+
/**
53+
Used to display error message when validation fails.
54+
55+
- returns: String of error message.
56+
*/
57+
public func errorMessage() -> String {
58+
return message
59+
}
60+
61+
}

SwiftValidator/Rules/CardNumberRule.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,6 @@ public class CardNumberRule: Rule {
3434
guard CardState(fromNumber: cardNoFull) != .invalid else {
3535
return false
3636
}
37-
// let cardState = CardState(fromNumber: cardNoFull)
38-
// switch cardState {
39-
// case .identified(let cardType):
40-
// print(cardType)
41-
// case .indeterminate:
42-
// print("undefined")
43-
// case .invalid:
44-
// print("invalid")
45-
// }
4637

4738
return true
4839

SwiftValidatorTests/SwiftValidatorTests.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class SwiftValidatorTests: XCTestCase {
3434
let VALID_CARD_EXPIRY_MONTH = "10"
3535
let INVALID_CARD_EXPIRY_MONTH = "13"
3636

37-
let VALID_CARD_EXPIRY_YEAR = "2018"
37+
let VALID_CARD_EXPIRY_YEAR = "2020"
3838
let INVALID_CARD_EXPIRY_YEAR = "2016"
3939

4040
let LEN_3 = "hey"
@@ -96,6 +96,10 @@ class SwiftValidatorTests: XCTestCase {
9696
super.tearDown()
9797
}
9898

99+
//CARD EXPIRY VALIDATION VALUES
100+
let VALID_DATE = "10/29"
101+
let INVALID_DATE = "10/12"
102+
99103
//MARK: CARD NUMBER VALIDATION
100104

101105
//VISA
@@ -188,6 +192,19 @@ class SwiftValidatorTests: XCTestCase {
188192
XCTAssertNotNil(CardExpiryYearRule().errorMessage())
189193
}
190194

195+
// MARK: CARD EXPIRY DATE
196+
func testValidCardExpiryDateFull(){
197+
XCTAssertTrue(CardExpiryRule().validate(VALID_DATE), "Valid card expiry date should retun true")
198+
}
199+
200+
func testInvalidCardExpiryDateFull(){
201+
XCTAssertFalse(CardExpiryRule().validate(INVALID_DATE), "Invalid card expiry date should return false")
202+
}
203+
204+
func testInvalidCardExpiryDateFullMessage(){
205+
XCTAssertNotNil(CardExpiryYearRule().errorMessage())
206+
}
207+
191208

192209
// MARK: Required
193210

Validator.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* Begin PBXBuildFile section */
1010
256576A72232DFD900C8369F /* CardNumberRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 256576A62232DFD900C8369F /* CardNumberRule.swift */; };
1111
256576AA2232E01500C8369F /* CardParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 256576A92232E01500C8369F /* CardParser.swift */; };
12+
25FB0A2A22395AFA00373197 /* CardExpiryRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25FB0A2922395AFA00373197 /* CardExpiryRule.swift */; };
1213
62C1821D1C6312F5003788E7 /* ExactLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C1821C1C6312F5003788E7 /* ExactLengthRule.swift */; };
1314
62D1AE1D1A1E6D4400E4DFF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE1C1A1E6D4400E4DFF8 /* AppDelegate.swift */; };
1415
62D1AE221A1E6D4400E4DFF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE201A1E6D4400E4DFF8 /* Main.storyboard */; };
@@ -96,6 +97,7 @@
9697
/* Begin PBXFileReference section */
9798
256576A62232DFD900C8369F /* CardNumberRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardNumberRule.swift; sourceTree = "<group>"; };
9899
256576A92232E01500C8369F /* CardParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardParser.swift; sourceTree = "<group>"; };
100+
25FB0A2922395AFA00373197 /* CardExpiryRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardExpiryRule.swift; sourceTree = "<group>"; };
99101
62C1821C1C6312F5003788E7 /* ExactLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExactLengthRule.swift; sourceTree = "<group>"; };
100102
62D1AE171A1E6D4400E4DFF8 /* Validator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Validator.app; sourceTree = BUILT_PRODUCTS_DIR; };
101103
62D1AE1B1A1E6D4400E4DFF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -300,6 +302,7 @@
300302
FB465CEB1B9889EA00398388 /* RegexRule.swift */,
301303
FB465CEC1B9889EA00398388 /* RequiredRule.swift */,
302304
FB465CED1B9889EA00398388 /* Rule.swift */,
305+
25FB0A2922395AFA00373197 /* CardExpiryRule.swift */,
303306
FB465CEE1B9889EA00398388 /* ValidationRule.swift */,
304307
FB465CEF1B9889EA00398388 /* ZipCodeRule.swift */,
305308
62C1821C1C6312F5003788E7 /* ExactLengthRule.swift */,
@@ -538,6 +541,7 @@
538541
256576A72232DFD900C8369F /* CardNumberRule.swift in Sources */,
539542
7CC1E4D71C637F6E00AF013C /* ISBNRule.swift in Sources */,
540543
FB465D001B9889EA00398388 /* ValidationError.swift in Sources */,
544+
25FB0A2A22395AFA00373197 /* CardExpiryRule.swift in Sources */,
541545
FB465CFC1B9889EA00398388 /* RequiredRule.swift in Sources */,
542546
FB465CFB1B9889EA00398388 /* RegexRule.swift in Sources */,
543547
7CC1E4CF1C636B4500AF013C /* AlphaRule.swift in Sources */,

0 commit comments

Comments
 (0)