Separate parser and helpers from Password class for better testability
This commit is contained in:
parent
2abbceb2e9
commit
7c12263458
17 changed files with 913 additions and 537 deletions
276
passKitTests/Models/PasswordTest.swift
Normal file
276
passKitTests/Models/PasswordTest.swift
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
//
|
||||
// PasswordTests.swift
|
||||
// passKitTests
|
||||
//
|
||||
// Created by Danny Moesch on 02.05.18.
|
||||
// Copyright © 2018 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable import passKit
|
||||
|
||||
class PasswordTest: XCTestCase {
|
||||
|
||||
private let PASSWORD_PATH = "/path/to/password"
|
||||
private let PASSWORD_URL = URL(fileURLWithPath: "/path/to/password")
|
||||
private let PASSWORD_STRING = "abcd1234"
|
||||
private let OTP_TOKEN = "otpauth://totp/email@email.com?secret=abcd1234"
|
||||
|
||||
private let SECURE_URL_FIELD = "url" => "https://secure.com"
|
||||
private let INSECURE_URL_FIELD = "url" => "http://insecure.com"
|
||||
private let LOGIN_FIELD = "login" => "login name"
|
||||
private let USERNAME_FIELD = "username" => "some username"
|
||||
private let NOTE_FIELD = "note" => "A NOTE"
|
||||
private let HINT_FIELD = "some hints" => "äöüß // €³ %% −° && @²` | [{\\}],.<>"
|
||||
|
||||
func testUrl() {
|
||||
let password = getPasswordObjectWith(content: "")
|
||||
XCTAssertEqual(password.url, PASSWORD_URL)
|
||||
XCTAssertEqual(password.namePath, PASSWORD_PATH)
|
||||
}
|
||||
|
||||
func testEmptyFile() {
|
||||
[
|
||||
"",
|
||||
"\n",
|
||||
].forEach { fileContent in
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, "")
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
|
||||
XCTAssertEqual(password.additionsPlainText, "")
|
||||
XCTAssertTrue(password.getFilteredAdditions().isEmpty)
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertNil(password.urlString)
|
||||
XCTAssertNil(password.login)
|
||||
}
|
||||
}
|
||||
|
||||
func testEmptyPassword() {
|
||||
let fileContent = "\n\(LOGIN_FIELD.asString)"
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, "")
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, LOGIN_FIELD.asString)
|
||||
|
||||
XCTAssertFalse(does(password, contain: LOGIN_FIELD))
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertNil(password.urlString)
|
||||
XCTAssertEqual(password.login, LOGIN_FIELD.content)
|
||||
}
|
||||
|
||||
func testSimplePasswordFile() {
|
||||
let additions = SECURE_URL_FIELD | LOGIN_FIELD | USERNAME_FIELD | NOTE_FIELD
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: SECURE_URL_FIELD))
|
||||
XCTAssertFalse(does(password, contain: LOGIN_FIELD))
|
||||
XCTAssertFalse(does(password, contain: USERNAME_FIELD))
|
||||
XCTAssertTrue(does(password, contain: NOTE_FIELD))
|
||||
|
||||
XCTAssertEqual(password.urlString, SECURE_URL_FIELD.content)
|
||||
XCTAssertEqual(password.login, LOGIN_FIELD.content)
|
||||
XCTAssertEqual(password.username, USERNAME_FIELD.content)
|
||||
}
|
||||
|
||||
func testTwoPasswords() {
|
||||
let additions = "efgh5678" | INSECURE_URL_FIELD
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: INSECURE_URL_FIELD))
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(1) => "efgh5678"))
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertEqual(password.urlString, INSECURE_URL_FIELD.content)
|
||||
XCTAssertNil(password.login)
|
||||
}
|
||||
|
||||
func testNoPassword() {
|
||||
let fileContent = SECURE_URL_FIELD | NOTE_FIELD
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, SECURE_URL_FIELD.asString)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, NOTE_FIELD.asString)
|
||||
|
||||
XCTAssertTrue(does(password, contain: NOTE_FIELD))
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertNil(password.urlString)
|
||||
XCTAssertNil(password.login)
|
||||
}
|
||||
|
||||
func testDuplicateKeys() {
|
||||
let additions = SECURE_URL_FIELD | INSECURE_URL_FIELD
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: SECURE_URL_FIELD))
|
||||
XCTAssertTrue(does(password, contain: INSECURE_URL_FIELD))
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertEqual(password.urlString, SECURE_URL_FIELD.content)
|
||||
XCTAssertNil(password.login)
|
||||
}
|
||||
|
||||
func testUnknownKeys() {
|
||||
let value1 = "value 1"
|
||||
let value2 = "value 2"
|
||||
let value3 = "value 3"
|
||||
let value4 = "value 4"
|
||||
let additions = value1 | NOTE_FIELD | value2 | value3 | SECURE_URL_FIELD | value4
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(1) => value1))
|
||||
XCTAssertTrue(does(password, contain: NOTE_FIELD))
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(2) => value2))
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(3) => value3))
|
||||
XCTAssertTrue(does(password, contain: SECURE_URL_FIELD))
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(4) => value4))
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertEqual(password.urlString, SECURE_URL_FIELD.content)
|
||||
XCTAssertNil(password.login)
|
||||
}
|
||||
|
||||
func testPasswordFileWithOtpToken() {
|
||||
let additions = NOTE_FIELD | OTP_TOKEN
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertEqual(password.otpType, OtpType.totp)
|
||||
XCTAssertNotNil(password.getOtp())
|
||||
}
|
||||
|
||||
func testFirstLineIsOtpToken() {
|
||||
let password = getPasswordObjectWith(content: OTP_TOKEN)
|
||||
|
||||
XCTAssertEqual(password.password, OTP_TOKEN)
|
||||
XCTAssertEqual(password.plainData, OTP_TOKEN.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, "")
|
||||
|
||||
XCTAssertNil(password.username)
|
||||
XCTAssertNil(password.urlString)
|
||||
XCTAssertNil(password.login)
|
||||
|
||||
XCTAssertEqual(password.otpType, OtpType.totp)
|
||||
XCTAssertNotNil(password.getOtp())
|
||||
}
|
||||
|
||||
func testWrongOtpToken() {
|
||||
let fileContent = "otpauth://htop/blabla"
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, fileContent)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertTrue(password.additionsPlainText.isEmpty)
|
||||
|
||||
XCTAssertEqual(password.otpType, OtpType.none)
|
||||
XCTAssertNil(password.getOtp())
|
||||
}
|
||||
|
||||
func testEmptyMultilineValues() {
|
||||
let lineBreakField1 = "with line breaks" => "| \n"
|
||||
let lineBreakField2 = "with line breaks" => "| \n "
|
||||
let noLineBreakField = "without line breaks" => " > "
|
||||
let additions = lineBreakField1 | lineBreakField2 | NOTE_FIELD | noLineBreakField
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: lineBreakField1.title => ""))
|
||||
XCTAssertTrue(does(password, contain: lineBreakField2.title => ""))
|
||||
XCTAssertTrue(does(password, contain: NOTE_FIELD))
|
||||
XCTAssertTrue(does(password, contain: noLineBreakField.title => ""))
|
||||
}
|
||||
|
||||
func testMultilineValues() {
|
||||
let lineBreakField = "with line breaks" => "|\n This is \n text spread over \n multiple lines! "
|
||||
let noLineBreakField = "without line breaks" => " > \n This is \n text spread over\n multiple lines!"
|
||||
let additions = lineBreakField | NOTE_FIELD | noLineBreakField
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: lineBreakField.title => "This is \n text spread over \nmultiple lines!"))
|
||||
XCTAssertTrue(does(password, contain: NOTE_FIELD))
|
||||
XCTAssertTrue(does(password, contain: noLineBreakField.title => "This is text spread over multiple lines!"))
|
||||
}
|
||||
|
||||
func testMultilineValuesMixed() {
|
||||
let lineBreakField = "with line breaks" => "|\n This is \n \(HINT_FIELD.asString) spread over\n multiple lines!"
|
||||
let noLineBreakField = "without line breaks" => " > \n This is \n | \n text spread over\nmultiple lines!"
|
||||
let additions = lineBreakField | noLineBreakField | NOTE_FIELD
|
||||
let fileContent = PASSWORD_STRING | additions
|
||||
let password = getPasswordObjectWith(content: fileContent)
|
||||
|
||||
XCTAssertEqual(password.password, PASSWORD_STRING)
|
||||
XCTAssertEqual(password.plainData, fileContent.data(using: .utf8))
|
||||
XCTAssertEqual(password.additionsPlainText, additions)
|
||||
|
||||
XCTAssertTrue(does(password, contain: lineBreakField.title => "This is \n\(HINT_FIELD.asString) spread over"))
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(1) => " multiple lines!"))
|
||||
XCTAssertTrue(does(password, contain: noLineBreakField.title => "This is | text spread over"))
|
||||
XCTAssertTrue(does(password, contain: Constants.unknown(2) => "multiple lines!"))
|
||||
XCTAssertTrue(does(password, contain: NOTE_FIELD))
|
||||
}
|
||||
|
||||
func testUpdatePassword() {
|
||||
let password = getPasswordObjectWith(content: "")
|
||||
XCTAssertEqual(password.changed, 0)
|
||||
|
||||
password.updatePassword(name: "password", url: PASSWORD_URL, plainText: "")
|
||||
XCTAssertEqual(password.changed, 0)
|
||||
|
||||
password.updatePassword(name: "", url: PASSWORD_URL, plainText: "a")
|
||||
XCTAssertEqual(password.changed, 2)
|
||||
|
||||
password.updatePassword(name: "", url: URL(fileURLWithPath: "/some/path/"), plainText: "a")
|
||||
XCTAssertEqual(password.changed, 3)
|
||||
|
||||
password.updatePassword(name: "", url: PASSWORD_URL, plainText: "")
|
||||
XCTAssertEqual(password.changed, 3)
|
||||
}
|
||||
|
||||
private func getPasswordObjectWith(content: String, url: URL? = nil) -> Password {
|
||||
return Password(name: "password", url: url ?? PASSWORD_URL, plainText: content)
|
||||
}
|
||||
|
||||
private func does(_ password: Password, contain field: AdditionField) -> Bool {
|
||||
return password.getFilteredAdditions().contains(field)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue