use crate::models::{Category, CategoryID, CategoryType, Feed, FeedID, FeedMapping, Url, NEWSFLASH_TOPLEVEL};
use crate::util::opml;
use reqwest::Client;

#[test]
fn opml_export_1() {
    let mut categories: Vec<Category> = Vec::new();
    let mut feeds: Vec<Feed> = Vec::new();
    let mut mappings: Vec<FeedMapping> = Vec::new();

    categories.push(Category {
        category_id: CategoryID::new("cat1"),
        label: "Category 1".to_owned(),
        sort_index: Some(0),
        parent_id: NEWSFLASH_TOPLEVEL.clone(),
        category_type: CategoryType::Default,
    });

    categories.push(Category {
        category_id: CategoryID::new("cat2"),
        label: "Category 2".to_owned(),
        sort_index: Some(1),
        parent_id: NEWSFLASH_TOPLEVEL.clone(),
        category_type: CategoryType::Default,
    });

    categories.push(Category {
        category_id: CategoryID::new("cat3"),
        label: "Category 3".to_owned(),
        sort_index: Some(0),
        parent_id: CategoryID::new("cat1"),
        category_type: CategoryType::Default,
    });

    feeds.push(Feed {
        feed_id: FeedID::new("feed1"),
        label: "Feed 1".to_owned(),
        website: Some(Url::parse("http://golem.de").unwrap()),
        feed_url: Some(Url::parse("https://rss.golem.de/rss.php?feed=RSS2.0").unwrap()),
        icon_url: None,
        sort_index: Some(0),
    });

    feeds.push(Feed {
        feed_id: FeedID::new("feed2"),
        label: "Feed 2".to_owned(),
        website: Some(Url::parse("http://golem.de").unwrap()),
        feed_url: Some(Url::parse("https://rss.golem.de/rss.php?feed=ATOM1.0").unwrap()),
        icon_url: None,
        sort_index: Some(1),
    });

    feeds.push(Feed {
        feed_id: FeedID::new("feed3"),
        label: "Feed 3".to_owned(),
        website: Some(Url::parse("http://heise.de").unwrap()),
        feed_url: Some(Url::parse("https://www.heise.de/newsticker/heise-atom.xml").unwrap()),
        icon_url: None,
        sort_index: Some(2),
    });

    mappings.push(FeedMapping {
        feed_id: FeedID::new("feed1"),
        category_id: NEWSFLASH_TOPLEVEL.clone(),
    });

    mappings.push(FeedMapping {
        feed_id: FeedID::new("feed1"),
        category_id: CategoryID::new("cat1"),
    });

    mappings.push(FeedMapping {
        feed_id: FeedID::new("feed2"),
        category_id: CategoryID::new("cat2"),
    });

    mappings.push(FeedMapping {
        feed_id: FeedID::new("feed3"),
        category_id: CategoryID::new("cat3"),
    });

    let opml_string = opml::generate_opml(&categories, &feeds, &mappings).unwrap();
    let opml_reference = r#"<?xml version='1.0'?><opml version='1.0'><head><title>NewsFlash OPML export</title></head><body><outline title='Category 1' text='Category 1'><outline title='Category 3' text='Category 3'><outline title='Feed 3' text='Feed 3' type='rss' xmlUrl='https://www.heise.de/newsticker/heise-atom.xml' htmlUrl='http://heise.de/'/></outline><outline title='Feed 1' text='Feed 1' type='rss' xmlUrl='https://rss.golem.de/rss.php?feed=RSS2.0' htmlUrl='http://golem.de/'/></outline><outline title='Category 2' text='Category 2'><outline title='Feed 2' text='Feed 2' type='rss' xmlUrl='https://rss.golem.de/rss.php?feed=ATOM1.0' htmlUrl='http://golem.de/'/></outline><outline title='Feed 1' text='Feed 1' type='rss' xmlUrl='https://rss.golem.de/rss.php?feed=RSS2.0' htmlUrl='http://golem.de/'/></body></opml>"#;

    assert_eq!(&opml_string, opml_reference);
}

