= { result in
32 | if case .failure(let clientError) = result, case .unknownError = clientError {
33 | test.fulfill()
34 | }
35 | }
36 |
37 | ClientCompletionResult.failure(ClientError.unknownError("", nil)).parse(queue, completion)
38 | }
39 | }
40 |
41 | func testRemovedErrors() {
42 | let response = Response(statusCode: 200, data: Data())
43 | let responseResult: ClientCompletionResult = .success(response)
44 |
45 | expect("error json decode") { test in
46 | responseResult.parseRemoved(queue) { result in
47 | if case .failure(let clientError) = result, case .jsonDecode = clientError {
48 | test.fulfill()
49 | }
50 | }
51 | }
52 |
53 | expect("error result") { test in
54 | ClientCompletionResult.failure(ClientError.unknownError("", nil)).parseRemoved(queue) { result in
55 | if case .failure(let clientError) = result, case .unknownError = clientError {
56 | test.fulfill()
57 | }
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Tests/Core/CollectionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 24/12/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | final class Food: CollectionObject {
13 | private enum CodingKeys: String, CodingKey {
14 | case name
15 | }
16 |
17 | var name: String
18 |
19 | init(name: String, id: String? = nil) {
20 | self.name = name
21 | super.init(collectionName: "food", id: id)
22 | }
23 |
24 | required init(from decoder: Decoder) throws {
25 | let dataContainer = try decoder.container(keyedBy: DataCodingKeys.self)
26 | let container = try dataContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
27 | name = try container.decode(String.self, forKey: .name)
28 | try super.init(from: decoder)
29 | }
30 |
31 | required init(collectionName: String, id: String? = nil) {
32 | name = ""
33 | super.init(collectionName: collectionName, id: id)
34 | }
35 |
36 | override func encode(to encoder: Encoder) throws {
37 | var dataContainer = encoder.container(keyedBy: DataCodingKeys.self)
38 | var container = dataContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
39 | try container.encode(name, forKey: .name)
40 | try super.encode(to: encoder)
41 | }
42 | }
43 |
44 | class CollectionTests: TestCase {
45 |
46 | func testAdd() {
47 | let burger = Food(name: "Burger", id: "123")
48 | XCTAssertEqual(burger.referenceId, "SO:food:123")
49 |
50 | expect("add collection object") { test in
51 | Client.shared.add(collectionObject: burger) { result in
52 | if let addedBurger = try? result.get() {
53 | XCTAssertEqual(addedBurger.collectionName, "food")
54 | XCTAssertEqual(addedBurger.foreignId, "food:123")
55 | XCTAssertEqual(addedBurger.name, "Burger")
56 | } else {
57 | XCTFail("Add collection object: \(result)")
58 | }
59 |
60 | test.fulfill()
61 | }
62 | }
63 | }
64 |
65 | func testGet() {
66 | expect("get collection object") { test in
67 | Client.shared.get(typeOf: Food.self, collectionName: "test", collectionObjectId: "obj") { result in
68 | let burger = try! result.get()
69 | XCTAssertEqual(burger.id, "123")
70 | XCTAssertEqual(burger.collectionName, "food")
71 | XCTAssertEqual(burger.name, "Burger")
72 | test.fulfill()
73 | }
74 | }
75 | }
76 |
77 | func testUpdate() {
78 | let burger = Food(name: "Burger2", id: "123")
79 |
80 | expect("update collection object") { test in
81 | Client.shared.update(collectionObject: burger) { result in
82 | let addedBurger = try! result.get()
83 | XCTAssertEqual(addedBurger.name, "Burger2")
84 | test.fulfill()
85 | }
86 | }
87 | }
88 |
89 | func testDelete() {
90 | expect("bad delete collection object") { test in
91 | let burger = Food(name: "Burger")
92 | XCTAssertEqual(burger.referenceId, "SO:food")
93 | Client.shared.delete(collectionObject: burger) { result in
94 | if case .failure(let error) = result, case .jsonInvalid = error {
95 | test.fulfill()
96 | }
97 | }
98 | }
99 |
100 | expect("delete collection object") { test in
101 | let burger = Food(name: "Burger", id: "123")
102 |
103 | Client.shared.delete(collectionObject: burger) { result in
104 | let status = try! result.get()
105 | XCTAssertEqual(status, 200)
106 | test.fulfill()
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/Tests/Core/ExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionsTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 20/11/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | import Moya
11 | @testable import GetStream
12 |
13 | final class ExtensionsTests: XCTestCase {
14 | let decoder = JSONDecoder.default
15 | let encoder = JSONEncoder.default
16 |
17 | let defaultData = """
18 | {
19 | "actor":"eric",
20 | "foreign_id":"1E42DEB6-7C2F-4DA9-B6E6-0C6E5CC9815D",
21 | "id":"9b5b3540-e825-11e8-8080-800016ff21e4",
22 | "object":"Hello world 3",
23 | "origin":null,
24 | "target":"",
25 | "time":"2018-11-14T15:54:45.268000",
26 | "to":["timeline:jessica"],
27 | "verb":"tweet"
28 | }
29 | """.data(using: .utf8)!
30 |
31 | let iso8601Data = """
32 | {
33 | "actor":"eric",
34 | "foreign_id":"1E42DEB6-7C2F-4DA9-B6E6-0C6E5CC9815D",
35 | "id":"9b5b3540-e825-11e8-8080-800016ff21e4",
36 | "object":"Hello world 3",
37 | "origin":null,
38 | "target":"",
39 | "time":"2018-11-14T15:54:45.268000Z",
40 | "to":["timeline:jessica"],
41 | "verb":"tweet"
42 | }
43 | """.data(using: .utf8)!
44 |
45 | let badDefaultData = """
46 | {
47 | "actor":"eric",
48 | "foreign_id":"1E42DEB6-7C2F-4DA9-B6E6-0C6E5CC9815D",
49 | "id":"9b5b3540-e825-11e8-8080-800016ff21e4",
50 | "object":"Hello world 3",
51 | "origin":null,
52 | "target":"",
53 | "time":"2018-11-14",
54 | "to":["timeline:jessica"],
55 | "verb":"tweet"
56 | }
57 | """.data(using: .utf8)!
58 |
59 | // MARK: - Codable
60 |
61 | func testCodable() throws {
62 | let activity = try decoder.decode(SimpleActivity.self, from: defaultData)
63 | XCTAssertEqual(activity.actor, "eric")
64 | XCTAssertEqual(activity.time!, "2018-11-14T15:54:45.268000".streamDate!)
65 | let encodedData = try encoder.encode(activity)
66 | XCTAssertTrue(String(data: encodedData, encoding: .utf8)!.contains("2018-11-14T15:54:45.268"))
67 | }
68 |
69 | func testCodableInvalidData() {
70 | do {
71 | _ = try decoder.decode(SimpleActivity.self, from: badDefaultData)
72 | XCTFail("❌ Empty json data check")
73 |
74 | } catch let error as DecodingError {
75 | if case .dataCorrupted(let context) = error {
76 | XCTAssertEqual(context.debugDescription, "Invalid date: 2018-11-14")
77 | } else {
78 | XCTFail("❌")
79 | }
80 | } catch {
81 | XCTFail("❌")
82 | }
83 | }
84 |
85 | func testAnyCodable() throws {
86 | struct Test: Encodable {
87 | let value: String
88 | }
89 |
90 | let anyEncodable = AnyEncodable(Test(value: "test"))
91 | let jsonData = try encoder.encode(anyEncodable)
92 | XCTAssertEqual(String(data: jsonData, encoding: .utf8)!, "{\"value\":\"test\"}")
93 | }
94 |
95 | // MARK: - Test Date Formatter
96 |
97 | func testISO8601Codable() throws {
98 | let activity = try decoder.decode(SimpleActivity.self, from: iso8601Data)
99 | XCTAssertEqual(activity.actor, "eric")
100 | XCTAssertEqual(activity.time!, "2018-11-14T15:54:45.268000".streamDate!)
101 | }
102 |
103 | func testDateExtension() {
104 | let date = Date()
105 | let streamString = date.stream
106 | let streamDate = streamString.streamDate!
107 | XCTAssertEqual(streamDate, streamDate.stream.streamDate!)
108 |
109 | let formatter = DateFormatter()
110 | formatter.dateStyle = .full
111 | formatter.timeStyle = .full
112 | XCTAssertEqual(formatter.string(from: date), formatter.string(from: streamDate))
113 | }
114 |
115 | func testStreamTargetType() {
116 | struct Test: StreamTargetType {
117 | var path: String = ""
118 | var method: Moya.Method = Moya.Method.get
119 | var task: Task = .requestPlain
120 | }
121 |
122 | let test = Test()
123 |
124 | XCTAssertEqual(test.baseURL, URL(string: "https://getstream.io")!)
125 | XCTAssertEqual(test.headers?["X-Stream-Client"]!, "stream-swift-client-\(Client.version)")
126 | XCTAssertEqual(test.sampleData, Data())
127 | }
128 |
129 | func testSimpleCancellable() {
130 | let cancellable = SimpleCancellable()
131 | XCTAssertFalse(cancellable.isCancelled)
132 | cancellable.cancel()
133 | XCTAssertTrue(cancellable.isCancelled)
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Tests/Core/FilesTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FilesTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 24/12/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | class FilesTests: TestCase {
13 |
14 | let data = Data(base64Encoded: "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==")!
15 |
16 | lazy var image = Image(data: data)!
17 |
18 | func testUpload() {
19 | expect("upload file") { test in
20 | let file = File(name: "test", data: data)
21 | Client.shared.upload(file: file) {
22 | XCTAssertEqual(try! $0.get(), URL(string: "http://uploaded.getstream.io/test")!)
23 | test.fulfill()
24 | }
25 | }
26 | }
27 |
28 | func testDelete() {
29 | expect("delete file") { test in
30 | Client.shared.delete(fileURL: URL(string: "http://uploaded.getstream.io/test")!) {
31 | XCTAssertEqual(try! $0.get(), 200)
32 | test.fulfill()
33 | }
34 | }
35 |
36 | expect("delete image") { test in
37 | Client.shared.delete(imageURL: URL(string: "http://images.getstream.io/test")!) {
38 | XCTAssertEqual(try! $0.get(), 200)
39 | test.fulfill()
40 | }
41 | }
42 | }
43 |
44 | func testUploadImage() {
45 | expect("upload image") { test in
46 | let file = File(name: "jpg", jpegImage: image)!
47 | Client.shared.upload(image: file) {
48 | XCTAssertEqual(try! $0.get(), URL(string: "http://images.getstream.io/jpg")!)
49 |
50 | let file = File(name: "png", pngImage: self.image)!
51 | Client.shared.upload(image: file) {
52 | XCTAssertEqual(try! $0.get(), URL(string: "http://images.getstream.io/png")!)
53 | test.fulfill()
54 | }
55 | }
56 | }
57 | }
58 |
59 | func testImageProcess() {
60 | expect("process image") { test in
61 | let process = ImageProcess(url: URL(string: "http://images.getstream.io/jpg")!, width: 100, height: 100)
62 |
63 | Client.shared.resizeImage(imageProcess: process, completion: {
64 | XCTAssertEqual(try! $0.get(), URL(string: "http://images.getstream.io/jpg?crop=center&h=100&w=100&resize=clip&url=http://images.getstream.io/jpg")!)
65 | test.fulfill()
66 | })
67 | }
68 |
69 | expect("bad process image") { test in
70 | let process = ImageProcess(url: URL(string: "http://images.getstream.io/jpg")!, width: 1, height: 0)
71 |
72 | Client.shared.resizeImage(imageProcess: process, completion: {
73 | if case .failure(let clientError) = $0, case .parameterInvalid = clientError {
74 | test.fulfill()
75 | }
76 | })
77 | }
78 |
79 | expect("bad process image") { test in
80 | let process = ImageProcess(url: URL(string: "http://images.getstream.io/jpg")!, width: 0, height: 1)
81 |
82 | Client.shared.resizeImage(imageProcess: process, completion: {
83 | if case .failure(let clientError) = $0, case .parameterInvalid = clientError {
84 | test.fulfill()
85 | }
86 | })
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Tests/Core/NotificationFeedTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationFeedTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 24/12/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | class NotificationFeedTests: TestCase {
13 | lazy var notificationsFeed = Client.shared.notificationFeed(feedSlug: "notifications")
14 |
15 | func testNotioficationsFeed() {
16 | expect("get notifications") { test in
17 | notificationsFeed?.get(typeOf: SimpleActivity.self) { result in
18 | let notifications = try! result.get()
19 |
20 | XCTAssertEqual(notifications.results.count, 1)
21 | XCTAssertEqual(notifications.results.first!.isSeen, true)
22 | XCTAssertEqual(notifications.results.first!.isRead, false)
23 | XCTAssertEqual(notifications.results.first!.activitiesCount, 6)
24 | XCTAssertEqual(notifications.results.first!.activities.count, 6)
25 | XCTAssertEqual(notifications.results.first!.verb, "test")
26 | XCTAssertTrue(notifications.results.first!.group.hasPrefix("test_"))
27 | XCTAssertEqual(notifications.results.first!.activities.first!.verb, "test")
28 |
29 | test.fulfill()
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/Core/OGTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OGTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 24/12/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | class OGTests: TestCase {
13 |
14 | func testOG() {
15 | expect("get OpenGraph data") { test in
16 | let url = URL(string: "http://www.imdb.com/title/tt2084970/")!
17 | Client.shared.og(url: url) {
18 | let data = try! $0.get()
19 | XCTAssertEqual(data.title, "The Imitation Game (2014)")
20 | XCTAssertEqual(data.url, url)
21 | XCTAssertEqual(data.siteName, "IMDb")
22 | XCTAssertEqual(data.images!.count, 1)
23 | XCTAssertEqual(data.images!.first!.image,
24 | "https://m.media-amazon.com/images/M/MV5BOTgwMzFiMWYtZDhlNS00ODNkLWJiODAtZDVhNzgyNzJhYjQ4L2ltYWdlXkEyXkFqcGdeQXVyNzEzOTYxNTQ@._V1_UY1200_CR87,0,630,1200_AL_.jpg")
25 | test.fulfill()
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Tests/Core/ReactionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReactionTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 27/12/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | class ReactionTests: TestCase {
13 |
14 | func testAdd() {
15 | Client.shared.add(reactionTo: .test1, kindOf: .comment, extraData: Comment(text: "Hello!"), userTypeOf: User.self) {
16 | let commentReaction = try! $0.get()
17 | XCTAssertEqual(commentReaction.kind, .comment)
18 | XCTAssertEqual(commentReaction.data.text, "Hello!")
19 |
20 | Client.shared.add(reactionTo: .test1, parentReactionId: commentReaction.parentId, kindOf: .like) {
21 | let likeReaction = try! $0.get()
22 | XCTAssertEqual(likeReaction.kind, .like)
23 | XCTAssertEqual(likeReaction.parentId, commentReaction.id)
24 | }
25 |
26 | Client.shared.add(reactionToParentReaction: commentReaction, kindOf: .like, userTypeOf: User.self) {
27 | let likeReaction = try! $0.get()
28 | XCTAssertEqual(likeReaction.kind, .like)
29 | XCTAssertEqual(likeReaction.parentId, commentReaction.id)
30 | }
31 | }
32 | }
33 |
34 | func testGet() {
35 | Client.shared.get(reactionId: .test1) {
36 | let reaction = try! $0.get()
37 | XCTAssertEqual(reaction.kind, .like)
38 | XCTAssertEqual(reaction.data, EmptyReactionExtraData.shared)
39 | }
40 |
41 | Client.shared.get(reactionId: .test2, extraDataTypeOf: Comment.self, userTypeOf: User.self) {
42 | let reaction = try! $0.get()
43 | XCTAssertEqual(reaction.kind, .comment)
44 | XCTAssertEqual(reaction.data.text, "Hello!")
45 | }
46 |
47 | Client.shared.get(reactionId: .test2) {
48 | let reaction = try! $0.get()
49 | XCTAssertEqual(reaction.kind, .comment)
50 | XCTAssertEqual(reaction.data, EmptyReactionExtraData.shared)
51 | }
52 | }
53 |
54 | func testUpdate() {
55 | Client.shared.update(reactionId: .test2, extraData: ReactionExtraData.comment("Hi!"), userTypeOf: User.self) {
56 | let reaction = try! $0.get()
57 | XCTAssertEqual(reaction.kind, .comment)
58 |
59 |
60 | if case .comment(let text) = reaction.data {
61 | XCTAssertEqual(text, "Hi!")
62 | }
63 |
64 | if let lastLike = reaction.latestChildren[.like]?.first {
65 | XCTAssertEqual(lastLike.kind, .like)
66 | }
67 |
68 | if let lastComment = reaction.latestChildren[.comment]?.first {
69 | XCTAssertEqual(lastComment.kind, .comment)
70 |
71 | if case .comment(let text) = lastComment.data {
72 | XCTAssertEqual(text, "Hey!")
73 | }
74 | }
75 | }
76 | }
77 |
78 | func testDelete() {
79 | Client.shared.delete(reactionId: .test1) {
80 | XCTAssertEqual(try! $0.get(), 200)
81 | }
82 | }
83 |
84 | func testFetchReactions() {
85 | Client.shared.reactions(forUserId: "1") {
86 | let reactions = try! $0.get()
87 | XCTAssertEqual(reactions.reactions.count, 3)
88 | }
89 |
90 | Client.shared.reactions(forUserId: "1", kindOf: .comment, extraDataTypeOf: ReactionExtraData.self, userTypeOf: User.self) {
91 | let reactions = try! $0.get()
92 | XCTAssertEqual(reactions.reactions.count, 2)
93 |
94 | if case .comment(let text) = reactions.reactions[0].data {
95 | XCTAssertEqual(text, "Hey!")
96 | }
97 |
98 | if case .comment(let text) = reactions.reactions[1].data {
99 | XCTAssertEqual(text, "Hi!")
100 | }
101 | }
102 |
103 | Client.shared.reactions(forReactionId: "50539e71-d6bf-422d-ad21-c8717df0c325") {
104 | let reactions = try! $0.get()
105 | XCTAssertEqual(reactions.reactions.count, 2)
106 | }
107 |
108 | Client.shared.reactions(forActivityId: "ce918867-0520-11e9-a11e-0a286b200b2e", withActivityData: true) {
109 | let reactions = try! $0.get()
110 | XCTAssertEqual(reactions.reactions.count, 3)
111 | XCTAssertNotNil(try? reactions.activity(typeOf: SimpleActivity.self))
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/Tests/Core/UserTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 27/12/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | final class CustomUser: User {
13 | private enum CodingKeys: String, CodingKey {
14 | case name
15 | }
16 |
17 | var name: String
18 |
19 | init(id: String, name: String) {
20 | self.name = name
21 | super.init(id: id)
22 | }
23 |
24 | required init(from decoder: Decoder) throws {
25 | let dataContainer = try decoder.container(keyedBy: DataCodingKeys.self)
26 | let container = try dataContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
27 | name = try container.decode(String.self, forKey: .name)
28 | try super.init(from: decoder)
29 | }
30 |
31 | required init(id: String) {
32 | name = ""
33 | super.init(id: id)
34 | }
35 |
36 | override func encode(to encoder: Encoder) throws {
37 | var dataContainer = encoder.container(keyedBy: DataCodingKeys.self)
38 | var container = dataContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
39 | try container.encode(name, forKey: .name)
40 | try super.encode(to: encoder)
41 | }
42 | }
43 |
44 | class UserTests: TestCase {
45 | func testCreate() {
46 | let user = CustomUser(id: "eric", name: "Eric")
47 |
48 | expect("create user") { test in
49 | Client.shared.create(user: user) {
50 | print($0)
51 | let created = try! $0.get()
52 | XCTAssertEqual(created.name, user.name)
53 |
54 | Client.shared.get(typeOf: CustomUser.self, userId: user.id) {
55 | let loaded = try! $0.get()
56 | XCTAssertEqual(loaded.name, user.name)
57 | loaded.name = "Eric Updated"
58 | XCTAssertNotEqual(loaded.name, user.name)
59 |
60 | Client.shared.update(user: loaded) {
61 | let updated = try! $0.get()
62 | XCTAssertEqual(updated.name, loaded.name)
63 |
64 | Client.shared.delete(userId: updated.id) {
65 | XCTAssertEqual(try! $0.get(), 200)
66 | test.fulfill()
67 | }
68 | }
69 | }
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Tests/Extensions/String+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Extensions.swift
3 | // GetStream
4 | //
5 | // Created by Alexey Bukhtin on 21/11/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | extension String {
12 | static let test1 = "00000000-0000-0000-0000-000000000001"
13 | static let test2 = "00000000-0000-0000-0000-000000000002"
14 | }
15 |
--------------------------------------------------------------------------------
/Tests/Extensions/TestCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestCase.swift
3 | // GetStream
4 | //
5 | // Created by Alexey Bukhtin on 21/11/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import GetStream
11 |
12 | class TestCase: XCTestCase {
13 |
14 | override class func setUp() {
15 | let provider = NetworkProvider(stubClosure: NetworkProvider.immediatelyStub)
16 | Client.config = .init(apiKey: "apiKey", appId: "appId", networkProvider: provider)
17 |
18 | if User.current == nil {
19 | setupUser(token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZXJpYyJ9.20YPOjP1-HtwKH7SH3k5CgLLLrhLCLaKDnb8XuiU7oA")
20 | }
21 | }
22 |
23 | class func setupUser(token: Token, shouldFail: Bool = false) {
24 | Client.shared.setupUser(token: token) { result in
25 | if let user = try? result.get(), Client.shared.currentUserId == user.id {
26 | if shouldFail {
27 | XCTFail("User setup should fail, but got user: \(user)")
28 | } else {
29 | XCTAssertEqual(user.id, Client.shared.currentUserId ?? "unwrapped")
30 | }
31 | } else if let error = result.error {
32 | if !shouldFail {
33 | XCTFail("User setup failed with error: \(error)")
34 | }
35 | } else if !shouldFail {
36 | XCTFail("User setup failed: \(result)")
37 | }
38 | }
39 | }
40 |
41 | func expect(_ description: String, timeout: TimeInterval = TimeInterval(1), callback: (_ test: XCTestExpectation) -> Void) {
42 | let test = expectation(description: "⏳ expecting \(description)")
43 | callback(test)
44 | wait(for: [test], timeout: timeout)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Tests/Faye/FayeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FayeTests.swift
3 | // FayeTests
4 | //
5 | // Created by Alexey Bukhtin on 26/11/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class FayeTests: TestCase {
12 |
13 | func testExample() {
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Tests/Token/TokenTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TokenTests.swift
3 | // GetStream-iOS Tests
4 | //
5 | // Created by Alexey Bukhtin on 22/11/2018.
6 | // Copyright © 2018 Stream.io Inc. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | import JWT
11 | @testable import GetStream
12 |
13 | class TokenTests: XCTestCase {
14 |
15 | func testGenerator() {
16 | let secretData = "xwnkc2rdvm7bp7gn8ddzc6ngbgvskahf6v3su7qj5gp6utyu8rtek8k2vq2ssaav".data(using: .utf8)!
17 | let token = Token(secretData: secretData)
18 | let jwtClaims: ClaimSet = try! JWT.decode(token, algorithm: .hs256(secretData))
19 | XCTAssertEqual(jwtClaims["resource"] as! String, Token.Resource.all.rawValue)
20 | XCTAssertEqual(jwtClaims["action"] as! String, Token.Permission.all.rawValue)
21 | XCTAssertEqual(jwtClaims["feed_id"] as! String, FeedId.any.description)
22 | }
23 |
24 | func testUserGenerator() {
25 | let secretData = "xwnkc2rdvm7bp7gn8ddzc6ngbgvskahf6v3su7qj5gp6utyu8rtek8k2vq2ssaav".data(using: .utf8)!
26 | let token = Token(secretData: secretData, userId: "eric")
27 | let jwtClaims: ClaimSet = try! JWT.decode(token, algorithm: .hs256(secretData))
28 | XCTAssertNil(jwtClaims["resource"])
29 | XCTAssertNil(jwtClaims["action"])
30 | XCTAssertNil(jwtClaims["feed_id"])
31 | XCTAssertEqual(jwtClaims["user_id"] as! String, "eric")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
--------------------------------------------------------------------------------
/docs/badge.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | com.jazzy.getstream
7 | CFBundleName
8 | GetStream
9 | DocSetPlatformFamily
10 | getstream
11 | isDashDocset
12 |
13 | dashIndexFilePath
14 | index.html
15 | isJavaScriptEnabled
16 |
17 | DashDocSetFamily
18 | dashtoc
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/badge.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/carat.png
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/dash.png
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/gh.png
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/docsets/GetStream.docset/Contents/Resources/Documents/img/spinner.gif
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | function toggleItem($link, $content) {
12 | var animationDuration = 300;
13 | $link.toggleClass('token-open');
14 | $content.slideToggle(animationDuration);
15 | }
16 |
17 | function itemLinkToContent($link) {
18 | return $link.parent().parent().next();
19 | }
20 |
21 | // On doc load + hash-change, open any targetted item
22 | function openCurrentItemIfClosed() {
23 | if (window.jazzy.docset) {
24 | return;
25 | }
26 | var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token');
27 | $content = itemLinkToContent($link);
28 | if ($content.is(':hidden')) {
29 | toggleItem($link, $content);
30 | }
31 | }
32 |
33 | $(openCurrentItemIfClosed);
34 | $(window).on('hashchange', openCurrentItemIfClosed);
35 |
36 | // On item link ('token') click, toggle its discussion
37 | $('.token').on('click', function(event) {
38 | if (window.jazzy.docset) {
39 | return;
40 | }
41 | var $link = $(this);
42 | toggleItem($link, itemLinkToContent($link));
43 |
44 | // Keeps the document from jumping to the hash.
45 | var href = $link.attr('href');
46 | if (history.pushState) {
47 | history.pushState({}, '', href);
48 | } else {
49 | location.hash = href;
50 | }
51 | event.preventDefault();
52 | });
53 |
54 | // Clicks on links to the current, closed, item need to open the item
55 | $("a:not('.token')").on('click', function() {
56 | if (location == this.href) {
57 | openCurrentItemIfClosed();
58 | }
59 | });
60 |
61 | // KaTeX rendering
62 | if ("katex" in window) {
63 | $($('.math').each( (_, element) => {
64 | katex.render(element.textContent, element, {
65 | displayMode: $(element).hasClass('m-block'),
66 | throwOnError: false,
67 | trust: true
68 | });
69 | }))
70 | }
71 |
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/Documents/js/jazzy.search.js:
--------------------------------------------------------------------------------
1 | $(function(){
2 | var $typeahead = $('[data-typeahead]');
3 | var $form = $typeahead.parents('form');
4 | var searchURL = $form.attr('action');
5 |
6 | function displayTemplate(result) {
7 | return result.name;
8 | }
9 |
10 | function suggestionTemplate(result) {
11 | var t = '';
12 | t += '' + result.name + '';
13 | if (result.parent_name) {
14 | t += '' + result.parent_name + '';
15 | }
16 | t += '
';
17 | return t;
18 | }
19 |
20 | $typeahead.one('focus', function() {
21 | $form.addClass('loading');
22 |
23 | $.getJSON(searchURL).then(function(searchData) {
24 | const searchIndex = lunr(function() {
25 | this.ref('url');
26 | this.field('name');
27 | this.field('abstract');
28 | for (const [url, doc] of Object.entries(searchData)) {
29 | this.add({url: url, name: doc.name, abstract: doc.abstract});
30 | }
31 | });
32 |
33 | $typeahead.typeahead(
34 | {
35 | highlight: true,
36 | minLength: 3,
37 | autoselect: true
38 | },
39 | {
40 | limit: 10,
41 | display: displayTemplate,
42 | templates: { suggestion: suggestionTemplate },
43 | source: function(query, sync) {
44 | const lcSearch = query.toLowerCase();
45 | const results = searchIndex.query(function(q) {
46 | q.term(lcSearch, { boost: 100 });
47 | q.term(lcSearch, {
48 | boost: 10,
49 | wildcard: lunr.Query.wildcard.TRAILING
50 | });
51 | }).map(function(result) {
52 | var doc = searchData[result.ref];
53 | doc.url = result.ref;
54 | return doc;
55 | });
56 | sync(results);
57 | }
58 | }
59 | );
60 | $form.removeClass('loading');
61 | $typeahead.trigger('focus');
62 | });
63 | });
64 |
65 | var baseURL = searchURL.slice(0, -"search.json".length);
66 |
67 | $typeahead.on('typeahead:select', function(e, result) {
68 | window.location = baseURL + result.url;
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/docs/docsets/GetStream.docset/Contents/Resources/docSet.dsidx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/docsets/GetStream.docset/Contents/Resources/docSet.dsidx
--------------------------------------------------------------------------------
/docs/docsets/GetStream.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/docsets/GetStream.tgz
--------------------------------------------------------------------------------
/docs/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/img/carat.png
--------------------------------------------------------------------------------
/docs/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/img/dash.png
--------------------------------------------------------------------------------
/docs/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/img/gh.png
--------------------------------------------------------------------------------
/docs/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/stream-swift/0785e68cbb3dda1092f65e2fc53d6eb91ba990a1/docs/img/spinner.gif
--------------------------------------------------------------------------------
/docs/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | function toggleItem($link, $content) {
12 | var animationDuration = 300;
13 | $link.toggleClass('token-open');
14 | $content.slideToggle(animationDuration);
15 | }
16 |
17 | function itemLinkToContent($link) {
18 | return $link.parent().parent().next();
19 | }
20 |
21 | // On doc load + hash-change, open any targetted item
22 | function openCurrentItemIfClosed() {
23 | if (window.jazzy.docset) {
24 | return;
25 | }
26 | var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token');
27 | $content = itemLinkToContent($link);
28 | if ($content.is(':hidden')) {
29 | toggleItem($link, $content);
30 | }
31 | }
32 |
33 | $(openCurrentItemIfClosed);
34 | $(window).on('hashchange', openCurrentItemIfClosed);
35 |
36 | // On item link ('token') click, toggle its discussion
37 | $('.token').on('click', function(event) {
38 | if (window.jazzy.docset) {
39 | return;
40 | }
41 | var $link = $(this);
42 | toggleItem($link, itemLinkToContent($link));
43 |
44 | // Keeps the document from jumping to the hash.
45 | var href = $link.attr('href');
46 | if (history.pushState) {
47 | history.pushState({}, '', href);
48 | } else {
49 | location.hash = href;
50 | }
51 | event.preventDefault();
52 | });
53 |
54 | // Clicks on links to the current, closed, item need to open the item
55 | $("a:not('.token')").on('click', function() {
56 | if (location == this.href) {
57 | openCurrentItemIfClosed();
58 | }
59 | });
60 |
61 | // KaTeX rendering
62 | if ("katex" in window) {
63 | $($('.math').each( (_, element) => {
64 | katex.render(element.textContent, element, {
65 | displayMode: $(element).hasClass('m-block'),
66 | throwOnError: false,
67 | trust: true
68 | });
69 | }))
70 | }
71 |
--------------------------------------------------------------------------------
/docs/js/jazzy.search.js:
--------------------------------------------------------------------------------
1 | $(function(){
2 | var $typeahead = $('[data-typeahead]');
3 | var $form = $typeahead.parents('form');
4 | var searchURL = $form.attr('action');
5 |
6 | function displayTemplate(result) {
7 | return result.name;
8 | }
9 |
10 | function suggestionTemplate(result) {
11 | var t = '';
12 | t += '' + result.name + '';
13 | if (result.parent_name) {
14 | t += '' + result.parent_name + '';
15 | }
16 | t += '
';
17 | return t;
18 | }
19 |
20 | $typeahead.one('focus', function() {
21 | $form.addClass('loading');
22 |
23 | $.getJSON(searchURL).then(function(searchData) {
24 | const searchIndex = lunr(function() {
25 | this.ref('url');
26 | this.field('name');
27 | this.field('abstract');
28 | for (const [url, doc] of Object.entries(searchData)) {
29 | this.add({url: url, name: doc.name, abstract: doc.abstract});
30 | }
31 | });
32 |
33 | $typeahead.typeahead(
34 | {
35 | highlight: true,
36 | minLength: 3,
37 | autoselect: true
38 | },
39 | {
40 | limit: 10,
41 | display: displayTemplate,
42 | templates: { suggestion: suggestionTemplate },
43 | source: function(query, sync) {
44 | const lcSearch = query.toLowerCase();
45 | const results = searchIndex.query(function(q) {
46 | q.term(lcSearch, { boost: 100 });
47 | q.term(lcSearch, {
48 | boost: 10,
49 | wildcard: lunr.Query.wildcard.TRAILING
50 | });
51 | }).map(function(result) {
52 | var doc = searchData[result.ref];
53 | doc.url = result.ref;
54 | return doc;
55 | });
56 | sync(results);
57 | }
58 | }
59 | );
60 | $form.removeClass('loading');
61 | $typeahead.trigger('focus');
62 | });
63 | });
64 |
65 | var baseURL = searchURL.slice(0, -"search.json".length);
66 |
67 | $typeahead.on('typeahead:select', function(e, result) {
68 | window.location = baseURL + result.url;
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # This file contains the fastlane.tools configuration
2 | # You can find the documentation at https://docs.fastlane.tools
3 | #
4 | # For a list of all available actions, check out
5 | #
6 | # https://docs.fastlane.tools/actions
7 | #
8 | # For a list of all available plugins, check out
9 | #
10 | # https://docs.fastlane.tools/plugins/available-plugins
11 | #
12 |
13 | # Uncomment the line if you want fastlane to automatically update itself
14 | update_fastlane
15 |
16 | carthage(use_binaries: false, platform: "iOS", cache_builds: true, new_resolver: true)
17 |
18 | default_platform(:ios)
19 |
20 | platform :ios do
21 | desc "Run all unit tests for GetStream"
22 | lane :tests do
23 | run_tests(scheme: "GetStream-iOS")
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/fastlane/README.md:
--------------------------------------------------------------------------------
1 | fastlane documentation
2 | ================
3 | # Installation
4 |
5 | Make sure you have the latest version of the Xcode command line tools installed:
6 |
7 | ```
8 | xcode-select --install
9 | ```
10 |
11 | Install _fastlane_ using
12 | ```
13 | [sudo] gem install fastlane -NV
14 | ```
15 | or alternatively using `brew cask install fastlane`
16 |
17 | # Available Actions
18 | ## iOS
19 | ### ios tests
20 | ```
21 | fastlane ios tests
22 | ```
23 | Run all unit tests for GetStream
24 |
25 | ----
26 |
27 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
28 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
29 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
30 |
--------------------------------------------------------------------------------