286 lines
14 KiB
Swift
286 lines
14 KiB
Swift
|
import XCTest
|
|||
|
import CoreData
|
|||
|
@testable import Wikipedia
|
|||
|
|
|||
|
class TalkPageLocalHandlerTests: XCTestCase {
|
|||
|
|
|||
|
let urlString1 = "https://en.wikipedia.org/api/rest_v1/page/talk/Username1"
|
|||
|
let urlString2 = "https://en.wikipedia.org/api/rest_v1/page/talk/Username2"
|
|||
|
let urlString3 = "https://es.wikipedia.org/api/rest_v1/page/talk/Username1"
|
|||
|
|
|||
|
var tempDataStore: MWKDataStore!
|
|||
|
var moc: NSManagedObjectContext!
|
|||
|
|
|||
|
override func setUp() {
|
|||
|
super.setUp()
|
|||
|
tempDataStore = MWKDataStore.temporary()
|
|||
|
moc = tempDataStore.viewContext
|
|||
|
}
|
|||
|
|
|||
|
override func tearDown() {
|
|||
|
tempDataStore.removeFolderAtBasePath()
|
|||
|
tempDataStore = nil
|
|||
|
super.tearDown()
|
|||
|
}
|
|||
|
|
|||
|
func testCreateFirstTalkPageSavesToDatabase() {
|
|||
|
|
|||
|
// confirm no talk pages in DB
|
|||
|
let fetchRequest: NSFetchRequest<TalkPage> = TalkPage.fetchRequest()
|
|||
|
|
|||
|
guard let firstResults = try? tempDataStore.viewContext.fetch(fetchRequest) else {
|
|||
|
XCTFail("Failure fetching initial talk pages")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(firstResults.count, 0, "Expected zero existing talk pages at first")
|
|||
|
|
|||
|
// add network talk page
|
|||
|
guard let json = wmf_bundle().wmf_data(fromContentsOfFile: TalkPageTestHelpers.TalkPageJSONType.original.fileName, ofType: "json"),
|
|||
|
let talkPage = TalkPageTestHelpers.networkTalkPage(for: urlString1, data: json, revisionId: 1) else {
|
|||
|
XCTFail("Failure stubbing out network talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// create db talk page
|
|||
|
guard let dbTalkPage = moc.createTalkPage(with: talkPage) else {
|
|||
|
XCTFail("Failure to create db talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// assert db talk page values
|
|||
|
let keyedUrlString = URL(string: urlString1)?.wmf_databaseKey
|
|||
|
XCTAssertNotNil(dbTalkPage.key)
|
|||
|
XCTAssertEqual(dbTalkPage.key, keyedUrlString, "Unexpected key")
|
|||
|
XCTAssertEqual(dbTalkPage.revisionId, 1, "Unexpected revisionId")
|
|||
|
XCTAssertEqual(dbTalkPage.topics?.count, 6, "Unexpected topic count")
|
|||
|
|
|||
|
let topics = dbTalkPage.topics?.allObjects.sorted { ($0 as! TalkPageTopic).sort < ($1 as! TalkPageTopic).sort }
|
|||
|
|
|||
|
if let introTopic = topics?[0] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(introTopic.title, "", "Unexpected topic title")
|
|||
|
XCTAssertEqual(introTopic.replies?.count, 1, "Unexpected replies count")
|
|||
|
let replies = introTopic.replies?.allObjects.sorted { ($0 as! TalkPageReply).sort < ($1 as! TalkPageReply).sort }
|
|||
|
if let firstReply = replies?[0] as? TalkPageReply {
|
|||
|
XCTAssertEqual(firstReply.text, "Hello! This is some introduction text on my talk page. L8erz, <a href='./User:TSevener_(WMF)' title='User:TSevener (WMF)'>TSevener (WMF)</a> (<a href='./User_talk:TSevener_(WMF)' title='User talk:TSevener (WMF)'>talk</a>) 20:48, 21 June 2019 (UTC)", "Unexpected replies html")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected first reply type")
|
|||
|
}
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected intro topic type")
|
|||
|
}
|
|||
|
|
|||
|
if let firstTopic = topics?[1] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(firstTopic.title, "Let’s talk about talk pages", "Unexpected topic title")
|
|||
|
XCTAssertEqual(firstTopic.replies?.count, 3, "Unexpected topic items count")
|
|||
|
|
|||
|
let replies = firstTopic.replies?.allObjects.sorted { ($0 as! TalkPageReply).sort < ($1 as! TalkPageReply).sort }
|
|||
|
if let firstReply = replies?[0] as? TalkPageReply {
|
|||
|
XCTAssertEqual(firstReply.text, "Hello, I am testing a new topic from the <a href='./IOS' title='IOS'>iOS</a> app. It is fun. <a href='./Special:Contributions/47.184.10.84' title='Special:Contributions/47.184.10.84'>47.184.10.84</a> 20:50, 21 June 2019 (UTC)")
|
|||
|
XCTAssertEqual(firstReply.depth, 0, "Unexpected reply depth")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected first reply type")
|
|||
|
}
|
|||
|
|
|||
|
if let secondReply = replies?[1] as? TalkPageReply {
|
|||
|
XCTAssertEqual(secondReply.text, "Hello back! This is a nested reply. <a href='./User:TSevener_(WMF)' title='User:TSevener (WMF)'>TSevener (WMF)</a> (<a href='./User_talk:TSevener_(WMF)' title='User talk:TSevener (WMF)'>talk</a>) 20:51, 21 June 2019 (UTC)")
|
|||
|
XCTAssertEqual(secondReply.depth, 1, "Unexpected reply depth")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected second reply type")
|
|||
|
}
|
|||
|
|
|||
|
if let thirdReply = replies?[2] as? TalkPageReply {
|
|||
|
XCTAssertEqual(thirdReply.text, "Yes I see, I am nested as well. <a href='./Special:Contributions/47.184.10.84' title='Special:Contributions/47.184.10.84'>47.184.10.84</a> 20:52, 21 June 2019 (UTC)")
|
|||
|
XCTAssertEqual(thirdReply.depth, 2, "Unexpected reply depth")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected third reply type")
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected first topic type")
|
|||
|
}
|
|||
|
|
|||
|
if let secondTopic = topics?[2] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(secondTopic.title, "Subtopic time")
|
|||
|
XCTAssertEqual(secondTopic.replies?.count, 2, "Unexpected topic items count")
|
|||
|
}
|
|||
|
|
|||
|
if let thirdTopic = topics?[3] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(thirdTopic.title, "Sub sub topic")
|
|||
|
XCTAssertEqual(thirdTopic.replies?.count, 2, "Unexpected topic items count")
|
|||
|
}
|
|||
|
|
|||
|
if let fourthTopic = topics?[4] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(fourthTopic.title, "Topic <a href='./Part' title='Part'>Part</a> Deux")
|
|||
|
XCTAssertEqual(fourthTopic.replies?.count, 9, "Unexpected topic items count")
|
|||
|
}
|
|||
|
|
|||
|
if let fifthTopic = topics?[5] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(fifthTopic.title, "Topic <a href='./Part' title='Part'>Part</a> Trois")
|
|||
|
XCTAssertEqual(fifthTopic.replies?.count, 1, "Unexpected topic items count")
|
|||
|
}
|
|||
|
|
|||
|
// confirm one talk page exists in DB
|
|||
|
guard let secondResults = try? tempDataStore.viewContext.fetch(fetchRequest) else {
|
|||
|
XCTFail("Failure fetching saved talk pages")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(secondResults.count, 1, "Expected 1 talk page in DB")
|
|||
|
XCTAssertEqual(secondResults.first, dbTalkPage)
|
|||
|
}
|
|||
|
|
|||
|
func testExistingTalkPagePullsFromDB() {
|
|||
|
|
|||
|
// confirm no talk pages in DB
|
|||
|
let fetchRequest: NSFetchRequest<TalkPage> = TalkPage.fetchRequest()
|
|||
|
|
|||
|
guard let firstResults = try? tempDataStore.viewContext.fetch(fetchRequest) else {
|
|||
|
XCTFail("Failure fetching initial talk pages")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(firstResults.count, 0, "Expected zero existing talk pages at first")
|
|||
|
|
|||
|
// add network talk page
|
|||
|
guard let json = wmf_bundle().wmf_data(fromContentsOfFile: TalkPageTestHelpers.TalkPageJSONType.original.fileName, ofType: "json"),
|
|||
|
let talkPage = TalkPageTestHelpers.networkTalkPage(for: urlString1, data: json, revisionId: 1) else {
|
|||
|
XCTFail("Failure stubbing out network talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// create db talk page
|
|||
|
guard let dbTalkPage = moc.createTalkPage(with: talkPage) else {
|
|||
|
XCTFail("Failure to create db talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// confirm asking for existing talk page with key pulls same talk page
|
|||
|
guard let existingTalkPage = try? moc.talkPage(for: URL(string: urlString1)!) else {
|
|||
|
XCTFail("Pull existing talk page fails")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(existingTalkPage, dbTalkPage, "Unexpected existing talk page value")
|
|||
|
|
|||
|
// confirm asking for urlString2 pulls nothing
|
|||
|
do {
|
|||
|
let nonexistantTalkPage = try moc.talkPage(for: URL(string: urlString2)!)
|
|||
|
XCTAssertNil(nonexistantTalkPage)
|
|||
|
} catch {
|
|||
|
XCTFail("Pull existing talk page fails")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func testUpdateExistingTalkPageUpdatesValues() {
|
|||
|
// confirm no talk pages in DB
|
|||
|
let fetchRequest: NSFetchRequest<TalkPage> = TalkPage.fetchRequest()
|
|||
|
|
|||
|
guard let firstResults = try? tempDataStore.viewContext.fetch(fetchRequest) else {
|
|||
|
XCTFail("Failure fetching initial talk pages")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(firstResults.count, 0, "Expected zero existing talk pages at first")
|
|||
|
|
|||
|
// add network talk page
|
|||
|
guard let originalJson = wmf_bundle().wmf_data(fromContentsOfFile: TalkPageTestHelpers.TalkPageJSONType.original.fileName, ofType: "json"),
|
|||
|
let talkPage = TalkPageTestHelpers.networkTalkPage(for: urlString1, data: originalJson, revisionId: 1) else {
|
|||
|
XCTFail("Failure stubbing out network talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// create db talk page
|
|||
|
guard let dbTalkPage = moc.createTalkPage(with: talkPage) else {
|
|||
|
XCTFail("Failure to create db talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// mark last topic as read to confirm it stays read after updating.
|
|||
|
let topics = dbTalkPage.topics?.allObjects.sorted { ($0 as! TalkPageTopic).sort < ($1 as! TalkPageTopic).sort }
|
|||
|
if let fifthTopic = topics?[5] as? TalkPageTopic {
|
|||
|
fifthTopic.content?.isRead = true
|
|||
|
do {
|
|||
|
try moc.save()
|
|||
|
} catch {
|
|||
|
XCTFail("Failure to save isRead flag")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// get updated talk page payload
|
|||
|
guard let updatedJson = wmf_bundle().wmf_data(fromContentsOfFile: TalkPageTestHelpers.TalkPageJSONType.updated.fileName, ofType: "json"),
|
|||
|
let updatedTalkPage = TalkPageTestHelpers.networkTalkPage(for: urlString1, data: updatedJson, revisionId: 1) else {
|
|||
|
XCTFail("Failure stubbing out network talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// update local talk page with new talk page
|
|||
|
guard let updatedDbTalkPage = moc.updateTalkPage(dbTalkPage, with: updatedTalkPage) else {
|
|||
|
XCTFail("Failure updating existing local talk page")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(updatedDbTalkPage.topics?.count, 3, "Unexpected topic count")
|
|||
|
|
|||
|
let updatedTopics = updatedDbTalkPage.topics?.allObjects.sorted { ($0 as! TalkPageTopic).sort < ($1 as! TalkPageTopic).sort }
|
|||
|
|
|||
|
if let introTopic = updatedTopics?[0] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(introTopic.title, "", "Unexpected topic title")
|
|||
|
XCTAssertEqual(introTopic.replies?.count, 1, "Unexpected replies count")
|
|||
|
let replies = introTopic.replies?.allObjects.sorted { ($0 as! TalkPageReply).sort < ($1 as! TalkPageReply).sort }
|
|||
|
if let firstReply = replies?[0] as? TalkPageReply {
|
|||
|
XCTAssertEqual(firstReply.text, "Hello! This is some introduction text on my talk page. L8erz, <a href='./User:TSevener_(WMF)' title='User:TSevener (WMF)'>TSevener (WMF)</a> (<a href='./User_talk:TSevener_(WMF)' title='User talk:TSevener (WMF)'>talk</a>) 20:48, 21 June 2019 (UTC)", "Unexpected replies html")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected first reply type")
|
|||
|
}
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected intro topic type")
|
|||
|
}
|
|||
|
|
|||
|
if let firstTopic = updatedTopics?[1] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(firstTopic.title, "Topic <a href='./Part' title='Part'>Part</a> Deux", "Unexpected topic title")
|
|||
|
XCTAssertEqual(firstTopic.replies?.count, 11, "Unexpected topic items count")
|
|||
|
|
|||
|
let replies = firstTopic.replies?.allObjects.sorted { ($0 as! TalkPageReply).sort < ($1 as! TalkPageReply).sort }
|
|||
|
if let firstReply = replies?[0] as? TalkPageReply {
|
|||
|
XCTAssertEqual(firstReply.text, "Also injecting something in the front because why not. 🤷♀️ <a href='./User:TSevener_(WMF)' title='User:TSevener (WMF)'>TSevener (WMF)</a> (<a href='./User_talk:TSevener_(WMF)' title='User talk:TSevener (WMF)'>talk</a>) 21:17, 21 June 2019 (UTC)")
|
|||
|
XCTAssertEqual(firstReply.depth, 0, "Unexpected reply depth")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected first reply type")
|
|||
|
}
|
|||
|
|
|||
|
if let secondReply = replies?[1] as? TalkPageReply {
|
|||
|
XCTAssertEqual(secondReply.text, "Ok try this on for size - can you put a link in a topic title from the iOS app? Only time will tell. <a href='./Special:Contributions/47.184.10.84' title='Special:Contributions/47.184.10.84'>47.184.10.84</a> 20:57, 21 June 2019 (UTC)")
|
|||
|
XCTAssertEqual(secondReply.depth, 0, "Unexpected reply depth")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected second reply type")
|
|||
|
}
|
|||
|
|
|||
|
if let thirdReply = replies?[2] as? TalkPageReply {
|
|||
|
XCTAssertEqual(thirdReply.text, "It certainly seems so. It is good we tested this my friend. <a href='./User:TSevener_(WMF)' title='User:TSevener (WMF)'>TSevener (WMF)</a> (<a href='./User_talk:TSevener_(WMF)' title='User talk:TSevener (WMF)'>talk</a>) 20:58, 21 June 2019 (UTC)")
|
|||
|
XCTAssertEqual(thirdReply.depth, 1, "Unexpected reply depth")
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected third reply type")
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
XCTFail("Unexpected first topic type")
|
|||
|
}
|
|||
|
|
|||
|
if let secondTopic = updatedTopics?[2] as? TalkPageTopic {
|
|||
|
XCTAssertEqual(secondTopic.title, "Topic <a href='./Part' title='Part'>Part</a> Trois")
|
|||
|
XCTAssertEqual(secondTopic.replies?.count, 1, "Unexpected topic items count")
|
|||
|
XCTAssertTrue(secondTopic.content?.isRead ?? false, "isRead flag flipped back to false after reorder.")
|
|||
|
}
|
|||
|
|
|||
|
// confirm one talk page exists in DB
|
|||
|
guard let secondResults = try? tempDataStore.viewContext.fetch(fetchRequest) else {
|
|||
|
XCTFail("Failure fetching saved talk pages")
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
XCTAssertEqual(secondResults.count, 1, "Expected 1 talk page in DB")
|
|||
|
XCTAssertEqual(secondResults.first, dbTalkPage)
|
|||
|
}
|
|||
|
}
|