#[tokio::test(basic_scheduler)]
async fn opml_import_1() {
    let opml_string = r#"<?xml version="1.0" encoding="UTF-8"?>
    <opml version="1.0">
        <head>
            <title>Sample OPML file for RSSReader</title>
        </head>
        <body>
            <outline title="News" text="News">
                <outline text="Big News Finland" title="Big News Finland" type="rss" xmlUrl="http://www.bignewsnetwork.com/?rss=37e8860164ce009a"/>
                <outline text="Euronews" title="Euronews" type="rss" xmlUrl="http://feeds.feedburner.com/euronews/en/news/"/>
                <outline text="Reuters Top News" title="Reuters Top News" type="rss" xmlUrl="http://feeds.reuters.com/reuters/topNews"/>
                <outline text="Yahoo Europe" title="Yahoo Europe" type="rss" xmlUrl="http://rss.news.yahoo.com/rss/europe"/>
            </outline>

            <outline title="Leisure" text="Leisure">
                <outline text="CNN Entertainment" title="CNN Entertainment" type="rss" xmlUrl="http://rss.cnn.com/rss/edition_entertainment.rss"/>
                <outline text="E! News" title="E! News" type="rss" xmlUrl="http://uk.eonline.com/syndication/feeds/rssfeeds/topstories.xml"/>
                <outline text="Hollywood Reporter" title="Hollywood Reporter" type="rss" xmlUrl="http://feeds.feedburner.com/thr/news"/>
                <outline text="Reuters Entertainment" title="Reuters Entertainment" type="rss"  xmlUrl="http://feeds.reuters.com/reuters/entertainment"/>
                <outline text="Reuters Music News" title="Reuters Music News" type="rss" xmlUrl="http://feeds.reuters.com/reuters/musicNews"/>
                <outline text="Yahoo Entertainment" title="Yahoo Entertainment" type="rss" xmlUrl="http://rss.news.yahoo.com/rss/entertainment"/>
            </outline>

            <outline title="Sports" text="Sports">
                <outline text="Formula 1" title="Formula 1" type="rss" xmlUrl="http://www.formula1.com/rss/news/latest.rss"/>
                <outline text="MotoGP" title="MotoGP" type="rss" xmlUrl="http://rss.crash.net/crash_motogp.xml"/>
                <outline text="N.Y.Times Track And Field" title="N.Y.Times Track And Field" type="rss" xmlUrl="http://topics.nytimes.com/topics/reference/timestopics/subjects/t/track_and_field/index.html?rss=1"/>
                <outline text="Reuters Sports" title="Reuters Sports" type="rss" xmlUrl="http://feeds.reuters.com/reuters/sportsNews"/>
                <outline text="Yahoo Sports NHL" title="Yahoo Sports NHL" type="rss" xmlUrl="http://sports.yahoo.com/nhl/rss.xml"/>
                <outline text="Yahoo Sports" title="Yahoo Sports" type="rss" xmlUrl="http://rss.news.yahoo.com/rss/sports"/>
            </outline>

            <outline title="Tech" text="Tech">
                <outline text="Coding Horror" title="Coding Horror" type="rss" xmlUrl="http://feeds.feedburner.com/codinghorror/"/>
                <outline text="Gadget Lab" title="Gadget Lab" type="rss" xmlUrl="http://www.wired.com/gadgetlab/feed/"/>
                <outline text="Gizmodo" title="Gizmodo" type="rss" xmlUrl="http://gizmodo.com/index.xml"/>
                <outline text="Reuters Technology" title="Reuters Technology" type="rss" xmlUrl="http://feeds.reuters.com/reuters/technologyNews"/>
            </outline>
        </body>
    </opml>
    "#;

    let res = opml::parse_opml(opml_string, false, &Client::new()).await.unwrap();

    assert_eq!(res.categories.len(), 4);
    assert_eq!(res.feeds.len(), 20);
    assert_eq!(res.feed_mappings.len(), res.feeds.len());
    assert_eq!(res.categories.get(2).unwrap().label, "Sports");
    assert_eq!(res.feeds.get(6).unwrap().label, "Hollywood Reporter");
}

