-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to Swift Testing for PassesTests
- Loading branch information
1 parent
939492b
commit 805a194
Showing
11 changed files
with
661 additions
and
725 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 6 additions & 4 deletions
10
Tests/OrdersTests/SecretMiddleware.swift → ...es/PassKit/Testing/SecretMiddleware.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Vapor | ||
|
||
package let isLoggingConfigured: Bool = { | ||
LoggingSystem.bootstrap { label in | ||
var handler = StreamLogHandler.standardOutput(label: label) | ||
handler.logLevel = .debug | ||
return handler | ||
} | ||
return true | ||
}() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,177 +1,135 @@ | ||
import Fluent | ||
import FluentSQLiteDriver | ||
import PassKit | ||
import Testing | ||
import XCTVapor | ||
import Zip | ||
|
||
@testable import Passes | ||
|
||
final class EncryptedPassesTests: XCTestCase { | ||
struct EncryptedPassesTests { | ||
let delegate = EncryptedPassesDelegate() | ||
let passesURI = "/api/passes/v1/" | ||
var passesService: PassesService! | ||
var app: Application! | ||
|
||
override func setUp() async throws { | ||
self.app = try await Application.make(.testing) | ||
app.databases.use(.sqlite(.memory), as: .sqlite) | ||
|
||
PassesService.register(migrations: app.migrations) | ||
app.migrations.add(CreatePassData()) | ||
passesService = try PassesService( | ||
app: app, | ||
delegate: delegate, | ||
pushRoutesMiddleware: SecretMiddleware(secret: "foo"), | ||
logger: app.logger | ||
) | ||
app.databases.middleware.use(PassDataMiddleware(service: passesService), on: .sqlite) | ||
|
||
try await app.autoMigrate() | ||
|
||
Zip.addCustomFileExtension("pkpass") | ||
} | ||
|
||
override func tearDown() async throws { | ||
try await app.autoRevert() | ||
try await self.app.asyncShutdown() | ||
self.app = nil | ||
@Test func passGeneration() async throws { | ||
try await withApp(delegate: delegate) { app, passesService in | ||
let passData = PassData(title: "Test Pass") | ||
try await passData.create(on: app.db) | ||
let pass = try await passData.$pass.get(on: app.db) | ||
let data = try await passesService.generatePassContent(for: pass, on: app.db) | ||
let passURL = FileManager.default.temporaryDirectory.appendingPathComponent("test.pkpass") | ||
try data.write(to: passURL) | ||
let passFolder = try Zip.quickUnzipFile(passURL) | ||
|
||
#expect(FileManager.default.fileExists(atPath: passFolder.path.appending("/signature"))) | ||
|
||
let passJSONData = try String(contentsOfFile: passFolder.path.appending("/pass.json")).data(using: .utf8) | ||
let passJSON = try JSONSerialization.jsonObject(with: passJSONData!) as! [String: Any] | ||
#expect(passJSON["authenticationToken"] as? String == pass.authenticationToken) | ||
let passID = try pass.requireID().uuidString | ||
#expect(passJSON["serialNumber"] as? String == passID) | ||
#expect(passJSON["description"] as? String == passData.title) | ||
|
||
let manifestJSONData = try String(contentsOfFile: passFolder.path.appending("/manifest.json")).data(using: .utf8) | ||
let manifestJSON = try JSONSerialization.jsonObject(with: manifestJSONData!) as! [String: Any] | ||
let iconData = try Data(contentsOf: passFolder.appendingPathComponent("/icon.png")) | ||
let iconHash = Array(Insecure.SHA1.hash(data: iconData)).hex | ||
#expect(manifestJSON["icon.png"] as? String == iconHash) | ||
} | ||
} | ||
|
||
func testPassGeneration() async throws { | ||
let passData = PassData(title: "Test Pass") | ||
try await passData.create(on: app.db) | ||
let pass = try await passData.$pass.get(on: app.db) | ||
let data = try await passesService.generatePassContent(for: pass, on: app.db) | ||
let passURL = FileManager.default.temporaryDirectory.appendingPathComponent("test.pkpass") | ||
try data.write(to: passURL) | ||
let passFolder = try Zip.quickUnzipFile(passURL) | ||
|
||
XCTAssert(FileManager.default.fileExists(atPath: passFolder.path.appending("/signature"))) | ||
|
||
let passJSONData = try String(contentsOfFile: passFolder.path.appending("/pass.json")).data( | ||
using: .utf8) | ||
let passJSON = try JSONSerialization.jsonObject(with: passJSONData!) as! [String: Any] | ||
XCTAssertEqual(passJSON["authenticationToken"] as? String, pass.authenticationToken) | ||
try XCTAssertEqual(passJSON["serialNumber"] as? String, pass.requireID().uuidString) | ||
XCTAssertEqual(passJSON["description"] as? String, passData.title) | ||
|
||
let manifestJSONData = try String( | ||
contentsOfFile: passFolder.path.appending("/manifest.json") | ||
).data(using: .utf8) | ||
let manifestJSON = | ||
try JSONSerialization.jsonObject(with: manifestJSONData!) as! [String: Any] | ||
let iconData = try Data(contentsOf: passFolder.appendingPathComponent("/icon.png")) | ||
let iconHash = Array(Insecure.SHA1.hash(data: iconData)).hex | ||
XCTAssertEqual(manifestJSON["icon.png"] as? String, iconHash) | ||
} | ||
@Test func personalizationAPI() async throws { | ||
try await withApp(delegate: delegate) { app, passesService in | ||
let passData = PassData(title: "Personalize") | ||
try await passData.create(on: app.db) | ||
let pass = try await passData.$pass.get(on: app.db) | ||
let personalizationDict = PersonalizationDictionaryDTO( | ||
personalizationToken: "1234567890", | ||
requiredPersonalizationInfo: .init( | ||
emailAddress: "[email protected]", | ||
familyName: "Doe", | ||
fullName: "John Doe", | ||
givenName: "John", | ||
isoCountryCode: "US", | ||
phoneNumber: "1234567890", | ||
postalCode: "12345" | ||
) | ||
) | ||
|
||
func testPersonalizationAPI() async throws { | ||
let passData = PassData(title: "Personalize") | ||
try await passData.create(on: app.db) | ||
let pass = try await passData.$pass.get(on: app.db) | ||
let personalizationDict = PersonalizationDictionaryDTO( | ||
personalizationToken: "1234567890", | ||
requiredPersonalizationInfo: .init( | ||
emailAddress: "[email protected]", | ||
familyName: "Doe", | ||
fullName: "John Doe", | ||
givenName: "John", | ||
isoCountryCode: "US", | ||
phoneNumber: "1234567890", | ||
postalCode: "12345" | ||
try await app.test( | ||
.POST, | ||
"\(passesURI)passes/\(pass.passTypeIdentifier)/\(pass.requireID())/personalize", | ||
headers: ["Authorization": "ApplePass \(pass.authenticationToken)"], | ||
beforeRequest: { req async throws in | ||
try req.content.encode(personalizationDict) | ||
}, | ||
afterResponse: { res async throws in | ||
#expect(res.status == .ok) | ||
#expect(res.body != nil) | ||
#expect(res.headers.contentType?.description == "application/octet-stream") | ||
} | ||
) | ||
) | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)passes/\(pass.passTypeIdentifier)/\(pass.requireID())/personalize", | ||
headers: ["Authorization": "ApplePass \(pass.authenticationToken)"], | ||
beforeRequest: { req async throws in | ||
try req.content.encode(personalizationDict) | ||
}, | ||
afterResponse: { res async throws in | ||
XCTAssertEqual(res.status, .ok) | ||
XCTAssertNotNil(res.body) | ||
XCTAssertEqual(res.headers.contentType?.description, "application/octet-stream") | ||
} | ||
) | ||
|
||
let personalizationQuery = try await UserPersonalization.query(on: app.db).all() | ||
XCTAssertEqual(personalizationQuery.count, 1) | ||
let passPersonalizationID = try await Pass.query(on: app.db).first()? | ||
._$userPersonalization.get(on: app.db)? | ||
.requireID() | ||
XCTAssertEqual(personalizationQuery[0]._$id.value, passPersonalizationID) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$emailAddress.value, | ||
personalizationDict.requiredPersonalizationInfo.emailAddress) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$familyName.value, | ||
personalizationDict.requiredPersonalizationInfo.familyName) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$fullName.value, | ||
personalizationDict.requiredPersonalizationInfo.fullName) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$givenName.value, | ||
personalizationDict.requiredPersonalizationInfo.givenName) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$isoCountryCode.value, | ||
personalizationDict.requiredPersonalizationInfo.isoCountryCode) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$phoneNumber.value, | ||
personalizationDict.requiredPersonalizationInfo.phoneNumber) | ||
XCTAssertEqual( | ||
personalizationQuery[0]._$postalCode.value, | ||
personalizationDict.requiredPersonalizationInfo.postalCode) | ||
|
||
let personalizationQuery = try await UserPersonalization.query(on: app.db).all() | ||
#expect(personalizationQuery.count == 1) | ||
let passPersonalizationID = try await Pass.query(on: app.db).first()?._$userPersonalization.get(on: app.db)?.requireID() | ||
#expect(personalizationQuery[0]._$id.value == passPersonalizationID) | ||
#expect(personalizationQuery[0]._$emailAddress.value == personalizationDict.requiredPersonalizationInfo.emailAddress) | ||
#expect(personalizationQuery[0]._$familyName.value == personalizationDict.requiredPersonalizationInfo.familyName) | ||
#expect(personalizationQuery[0]._$fullName.value == personalizationDict.requiredPersonalizationInfo.fullName) | ||
#expect(personalizationQuery[0]._$givenName.value == personalizationDict.requiredPersonalizationInfo.givenName) | ||
#expect(personalizationQuery[0]._$isoCountryCode.value == personalizationDict.requiredPersonalizationInfo.isoCountryCode) | ||
#expect(personalizationQuery[0]._$phoneNumber.value == personalizationDict.requiredPersonalizationInfo.phoneNumber) | ||
#expect(personalizationQuery[0]._$postalCode.value == personalizationDict.requiredPersonalizationInfo.postalCode) | ||
} | ||
} | ||
|
||
func testAPNSClient() async throws { | ||
XCTAssertNotNil(app.apns.client(.init(string: "passes"))) | ||
|
||
let passData = PassData(title: "Test Pass") | ||
try await passData.create(on: app.db) | ||
let pass = try await passData._$pass.get(on: app.db) | ||
|
||
try await passesService.sendPushNotificationsForPass( | ||
id: pass.requireID(), of: pass.passTypeIdentifier, on: app.db) | ||
|
||
let deviceLibraryIdentifier = "abcdefg" | ||
let pushToken = "1234567890" | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)push/\(pass.passTypeIdentifier)/\(pass.requireID())", | ||
headers: ["X-Secret": "foo"], | ||
afterResponse: { res async throws in | ||
XCTAssertEqual(res.status, .noContent) | ||
} | ||
) | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)devices/\(deviceLibraryIdentifier)/registrations/\(pass.passTypeIdentifier)/\(pass.requireID())", | ||
headers: ["Authorization": "ApplePass \(pass.authenticationToken)"], | ||
beforeRequest: { req async throws in | ||
try req.content.encode(RegistrationDTO(pushToken: pushToken)) | ||
}, | ||
afterResponse: { res async throws in | ||
XCTAssertEqual(res.status, .created) | ||
} | ||
) | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)push/\(pass.passTypeIdentifier)/\(pass.requireID())", | ||
headers: ["X-Secret": "foo"], | ||
afterResponse: { res async throws in | ||
XCTAssertEqual(res.status, .internalServerError) | ||
} | ||
) | ||
|
||
// Test `PassDataMiddleware` update method | ||
passData.title = "Test Pass 2" | ||
do { | ||
try await passData.update(on: app.db) | ||
} catch {} | ||
@Test func apnsClient() async throws { | ||
try await withApp(delegate: delegate) { app, passesService in | ||
#expect(app.apns.client(.init(string: "passes")) != nil) | ||
|
||
let passData = PassData(title: "Test Pass") | ||
try await passData.create(on: app.db) | ||
let pass = try await passData._$pass.get(on: app.db) | ||
|
||
try await passesService.sendPushNotificationsForPass(id: pass.requireID(), of: pass.passTypeIdentifier, on: app.db) | ||
|
||
let deviceLibraryIdentifier = "abcdefg" | ||
let pushToken = "1234567890" | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)push/\(pass.passTypeIdentifier)/\(pass.requireID())", | ||
headers: ["X-Secret": "foo"], | ||
afterResponse: { res async throws in | ||
#expect(res.status == .noContent) | ||
} | ||
) | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)devices/\(deviceLibraryIdentifier)/registrations/\(pass.passTypeIdentifier)/\(pass.requireID())", | ||
headers: ["Authorization": "ApplePass \(pass.authenticationToken)"], | ||
beforeRequest: { req async throws in | ||
try req.content.encode(RegistrationDTO(pushToken: pushToken)) | ||
}, | ||
afterResponse: { res async throws in | ||
#expect(res.status == .created) | ||
} | ||
) | ||
|
||
try await app.test( | ||
.POST, | ||
"\(passesURI)push/\(pass.passTypeIdentifier)/\(pass.requireID())", | ||
headers: ["X-Secret": "foo"], | ||
afterResponse: { res async throws in | ||
#expect(res.status == .internalServerError) | ||
} | ||
) | ||
|
||
// Test `PassDataMiddleware` update method | ||
passData.title = "Test Pass 2" | ||
do { | ||
try await passData.update(on: app.db) | ||
} catch {} | ||
} | ||
} | ||
} |
Oops, something went wrong.