2024-04-03 06:43:06 +02:00
|
|
|
|
//
|
|
|
|
|
// OPMLTests.swift
|
|
|
|
|
// RSParser
|
|
|
|
|
//
|
|
|
|
|
// Created by Brent Simmons on 6/25/17.
|
|
|
|
|
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import XCTest
|
2024-08-27 07:39:46 +02:00
|
|
|
|
import SAX
|
|
|
|
|
@testable import OPMLParser
|
2024-04-03 06:43:06 +02:00
|
|
|
|
|
|
|
|
|
class OPMLTests: XCTestCase {
|
|
|
|
|
|
|
|
|
|
let subsData = parserData("Subs", "opml", "http://example.org/")
|
|
|
|
|
|
|
|
|
|
func testOPMLParsingPerformance() {
|
|
|
|
|
|
2024-08-27 18:16:41 +02:00
|
|
|
|
// 0.003 sec on my M1 Mac Studio 2022
|
2024-04-03 06:43:06 +02:00
|
|
|
|
self.measure {
|
2024-08-27 07:39:46 +02:00
|
|
|
|
let _ = OPMLParser.document(with: self.subsData)
|
2024-04-03 06:43:06 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func testNotOPML() {
|
|
|
|
|
|
|
|
|
|
let d = parserData("DaringFireball", "rss", "http://daringfireball.net/")
|
2024-08-27 07:39:46 +02:00
|
|
|
|
XCTAssertNil(OPMLParser.document(with: d))
|
2024-04-03 06:43:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func testSubsStructure() {
|
2024-08-27 07:39:46 +02:00
|
|
|
|
let opmlDocument = OPMLParser.document(with: subsData)
|
|
|
|
|
XCTAssertNotNil(opmlDocument)
|
|
|
|
|
|
|
|
|
|
XCTAssertEqual("Subs", opmlDocument!.title)
|
|
|
|
|
XCTAssertEqual("http://example.org/", opmlDocument!.url)
|
|
|
|
|
recursivelyCheckOPMLStructure(opmlDocument!)
|
2024-04-03 06:43:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func testFindingTitles() {
|
|
|
|
|
// https://github.com/brentsimmons/NetNewsWire/issues/527
|
|
|
|
|
// Fix a bug where titles aren’t found when there’s no title attribute in the OPML,
|
|
|
|
|
// which appears to be true with OPML generated by The Old Reader.
|
|
|
|
|
|
|
|
|
|
let d = parserData("SubsNoTitleAttributes", "opml", "http://example.org/")
|
2024-08-27 07:39:46 +02:00
|
|
|
|
let opmlDocument = OPMLParser.document(with: d)
|
|
|
|
|
recursivelyCheckOPMLStructure(opmlDocument!)
|
2024-04-03 06:43:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private extension OPMLTests {
|
|
|
|
|
|
2024-08-27 07:39:46 +02:00
|
|
|
|
func recursivelyCheckOPMLStructure(_ item: OPMLItem) {
|
2024-04-03 06:43:06 +02:00
|
|
|
|
let feedSpecifier = item.feedSpecifier
|
2024-08-27 07:39:46 +02:00
|
|
|
|
if !(item is OPMLDocument) {
|
|
|
|
|
XCTAssertNotNil(item.attributes!.opml_text)
|
2024-04-03 06:43:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If it has no children, it should have a feed specifier. The converse is also true.
|
2024-08-27 07:39:46 +02:00
|
|
|
|
var isFolder = item.items != nil && item.items!.count > 0
|
|
|
|
|
if !isFolder && item.attributes?.opml_title == "Skip" {
|
2024-04-03 06:43:06 +02:00
|
|
|
|
isFolder = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !isFolder {
|
|
|
|
|
XCTAssertNotNil(feedSpecifier!.title)
|
|
|
|
|
XCTAssertNotNil(feedSpecifier!.feedURL)
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
XCTAssertNil(feedSpecifier)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-27 07:39:46 +02:00
|
|
|
|
if item.items != nil && item.items!.count > 0 {
|
|
|
|
|
for oneItem in item.items! {
|
2024-04-03 06:43:06 +02:00
|
|
|
|
recursivelyCheckOPMLStructure(oneItem)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-27 07:39:46 +02:00
|
|
|
|
|
|
|
|
|
func parserData(_ filename: String, _ fileExtension: String, _ url: String) -> ParserData {
|
|
|
|
|
let filename = "Resources/\(filename)"
|
|
|
|
|
let path = Bundle.module.path(forResource: filename, ofType: fileExtension)!
|
|
|
|
|
let data = try! Data(contentsOf: URL(fileURLWithPath: path))
|
|
|
|
|
return ParserData(url: url, data: data)
|
|
|
|
|
}
|