#[tokio::test(basic_scheduler)]
async fn opml_import_2() {
    let opml_string = r#"<?xml version="1.0" encoding="utf-8"?>
    <opml version="1.1">
        <head>
            <title>Blogtrottr OPML export</title>
            <dateCreated>Tue, 14 Apr 2015 20:43:49 +0000</dateCreated>
        </head>
        <body>
            <outline text="Subscriptions">
                <outline title="Create your own games» Game Creation Blog by Koonsolo" text="A blog on how to create your own computer games (by Koen Witters)" type="rss" xmlUrl="http://dev.koonsolo.com/feed/"/>
                <outline title="Digitanks" text="" type="rss" xmlUrl="http://digitanks.com/feed/"/>
                <outline title="Jacques Mattheij" text="" type="rss" xmlUrl="http://jacquesmattheij.com/rss.xml"/>
                <outline title="jwz" text="jwz - LiveJournal.com" type="rss" xmlUrl="http://jwz.livejournal.com/data/rss"/>
                <outline title="Pyevolve" text="by Christian S. Perone" type="rss" xmlUrl="http://feeds2.feedburner.com/pyevolve"/>
                <outline title="Yipit Django Blog" text="Django Tips and Best Practices" type="rss" xmlUrl="http://feeds.feedburner.com/YipitDjangoBlog?format=xml"/>
                <outline title="802-BIKEGUY" text="Bike pedals before gas pedals!" type="rss" xmlUrl="http://www.802bikeguy.com/feed/"/>
                <outline title="A Smart Bear" type="rss" xmlUrl="http://feeds.feedburner.com/blogspot/smartbear"/>
                <outline title="AVC" text="Musings of a VC in NYC" type="rss" xmlUrl="http://feeds.feedburner.com/avc"/>
                <outline title="ActiveBlog:  Insights on Code, the Cloud and More" text="" type="rss" xmlUrl="http://blogs.activestate.com/feed"/>
                <outline title="Algorithm.co.il" text="Algorithms, for the heck of it" type="rss" xmlUrl="http://www.algorithm.co.il/blogs/index.php/feed/"/>
                <outline title="Art Of Community Online" text="The Book On Community Management, by Jono Bacon" type="rss" xmlUrl="http://www.artofcommunityonline.org/feed/"/>
                <outline title="BetaList" text="BetaList provides an overview of upcoming internet startups. Discover and get early access to the future." type="rss" xmlUrl="http://betali.st/rss"/>
                <outline title="Black&amp;White™" text="Essay" type="rss" xmlUrl="http://000fff.org/feed/"/>
                <outline title="Critical-Gaming Blog" text="" type="rss" xmlUrl="http://critical-gaming.squarespace.com/blog/rss.xml"/>
                <outline title="Blog - Stack Exchange" text="free, community powered Q&amp;A" type="rss" xmlUrl="http://blog.stackoverflow.com/feed/"/>
                <outline title="Brainy Gamer" text="Thoughtful conversation about video games" type="rss" xmlUrl="http://feeds.feedburner.com/brainygamer"/>
                <outline title="Brandon Staggs .Com" text="Software, Society, the Bible, Politics, and everything else." type="rss" xmlUrl="http://www.brandonstaggs.com/feed/atom/"/>
                <outline title="Bruce Eckel's Weblog" text="Artima Weblogs is a community of bloggers" type="rss" xmlUrl="http://www.artima.com/weblogs/feeds/bloggers/beckel.rss"/>
                <outline title="Chocolate Hammer" text="Home of Vatsy and Bruno, Let's Plays, Several Ancient Ghosts" type="rss" xmlUrl="http://www.chocolatehammer.org/?feed=rss2"/>
                <outline title="Coding Horror" text="programming and human factors" type="rss" xmlUrl="http://feeds.feedburner.com/codinghorror"/>
                <outline title="Coding the Wheel" text="Building the collective hamster wheel, one line of code at a time" type="rss" xmlUrl="http://feeds.feedburner.com/codingthewheel"/>
                <outline title="Zukifying Security" text="" type="rss" xmlUrl="http://imthezuk.blogspot.com/feeds/posts/default?alt=rss"/>
                <outline title="Zukifying Security" text="" type="rss" xmlUrl="http://imthezuk.blogspot.com/feeds/posts/default"/>
                <outline title="Daniel Lew's Coding Thoughts" text="I post random things" type="rss" xmlUrl="http://daniel-codes.blogspot.com/feeds/posts/default?alt=rss"/>
                <outline title="Dead Panic" text="" type="rss" xmlUrl="http://deadpanic.com/rss.xml"/>
                <outline title="Derren Brown » Blog" text="The Official Site" type="rss" xmlUrl="http://derrenbrownart.com/blog/feed/"/>
                <outline title="Dilbert Daily Strip" text="" type="rss" xmlUrl="http://feeds.dilbert.com/DilbertDailyStrip"/>
                <outline title="Scott Adams Blog" text="" type="rss" xmlUrl="http://feed.dilbert.com/dilbert/blog"/>
                <outline title="Fog Creek Blog" text="Helping the world's best developers make better software" type="rss" xmlUrl="http://www.fogcreek.com/FogBugz/blog/syndication.axd"/>
                <outline title="Gamasutra News" text="Gamasutra News" type="rss" xmlUrl="http://feeds.feedburner.com/GamasutraFeatureArticles/"/>
                <outline title="Gigantt Blog" text="" type="rss" xmlUrl="http://feeds.feedburner.com/GiganttBlog"/>
                <outline title="Google Engineering Tools" text="" type="rss" xmlUrl="http://google-engtools.blogspot.com/atom.xml"/>
                <outline title="Guido van Rossum's Weblog" text="Artima Weblogs is a community" type="rss" xmlUrl="http://www.artima.com/weblogs/feeds/bloggers/guido.rss"/>
                <outline title="Henrik's Blog" text="" type="rss" xmlUrl="http://hforsten.com/feeds/all.atom.xml"/>
                <outline title="Heroes Happen Here {Comic Series}" text="Brought to you by Microsoft and Seagate" type="rss" xmlUrl="http://blogs.technet.com/hhh_comic/rss.xml"/>
                <outline title="HTML5 Security Cheatsheet" text="Page2RSS " type="rss" xmlUrl="http://page2rss.com/rss/957dc181afad20429e4633d20b1ca5a2"/>
                <outline title="‫iAndroid - האנדרואיד של גוגל - בעברית !‬" text="‫asdf‬" type="rss" xmlUrl="http://iandroid.co.il/dr-iandroid/feed"/>
                <outline title="Israel Venture Capital 2.0" text="General Partner" type="rss" xmlUrl="http://feeds.feedburner.com/typepad/BJMB"/>
                <outline title="James Breckenridge" text="Online, Marketing &amp; General Rubbish" type="rss" xmlUrl="http://www.jamesbreckenridge.co.uk/feed"/>
                <outline title="Joel on Software" text="Painless Software Management" type="rss" xmlUrl="http://www.joelonsoftware.com/rss.xml"/>
                <outline title="Man Vs. Debt" text="Sell your crap" type="rss" xmlUrl="http://feeds2.feedburner.com/manvsdebt"/>
                <outline title="My Boring Ass Life" text="Kevin Smith's Boring Ass Life" type="rss" xmlUrl="http://silentbobspeaks.com/?feed=rss2"/>
                <outline title="Ned Batchelder's blog" text="Ned Batchelder's personal blog." type="rss" xmlUrl="http://nedbatchelder.com/blog/atom.xml"/>
                <outline title="Nelson's Weblog" text="Occasional blog, powered by Blosxom" type="rss" xmlUrl="http://www.somebits.com/weblog/index.atom"/>
                <outline title="Neopythonic" text="Ramblings through technology" type="rss" xmlUrl="http://neopythonic.blogspot.com/feeds/posts/default"/>
                <outline title="New Rules" text="This is a blog" type="rss" xmlUrl="http://feedproxy.google.com/NewRules"/>
                <outline title="Paul Graham: Essays" text="Scraped feed provided by aaronsw.com" type="rss" xmlUrl="http://www.aaronsw.com/2002/feeds/pgessays.rss"/>
                <outline title="Penny Arcade" text="News Fucker 5000" type="rss" xmlUrl="http://feeds.penny-arcade.com/pa-mainsite"/>
                <outline title="Philosophy Bro" text="Philosophy is hard" type="rss" xmlUrl="http://feeds.feedburner.com/PhilosophyBro"/>
                <outline title="Procrastineering" text="Project blog for Johnny Chung Lee" type="rss" xmlUrl="http://procrastineering.blogspot.com/feeds/posts/default"/>
                <outline title="Robert's talk" text="Web development and Internet trends" type="rss" xmlUrl="http://feeds.feedburner.com/robertnyman"/>
                <outline title="SaaS Adventures" text="Tom's attempts to make money" type="rss" xmlUrl="http://feeds.feedburner.com/SaasAdventures"/>
                <outline title="secretGeek" text="secretGeek" type="rss" xmlUrl="http://www.secretgeek.net/rss.asp"/>
                <outline title="Seth Godin's Blog" text="Seth Godin's riffs on marketing" type="rss" xmlUrl="http://feeds.feedburner.com/typepad/sethsmainblog"/>
                <outline title="Shifty Jelly's blog of mystery" text="because some things were meant to be shifty..." type="rss" xmlUrl="https://shiftyjelly.wordpress.com/feed/"/>
                <outline title="Stephen Fry's PODGRAMS" text="Stephen Fry, British actor" type="rss" xmlUrl="http://www.stephenfry.com/media/audio/rss/m4a/"/>
                <outline title="Stevey's Blog Rants" text="Random whining and stuff." type="rss" xmlUrl="http://steve-yegge.blogspot.com/feeds/posts/default"/>
                <outline title="Successful Software" text="...requires more than just good programming." type="rss" xmlUrl="http://successfulsoftware.net/feed/"/>
                <outline title="Surf Roots, Software Thoughts" text="" type="rss" xmlUrl="http://alexlod.com/feed/"/>
                <outline title="Sveder's Blog" text="Sveder's blog about programming and stuff" type="rss" xmlUrl="http://feeds.feedburner.com/Sveder"/>
                <outline title="System Malfunction" text="An epic tale of courage" type="rss" xmlUrl="http://www.systemmalfunction.com/feeds/posts/default?alt=rss"/>
                <outline title="The Dilbert Blog" text="Dilbert humor" type="rss" xmlUrl="http://dilbertblog.typepad.com/the_dilbert_blog/rss.xml"/>
                <outline title="The Escapist" text="Shamus Young flings" type="rss" xmlUrl="http://www.escapistmagazine.com/rss/articles/comics/stolen-pixels"/>
                <outline title="The Ludologist" text="My name is Jesper Juul" type="rss" xmlUrl="http://www.jesperjuul.net/ludologist/feed"/>
                <outline title="The Radioactive Yak" text="" type="rss" xmlUrl="http://feeds.feedburner.com/TheRadioactiveYak"/>
                <outline title="The Resigned Gamer" text="Everything I hate about the thing I love the most." type="rss" xmlUrl="http://resignedgamer.blogspot.com/feeds/posts/default"/>
                <outline title="The Web World" text="Front-end and back-end web development" type="rss" xmlUrl="http://ronreiterdotcom.wordpress.com/feed/"/>
                <outline title="Twenty Sided" text="A Website for your Internet" type="rss" xmlUrl="http://www.shamusyoung.com/twentysidedtale/?feed=rss2"/>
                <outline title="Venture Hacks" text="Good advice for startups" type="rss" xmlUrl="http://feeds.venturehacks.com/venturehacks"/>
                <outline title="Каждая сова днем выглядит глупо" text="Каждая сова днем выглядит глупо - LiveJournal.com" type="rss" xmlUrl="http://the-owls1.livejournal.com/data/rss"/>
                <outline title="‫אנדרואיד באז שיווק ופרסום‬" text="‫Just another iAndroid - הפורטל הישראלי לפלטפורמת אנדרואיד‬" type="rss" xmlUrl="http://iandroid.co.il/android-marketing/feed"/>
                <outline title="ן להתעדכן גם כן" type="rss" xmlUrl="http://feeds.feedburner.com/ipod-hebrew"/>
                <outline title="רוכבים את ישראל" text="" type="rss" xmlUrl="http://ridingisrael.blogspot.com/feeds/posts/default"/>
                <outline title="Papa HuHu" text="Papa HuHu - LiveJournal.com" type="rss" xmlUrl="http://papahuhu.livejournal.com/data/rss"/>
                <outline title="A Gamer!" text="Gamer" type="rss" xmlUrl="http://marmamic.tumblr.com/rss"/>
                <outline title="The Django weblog" text="Latest news about Django" type="rss" xmlUrl="http://www.djangoproject.com/rss/weblog/"/>
                <outline title="Matt Hartzell's China Blog" text="" type="rss" xmlUrl="http://matthartzell.blogspot.com/feeds/posts/default?alt=rss"/>
                <outline title="Significant Bits" text="On videogame design and such." type="rss" xmlUrl="http://feeds.feedburner.com/SignificantBits"/>
                <outline title="Taiwan In Cycles" text="" type="rss" xmlUrl="http://taiwanincycles.blogspot.com/feeds/posts/default?alt=rss"/>
                <outline title="Synapticism" text="An experiential journal of synchronicity and connection." type="rss" xmlUrl="http://synapticism.com/feed/"/>
                <outline title="Feld Thoughts" text="" type="rss" xmlUrl="http://feeds.feedburner.com/FeldThoughts"/>
                <outline title="gil ben-artzy" text="Thoughts, observations and random musings..." type="rss" xmlUrl="http://gilbenartzy.com/feed/"/>
                <outline title="xkcd.com" text="" type="rss" xmlUrl="http://xkcd.com/atom.xml"/>
                <outline title="Any.DO Tech Blog" text="In search for a better way to make things happen" type="rss" xmlUrl="http://tech.any.do/feed/"/>
                <outline title="The Stack" text="A completist plays old games" type="rss" xmlUrl="http://www.wurb.com/stack/feed"/>
                <outline title="מה יש לאכול" text="החיים, מתכונים ומה שבינהם" type="rss" xmlUrl="http://www.tals-cooking.com/?feed=rss2"/>
                <outline title="Significant Bits" text="On videogame design and such." type="rss" xmlUrl="http://feeds.feedburner.com/SignificantBits"/>
                <outline title="Eric Sink" text="SourceGear Founder" type="rss" xmlUrl="http://www.ericsink.com/rss.xml"/>
                <outline title="HackMii" text="Notes from inside your Wii" type="rss" xmlUrl="http://hackmii.com/feed/"/>
                <outline title="User Agent Man" text="A Blog about Client Side Web Technology" type="rss" xmlUrl="http://www.useragentman.com/blog/feed/"/>
                <outline title="Valve" text="Valve Software Blogs" type="rss" xmlUrl="http://blogs.valvesoftware.com/feed/"/>
                <outline title="0 and 1" text="The Ugly Website" type="rss" xmlUrl="http://oandone.blogspot.com/feeds/posts/default?alt=rss"/>
                <outline title="M86 Security Labs Blog" text="M86 Security Labs blog for all news related to security." type="rss" xmlUrl="http://labs.m86security.com/feed/"/>
                <outline title="Mozilla Web Development" text="For make benefit of glorious tubes" type="rss" xmlUrl="http://blog.mozilla.org/webdev/feed/"/>
                <outline title="Sea of Memes" text="Let's Code... an MMO!" type="rss" xmlUrl="http://www.sea-of-memes.com/rss.xml"/>
                <outline title="The Word of Notch" text="Rarely updated rambling, ranting, and informing." type="rss" xmlUrl="http://notch.tumblr.com/rss"/>
                <outline title="Toolness" text="The Blog of Atul Varma" type="rss" xmlUrl="http://www.toolness.com/wp/?feed=rss2"/>
                <outline title="Toolness" text="The Blog of Atul Varma" type="rss" xmlUrl="http://www.toolness.com/wp/feed/"/>
                <outline title="Tynan" text="My name is Tynan" type="rss" xmlUrl="http://feeds.feedburner.com/tynan"/>
                <outline title="udinic" text="Geeky adventures...and more..." type="rss" xmlUrl="http://udinic.wordpress.com/feed/"/>
                <outline title="What If?" text="Answering your hypothetical questions with physics, every Tuesday." type="rss" xmlUrl="http://what-if.xkcd.com/feed.atom"/>
                <outline title="wtfjs" text="wtfjs" type="rss" xmlUrl="http://wtfjs.com/rss/"/>
                <outline title="xkcd" text="The blag of the webcomic" type="rss" xmlUrl="http://blag.xkcd.com/feed/"/>
                <outline title="Zovirl Industries" text="Mark Ivey's blog" type="rss" xmlUrl="http://zovirl.com/feed/"/>
                <outline title="‫בצק אלים‬" text="‫רשימות ממטבחה של מעצבת‬" type="rss" xmlUrl="http://feeds.feedburner.com/bazekalim"/>
            </outline>
        </body>
    </opml>
    "#;

    let res = opml::parse_opml(opml_string, false, &Client::new()).await.unwrap();

    assert_eq!(res.categories.len(), 1);
    assert_eq!(res.feeds.len(), 106);
    assert_eq!(res.feed_mappings.len(), res.feeds.len());
    assert_eq!(res.categories.get(0).unwrap().label, "Subscriptions");
    assert_eq!(res.feeds.get(8).unwrap().label, "AVC");
}

