import XCTest class ReadingListsTests: XCTestCase { var dataStore: MWKDataStore! override func setUp() { super.setUp() dataStore = MWKDataStore.temporary() } override func tearDown() { super.tearDown() dataStore.removeFolderAtBasePath() } func testListsWithTheSameName() { let originalName = "pebbles" let casedName = "pEbBLes" let diacriticName = "pEbBLĂ©s" do { let list = try dataStore.readingListsController.createReadingList(named: originalName, description: "Foo") XCTAssert(list.name == originalName) } catch let error { XCTAssert(false, "Should be able to create \(originalName) reading list: \(error)") } do { _ = try dataStore.readingListsController.createReadingList(named: casedName, description: "Foo") XCTAssert(true, "Should be able to create list with same title and different case") } catch let error { XCTAssert(false, "Should not throw an error: \(error) when creating a list with the same title and different case") } do { let list = try dataStore.readingListsController.createReadingList(named: diacriticName, description: "Foo") XCTAssert(list.name == diacriticName) } catch let error { XCTAssert(false, "Should be able to create \(diacriticName) reading list: \(error)") } } func testDeletingExistingReadingLists() { let readingListNames = ["foo", "bar"] var readingLists: [ReadingList] = [] do { readingLists.append(try dataStore.readingListsController.createReadingList(named: readingListNames[0], description: "Foo")) } catch let error { XCTAssert(false, "Should be able to create \(readingListNames[0]) reading list: \(error)") } do { readingLists.append(try dataStore.readingListsController.createReadingList(named: readingListNames[1], description: "Foo")) } catch let error { XCTAssert(false, "Should be able to create \(readingListNames[1]) reading list: \(error)") } do { try dataStore.readingListsController.delete(readingLists: readingLists) } catch let error { XCTAssert(false, "Should be able to delete \(readingListNames) reading lists: \(error)") } } func testDeletingNonexistentReadingLists() { let readingListNames = ["foo", "bar"] var readingLists: [ReadingList] = [] do { readingLists.append(try dataStore.readingListsController.createReadingList(named: readingListNames[0], description: "Foo")) } catch let error { XCTAssert(false, "Should be able to create \(readingListNames[0]) reading list: \(error)") } do { try dataStore.readingListsController.delete(readingLists: readingLists) } catch let error { XCTAssert(false, "Should attempt to delete \(readingListNames) reading lists: \(error)") } } func testCreatingReadingListWithArticles() { let readingListName = "foo" let articleURLs = [URL(string: "//en.wikipedia.org/wiki/Foo")!, URL(string: "//en.wikipedia.org/wiki/Bar")!] let articles = articleURLs.compactMap { (articleURL) -> WMFArticle? in return dataStore.fetchOrCreateArticle(with: articleURL) } let articleKeys = articles.compactMap { (article) -> String? in return article.key } do { let readingList = try dataStore.readingListsController.createReadingList(named: readingListName, description: "Foo", with: articles) XCTAssert(readingList.articleKeys.wmf_containsObjectsInAnyOrderAndMatchesCount(articleKeys)) } catch let error { XCTAssert(false, "Should be able to add articles to \(readingListName) reading list: \(error)") } } func testAddingArticlesToExistingReadingList() { let readingListName = "foo" let articleURLs = [URL(string: "//en.wikipedia.org/wiki/Foo")!, URL(string: "//en.wikipedia.org/wiki/Bar")!] let otherArticleURLs = [URL(string: "//en.wikipedia.org/wiki/Foo")!, URL(string: "//en.wikipedia.org/wiki/Bar")!, URL(string: "//en.wikipedia.org/wiki/Baz")!] let articles = articleURLs.compactMap { (articleURL) -> WMFArticle? in return dataStore.fetchOrCreateArticle(with: articleURL) } let otherArticles = otherArticleURLs.compactMap { (articleURL) -> WMFArticle? in return dataStore.fetchOrCreateArticle(with: articleURL) } let otherArticleKeys = otherArticles.compactMap { (article) -> String? in return article.key } do { let readingList = try dataStore.readingListsController.createReadingList(named: readingListName, description: "Foo", with: articles) do { try dataStore.readingListsController.add(articles: otherArticles, to: readingList) XCTAssert(readingList.articleKeys.wmf_containsObjectsInAnyOrderAndMatchesCount(otherArticleKeys)) } catch let error { XCTAssert(false, "Should be able to : \(error)") } } catch let error { XCTAssert(false, "Should be able to add articles to \(readingListName) reading list: \(error)") } } func testAddingDuplicateArticlesToExistingReadingList() { let readingListName = "foo" let articleURLs = [URL(string: "//en.wikipedia.org/wiki/Foo")!, URL(string: "//en.wikipedia.org/wiki/Foo")!] let articles = articleURLs.compactMap { (articleURL) -> WMFArticle? in return dataStore.fetchOrCreateArticle(with: articleURL) } let articleKeys = articles.compactMap { (article) -> String? in return article.key } do { let readingList = try dataStore.readingListsController.createReadingList(named: readingListName, description: "Foo", with: articles) let existingArticleKeys = readingList.articleKeys XCTAssert(existingArticleKeys.wmf_containsObjectsInAnyOrder(articleKeys) && existingArticleKeys.count == 1) } catch let error { XCTAssert(false, "Should be able to add articles to \(readingListName) reading list: \(error)") } } } extension Array where Element: Hashable { func wmf_containsObjectsInAnyOrderAndMatchesCount(_ other: [Element]) -> Bool { return wmf_containsObjectsInAnyOrder(other) && self.count == other.count } func wmf_containsObjectsInAnyOrder(_ other: [Element]) -> Bool { let selfSet = Set(self) let otherSet = Set(other) return otherSet.isSubset(of: selfSet) } }