gitbayTests/PushTargetTests.swift

v1.14.1
gitbay-ios/gitbayTests/PushTargetTests.swift history · blame · raw

83 lines · 3701 bytes

 1import Foundation
 2import Testing
 3@testable import gitbay
 4
 5private func account(_ host: String, _ user: String) throws -> Account {
 6    Account(instance: try GitbayInstance(url: "https://\(host)"), username: user)
 7}
 8
 9private func payload(_ instance: String, _ user: String, _ path: String) throws -> PushPayload {
10    try #require(PushPayload(userInfo: [
11        "aps": ["alert": ["title": "t", "body": "b"]],
12        "instance": instance, "user": user, "path": path,
13    ]))
14}
15
16@Test func targetResolvesToTheMatchingAccount() throws {
17    let accounts = [try account("gitbay.org", "cmc"), try account("dev.local", "cmc")]
18    let target = try #require(PushTarget(
19        payload: try payload("https://dev.local", "cmc", "krz/gitbay/mrs/7"),
20        accounts: accounts))
21    #expect(target.accountID == accounts[1].id)
22    #expect(target.destination == .mr(repo: "krz/gitbay", number: 7))
23}
24
25// Same username on two instances is two accounts; the instance decides.
26@Test func targetDistinguishesTheSameUserOnTwoInstances() throws {
27    let accounts = [try account("gitbay.org", "cmc"), try account("dev.local", "cmc")]
28    let target = try #require(PushTarget(
29        payload: try payload("https://gitbay.org", "cmc", "a/b/issues/1"),
30        accounts: accounts))
31    #expect(target.accountID == accounts[0].id)
32}
33
34@Test func targetIsNilForAnAccountSignedOut() throws {
35    let accounts = [try account("gitbay.org", "cmc")]
36    #expect(PushTarget(payload: try payload("https://other.example", "cmc", "a/b/issues/1"),
37                       accounts: accounts) == nil)
38}
39
40// A repository root, or a section the app has no screen for, resolves
41// to no target: the tap opens the app without navigating.
42@Test func targetIsNilForAnUnroutablePath() throws {
43    let accounts = [try account("gitbay.org", "cmc")]
44    #expect(PushTarget(payload: try payload("https://gitbay.org", "cmc", "krz/gitbay"),
45                       accounts: accounts) == nil)
46    #expect(PushTarget(payload: try payload("https://gitbay.org", "cmc", "krz/gitbay/wiki/Home"),
47                       accounts: accounts) == nil)
48}
49
50// A server's unnormalised site_url must not desync a payload from the
51// account it belongs to: both sides go through GitbayInstance's own
52// normalisation before comparing.
53@Test func targetMatchesAnInstanceWithATrailingSlash() throws {
54    let accounts = [try account("gitbay.org", "cmc")]
55    let target = try #require(PushTarget(
56        payload: try payload("https://gitbay.org/", "cmc", "a/b/issues/1"),
57        accounts: accounts))
58    #expect(target.accountID == accounts[0].id)
59}
60
61@Test func targetMatchesAnInstanceWithAnExplicitDefaultPort() throws {
62    let accounts = [try account("gitbay.org", "cmc")]
63    let target = try #require(PushTarget(
64        payload: try payload("https://gitbay.org:443", "cmc", "a/b/issues/1"),
65        accounts: accounts))
66    #expect(target.accountID == accounts[0].id)
67}
68
69// The other side of the same mismatch: an account stored before the
70// constructor folded the default port keeps ":443" in its baseURL, so
71// decoding is the only way to build one. Its id keeps the port —
72// rewriting that would orphan the Keychain token keyed by it.
73@Test func targetMatchesAnAccountStoredWithAnExplicitDefaultPort() throws {
74    let legacy = try JSONDecoder().decode(
75        GitbayInstance.self, from: Data(#"{"baseURL":"https://gitbay.org:443"}"#.utf8))
76    let accounts = [Account(instance: legacy, username: "cmc")]
77    #expect(accounts[0].id.contains(":443"))
78
79    let target = try #require(PushTarget(
80        payload: try payload("https://gitbay.org", "cmc", "a/b/issues/1"),
81        accounts: accounts))
82    #expect(target.accountID == accounts[0].id)
83}