-
Notifications
You must be signed in to change notification settings - Fork 194
/
AttachmentDTO_Tests.swift
321 lines (259 loc) 路 13 KB
/
AttachmentDTO_Tests.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
//
// Copyright 漏 2021 Stream.io Inc. All rights reserved.
//
@testable import StreamChat
@testable import StreamChatTestTools
import XCTest
class AttachmentDTO_Tests: XCTestCase {
var database: DatabaseContainer!
override func setUp() {
super.setUp()
database = DatabaseContainerMock()
}
override func tearDown() {
AssertAsync.canBeReleased(&database)
super.tearDown()
}
func test_attachmentPayload_isStoredAndLoadedFromDB() throws {
let cid: ChannelId = .unique
let messageId: MessageId = .unique
let attachment: MessageAttachmentPayload = .dummy()
let attachmentId = AttachmentId(cid: cid, messageId: messageId, index: 0)
// Create channel, message and attachment in the database.
try database.createChannel(cid: cid, withMessages: false)
try database.createMessage(id: messageId, cid: cid)
try database.writeSynchronously { session in
try session.saveAttachment(payload: attachment, id: attachmentId)
}
// Load the attachment from the database.
let loadedAttachment = try XCTUnwrap(database.viewContext.attachment(id: attachmentId))
// Assert attachment has correct values.
XCTAssertEqual(loadedAttachment.attachmentID, attachmentId)
XCTAssertEqual(loadedAttachment.localState, .unknown)
XCTAssertEqual(loadedAttachment.attachmentType, attachment.type)
XCTAssertEqual(loadedAttachment.message.id, messageId)
XCTAssertEqual(loadedAttachment.channel.cid, cid.rawValue)
let imagePayload = attachment.decodedImagePayload
let imageAttachmentModel = try XCTUnwrap(
loadedAttachment
.asAnyModel()
.attachment(payloadType: ImageAttachmentPayload.self)
)
XCTAssertEqual(imageAttachmentModel.payload, imagePayload)
}
func test_giphyAttachmentWithActionsPayload_isStoredAndLoadedFromDB() throws {
let cid: ChannelId = .unique
let messageId: MessageId = .unique
let giphyWithActionsJSON = XCTestCase.mockData(fromFile: "AttachmentPayloadGiphyWithActions", extension: "json")
let attachment = try JSONDecoder.default.decode(MessageAttachmentPayload.self, from: giphyWithActionsJSON)
let attachmentId = AttachmentId(cid: cid, messageId: messageId, index: 0)
// Create channel, message and attachment in the database.
try database.createChannel(cid: cid, withMessages: false)
try database.createMessage(id: messageId, cid: cid)
try database.writeSynchronously { session in
try session.saveAttachment(payload: attachment, id: attachmentId)
}
// Load the attachment from the database.
let loadedAttachment = try XCTUnwrap(database.viewContext.attachment(id: attachmentId))
// Assert attachment has correct values.
XCTAssertEqual(loadedAttachment.attachmentID, attachmentId)
XCTAssertEqual(loadedAttachment.localState, .unknown)
XCTAssertEqual(loadedAttachment.attachmentType, attachment.type)
XCTAssertEqual(loadedAttachment.message.id, messageId)
XCTAssertEqual(loadedAttachment.channel.cid, cid.rawValue)
let giphyPayload = attachment.decodedGiphyPayload
let giphyAttachmentWithActionsPayload = try XCTUnwrap(
loadedAttachment
.asAnyModel()
.attachment(payloadType: GiphyAttachmentPayload.self)
)
XCTAssertEqual(giphyAttachmentWithActionsPayload.payload, giphyPayload)
}
func test_giphyAttachmentWithoutActionsPayload_isStoredAndLoadedFromDB() throws {
let cid: ChannelId = .unique
let messageId: MessageId = .unique
let giphyWithoutActionsJSON = XCTestCase.mockData(fromFile: "AttachmentPayloadGiphyWithoutActions", extension: "json")
let attachment = try JSONDecoder.default.decode(MessageAttachmentPayload.self, from: giphyWithoutActionsJSON)
let attachmentId = AttachmentId(cid: cid, messageId: messageId, index: 0)
// Create channel, message and attachment in the database.
try database.createChannel(cid: cid, withMessages: false)
try database.createMessage(id: messageId, cid: cid)
try database.writeSynchronously { session in
try session.saveAttachment(payload: attachment, id: attachmentId)
}
// Load the attachment from the database.
let loadedAttachment = try XCTUnwrap(database.viewContext.attachment(id: attachmentId))
// Assert attachment has correct values.
XCTAssertEqual(loadedAttachment.attachmentID, attachmentId)
XCTAssertEqual(loadedAttachment.localState, .unknown)
XCTAssertEqual(loadedAttachment.attachmentType, attachment.type)
XCTAssertEqual(loadedAttachment.message.id, messageId)
XCTAssertEqual(loadedAttachment.channel.cid, cid.rawValue)
let giphyPayload = attachment.decodedGiphyPayload
let giphyAttachmentWithoutActionsPayload = try XCTUnwrap(
loadedAttachment
.asAnyModel()
.attachment(payloadType: GiphyAttachmentPayload.self)
)
XCTAssertEqual(giphyAttachmentWithoutActionsPayload.payload, giphyPayload)
}
func test_uploadableAttachmentEnvelope_isStoredAndLoadedFromDB() throws {
let cid: ChannelId = .unique
let messageId: MessageId = .unique
let attachmentEnvelope: AnyAttachmentPayload = .mockFile
let attachmentId = AttachmentId(cid: cid, messageId: messageId, index: 0)
// Create channel and message in the database.
try database.createChannel(cid: cid, withMessages: false)
try database.createMessage(id: messageId, cid: cid)
// Create attachment with provided type in the database.
try database.writeSynchronously { session in
try session.createNewAttachment(attachment: attachmentEnvelope, id: attachmentId)
}
// Load the attachment from the database.
let loadedAttachment = try XCTUnwrap(database.viewContext.attachment(id: attachmentId))
// Assert attachment has correct values.
XCTAssertEqual(loadedAttachment.attachmentID, attachmentId)
XCTAssertEqual(loadedAttachment.localURL, attachmentEnvelope.localFileURL)
XCTAssertEqual(loadedAttachment.localState, .pendingUpload)
XCTAssertEqual(loadedAttachment.attachmentType, attachmentEnvelope.type)
XCTAssertEqual(loadedAttachment.message.id, messageId)
XCTAssertEqual(loadedAttachment.channel.cid, cid.rawValue)
let fileAttachment = try XCTUnwrap(
loadedAttachment
.asAnyModel()
.attachment(payloadType: FileAttachmentPayload.self)
)
XCTAssertEqual(
fileAttachment,
attachmentEnvelope.attachment(id: attachmentId)
)
}
func test_attachmentEnvelope_isStoredAndLoadedFromDB() throws {
let cid: ChannelId = .unique
let messageId: MessageId = .unique
let attachmentPayload: TestAttachmentPayload = .unique
let attachmentEnvelope = AnyAttachmentPayload(payload: attachmentPayload)
let attachmentId = AttachmentId(cid: cid, messageId: messageId, index: 0)
// Create channel and message in the database.
try database.createChannel(cid: cid, withMessages: false)
try database.createMessage(id: messageId, cid: cid)
// Create attachment with provided type in the database.
try database.writeSynchronously { session in
try session.createNewAttachment(attachment: attachmentEnvelope, id: attachmentId)
}
// Load the attachment from the database.
let loadedAttachment = try XCTUnwrap(database.viewContext.attachment(id: attachmentId))
// Assert attachment has correct values.
XCTAssertEqual(loadedAttachment.attachmentID, attachmentId)
XCTAssertEqual(loadedAttachment.localURL, nil)
XCTAssertEqual(loadedAttachment.localState, .uploaded)
XCTAssertEqual(loadedAttachment.attachmentType, attachmentEnvelope.type)
XCTAssertEqual(loadedAttachment.message.id, messageId)
XCTAssertEqual(loadedAttachment.channel.cid, cid.rawValue)
let attachmentModel = try XCTUnwrap(
loadedAttachment
.asAnyModel()
.attachment(payloadType: TestAttachmentPayload.self)
)
XCTAssertEqual(attachmentModel.id, attachmentId)
XCTAssertEqual(attachmentModel.type, attachmentEnvelope.type)
XCTAssertEqual(attachmentModel.payload, attachmentPayload)
XCTAssertNil(attachmentModel.uploadingState)
}
func test_saveAttachment_throws_whenChannelDoesNotExist() throws {
// Create message in DB
let messageId: MessageId = .unique
try database.createMessage(id: messageId)
let payload: MessageAttachmentPayload = .dummy()
// Try to save an attachment and catch an error
let error = try waitFor {
database.write({ session in
let id = AttachmentId(cid: .unique, messageId: messageId, index: 0)
try session.saveAttachment(payload: payload, id: id)
}, completion: $0)
}
// Assert correct error is thrown
XCTAssertTrue(error is ClientError.ChannelDoesNotExist)
}
func test_saveAttachment_throws_whenMessageDoesNotExist() throws {
// Create channel in DB
let cid: ChannelId = .unique
try database.createChannel(cid: cid, withMessages: false)
let payload: MessageAttachmentPayload = .dummy()
// Try to save an attachment and catch an error
let error = try waitFor {
database.write({ session in
let id = AttachmentId(cid: cid, messageId: .unique, index: 0)
try session.saveAttachment(payload: payload, id: id)
}, completion: $0)
}
// Assert correct error is thrown
XCTAssertTrue(error is ClientError.MessageDoesNotExist)
}
func test_saveAttachment_resetsLocalState() throws {
let cid: ChannelId = .unique
let messageId: MessageId = .unique
let attachmentId = AttachmentId(cid: cid, messageId: messageId, index: 0)
let attachmentEnvelope = AnyAttachmentPayload.mockFile
// Create channel in the database.
try database.createChannel(cid: cid, withMessages: false)
// Create message in the database.
try database.createMessage(id: messageId, cid: cid)
// Seed message attachment.
try database.writeSynchronously { session in
try session.createNewAttachment(attachment: attachmentEnvelope, id: attachmentId)
}
// Load the attachment from the database.
var loadedAttachment: AttachmentDTO? {
database.viewContext.attachment(id: attachmentId)
}
// Assert attachment has valid local URL.
XCTAssertEqual(loadedAttachment?.localURL, attachmentEnvelope.localFileURL)
// Save attachment payload with the same id.
let attachmentPayload: MessageAttachmentPayload = .dummy()
try database.writeSynchronously { session in
try session.saveAttachment(payload: attachmentPayload, id: attachmentId)
}
// Assert attachment local file URL and state are nil.
XCTAssertNil(loadedAttachment?.localURL)
XCTAssertEqual(loadedAttachment?.localState, .unknown)
}
func test_attachmentChange_triggerMessageUpdate() throws {
// Arrange: Store message with attachment in database
var messageId: MessageId!
var attachmentId: AttachmentId!
let cid: ChannelId = .unique
try! database.createCurrentUser()
try! database.createChannel(cid: cid)
try database.writeSynchronously { session in
let message = try session.createNewMessage(
in: cid,
text: "Message pending send",
pinning: nil,
quotedMessageId: nil,
isSilent: false,
attachments: [.init(payload: TestAttachmentPayload.unique)],
extraData: [:]
)
message.localMessageState = .pendingSend
attachmentId = message.attachments.first!.attachmentID
messageId = message.id
}
// Arrange: Observe changes on message
let observer = EntityDatabaseObserver<MessageDTO, MessageDTO>(
context: database.viewContext,
fetchRequest: MessageDTO.message(withID: messageId),
itemCreator: { $0 }
)
try observer.startObserving()
var receivedChange: EntityChange<MessageDTO>?
observer.onChange { receivedChange = $0 }
// Act: Update attachment
try database.writeSynchronously { session in
let attachment = try XCTUnwrap(session.attachment(id: attachmentId))
attachment.localState = .uploadingFailed
}
// Assert: Members should be updated
XCTAssertNotNil(receivedChange)
}
}