#[tokio::test(basic_scheduler)]
async fn opml_import_3() {
    let opml_string = r#"<?xml version="1.0" encoding="UTF-8"?>
    <opml version="2.0">
        <body>
            <outline text="FOSS">
                <outline title="freedesktop.org" text="freedesktop.org" xmlUrl="https://planet.freedesktop.org/rss20.xml" htmlUrl="http://planet.freedesktop.org"></outline>
                <outline title="elementary" text="elementary" xmlUrl="https://blog.elementary.io/feed.xml" htmlUrl="http://blog.elementary.io/"></outline>
                <outline title="GIMP" text="GIMP" xmlUrl="https://www.gimp.org/feeds/rss.xml" htmlUrl="https://www.gimp.org/"></outline>
                <outline title="GTK+ Dev" text="GTK+ Dev" xmlUrl="https://blog.gtk.org/feed/" htmlUrl="https://blog.gtk.org"></outline>
                <outline title="heise Open" text="heise Open" xmlUrl="https://www.heise.de/thema/Linux-und-Open-Source?view=atom" htmlUrl="https://www.heise.de/thema/Linux-und-Open-Source?view=atom"></outline>
                <outline title="Kodi" text="Kodi" xmlUrl="https://kodi.tv/feed" htmlUrl="https://kodi.tv/blog"></outline>
                <outline title="LibreELEC" text="LibreELEC" xmlUrl="https://libreelec.tv/feed/" htmlUrl="https://libreelec.tv"></outline>
                <outline title="LWN.net" text="LWN.net" xmlUrl="https://lwn.net/headlines/newrss" htmlUrl="https://lwn.net"></outline>
                <outline title="OMG! Ubuntu!" text="OMG! Ubuntu!" xmlUrl="http://feeds.feedburner.com/d0od" htmlUrl="https://www.omgubuntu.co.uk"></outline>
                <outline title="PCSX2" text="PCSX2" xmlUrl="https://pcsx2.net/?format=feed&amp;type=rss" htmlUrl="https://pcsx2.net/"></outline>
                <outline title="Phoronix" text="Phoronix" xmlUrl="https://www.phoronix.com/rss.php" htmlUrl="https://www.phoronix.com/"></outline>
                <outline title="Planet GNOME" text="Planet GNOME" xmlUrl="https://planet.gnome.org/rss20.xml" htmlUrl="http://planet.gnome.org/"></outline>
                <outline title="Planet KDE" text="Planet KDE" xmlUrl="http://planetkde.org/rss20.xml" htmlUrl="http://planetKDE.org/"></outline>
                <outline title="Planet Vala" text="Planet Vala" xmlUrl="http://planet.vala-project.org/atom.xml" htmlUrl="http://planet.vala-project.org/"></outline>
                <outline title="Planet WebKitGTK+" text="Planet WebKitGTK+" xmlUrl="https://planet.webkitgtk.org/rss20.xml" htmlUrl="https://planet.webkitgtk.org/"></outline>
                <outline title="Pro-Linux" text="Pro-Linux" xmlUrl="https://www.pro-linux.de/rss/index2.xml" htmlUrl="https://www.pro-linux.de"></outline>
                <outline title="soeren-hentzschel.at" text="soeren-hentzschel.at" xmlUrl="https://www.soeren-hentzschel.at/feed/" htmlUrl="https://www.soeren-hentzschel.at"></outline>
                <outline title="WebUpd8" text="WebUpd8" xmlUrl="http://feeds2.feedburner.com/webupd8" htmlUrl="http://www.webupd8.org/"></outline>
            </outline>
            <outline text="Hardware">
                <outline title="AnandTech" text="AnandTech" xmlUrl="https://www.anandtech.com/rss/" htmlUrl="http://www.anandtech.com"></outline>
                <outline title="areamobile" text="areamobile" xmlUrl="https://www.areamobile.de/feed.cfm?menu_alias=home/" htmlUrl="http://www.areamobile.de/"></outline>
                <outline title="Hardwareluxx" text="Hardwareluxx" xmlUrl="https://www.hardwareluxx.de/index.php/component/obrss/hardwareluxx-rss-feed.feed" htmlUrl="https://www.hardwareluxx.de/"></outline>
                <outline title="Planet 3DNow!" text="Planet 3DNow!" xmlUrl="http://www.planet3dnow.de/cms/feed/" htmlUrl="https://www.planet3dnow.de/cms"></outline>
                <outline title="vrzone" text="vrzone" xmlUrl="https://vrzone.com/feed" htmlUrl="http://vrzone.com"></outline>
            </outline>
            <outline text="Podcasts">
                <outline title="Besser als Sex" text="Besser als Sex" xmlUrl="http://feeds.soundcloud.com/users/soundcloud:users:368209919/sounds.rss" htmlUrl="http://soundcloud.com/besseralssex"></outline>
                <outline title="New Rustacean" text="New Rustacean" xmlUrl="https://newrustacean.com/feed.xml" htmlUrl="http://newrustacean.com"></outline>
                <outline title="Quarks &amp; Co" text="Quarks &amp; Co" xmlUrl="https://www1.wdr.de/mediathek/video/podcast/channel-quarks-und-co-100.podcast" htmlUrl="https://www1.wdr.de/mediathek/video/podcast/channel-quarks-und-co-100.html"></outline>
            </outline>
            <outline text="CG">
                <outline title="Blender Dev" text="Blender Dev" xmlUrl="https://code.blender.org/feed/" htmlUrl="https://code.blender.org"></outline>
                <outline title="BlenderNation" text="BlenderNation" xmlUrl="http://feeds.feedburner.com/Blendernation" htmlUrl="https://www.blendernation.com"></outline>
            </outline>
            <outline text="General IT">
                <outline title="ComputerBase" text="ComputerBase" xmlUrl="https://www.computerbase.de/rss/news.xml" htmlUrl="https://www.computerbase.de/"></outline>
                <outline title="ComputerBase Tests" text="ComputerBase Tests" xmlUrl="https://www.computerbase.de/rss/artikel.xml" htmlUrl="https://www.computerbase.de/tests/"></outline>
                <outline title="Golem.de" text="Golem.de" xmlUrl="http://rss.golem.de/rss.php?feed=RSS1.0" htmlUrl="http://rss.golem.de/rss.php?feed=RSS1.0"></outline>
                <outline title="heise" text="heise" xmlUrl="https://www.heise.de/rss/heise-atom.xml" htmlUrl="https://www.heise.de/newsticker/"></outline>
                <outline title="SoftMaker Office" text="SoftMaker Office" xmlUrl="https://www.softmaker.de/blog/softmaker-office?format=feed&amp;type=atom" htmlUrl="https://www.softmaker.de"></outline>
            </outline>
            <outline text="Entertainment">
                <outline title="filmstarts.de" text="filmstarts.de" xmlUrl="http://rss.filmstarts.de/fs/news/filmnachrichten?format=xml" htmlUrl="http://www.filmstarts.de"></outline>
                <outline title="Movie Trailers" text="Movie Trailers" xmlUrl="https://trailers.apple.com/trailers/home/rss/newtrailers.rss" htmlUrl="http://www.apple.com/trailers/"></outline>
                <outline title="Serienjunkies" text="Serienjunkies" xmlUrl="http://feeds.feedburner.com/sj?format=xml" htmlUrl="https://www.serienjunkies.de/news/"></outline>
            </outline>
            <outline text="Games">
                <outline title="GamingOnLinux" text="GamingOnLinux" xmlUrl="https://www.gamingonlinux.com/article_rss.php" htmlUrl="https://www.gamingonlinux.com/"></outline>
                <outline title="SC2Casts" text="SC2Casts" xmlUrl="http://sc2casts.com/rss" htmlUrl="http://sc2casts.com"></outline>
                <outline title="Supertuxkart" text="Supertuxkart" xmlUrl="http://blog.supertuxkart.net/feeds/posts/default" htmlUrl="http://blog.supertuxkart.net/"></outline>
                <outline title="TeamLiquid.net" text="TeamLiquid.net" xmlUrl="https://tl.net/rss/news.xml" htmlUrl="http://www.teamliquid.net/"></outline>
            </outline>
            <outline text="News">
                <outline title="SPIEGEL" text="SPIEGEL" xmlUrl="https://www.spiegel.de/schlagzeilen/tops/index.rss" htmlUrl="http://www.spiegel.de"></outline>
                <outline title="Sueddeutsche" text="Sueddeutsche" xmlUrl="https://rss.sueddeutsche.de/rss/Topthemen" htmlUrl="http://www.sueddeutsche.de"></outline>
            </outline>
        </body>
    </opml>
    "#;

    let res = opml::parse_opml(opml_string, false, &Client::new()).await.unwrap();

    assert_eq!(res.categories.len(), 8);
    assert_eq!(res.feeds.len(), 42);
    assert_eq!(res.feed_mappings.len(), res.feeds.len());
    assert_eq!(res.categories.get(2).unwrap().label, "Podcasts");
    assert_eq!(res.feeds.get(6).unwrap().label, "LibreELEC");
}

#[tokio::test(basic_scheduler)]
async fn opml_import_no_title_no_html_url() {
    let opml_string = r#"<?xml version="1.0" encoding="UTF-8"?>
    <opml version="1.0">
        <head>
            <title>Sample OPML</title>
        </head>
        <body>
            <outline text="Some Category">
                <outline type="rss" xmlUrl="http://rss.computerworld.com.br/c/32184/f/499638/index.rss"/>
            </outline>
        </body>
    </opml>
    "#;

    let res = opml::parse_opml(opml_string, false, &Client::new()).await.unwrap();

    assert_eq!(res.categories.len(), 1);
    assert_eq!(res.feeds.len(), 1);
    assert_eq!(res.feed_mappings.len(), res.feeds.len());
    assert_eq!(res.categories.get(0).unwrap().label, "Some Category");
    assert_eq!(res.feeds.get(0).unwrap().label, "No Title");
    assert_eq!(res.feeds.get(0).unwrap().website, None);
}