public async Task LoadOnlineFeed() {
            ITemplateSource source = new FeedTemplateSource(new Uri(OnlineFeedPath));

            var result = await source.GetTemplatesAsync(null, null, CancellationToken.None);

            Assert.IsNull(result.ContinuationToken);
            Assert.IsTrue(result.Templates.Count > 0);
            Assert.IsFalse(string.IsNullOrEmpty(result.Templates[0].Name));
            Assert.IsFalse(string.IsNullOrEmpty(result.Templates[0].RemoteUrl));
        }
        public async Task SearchFeedSingleTerm()
        {
            ITemplateSource source = new FeedTemplateSource(new Uri(LocalFeedPath));

            var result = await source.GetTemplatesAsync("azure", null, CancellationToken.None);

            Assert.IsNull(result.ContinuationToken);
            Assert.AreEqual(1, result.Templates.Count);
            Assert.AreEqual("brettcannon/python-azure-web-app-cookiecutter", result.Templates[0].Name);
        }
        public async Task LoadOnlineFeed()
        {
            ITemplateSource source = new FeedTemplateSource(new Uri(OnlineFeedPath));

            var result = await source.GetTemplatesAsync(null, null, CancellationToken.None);

            Assert.IsNull(result.ContinuationToken);
            Assert.IsTrue(result.Templates.Count > 0);
            Assert.IsFalse(string.IsNullOrEmpty(result.Templates[0].Name));
            Assert.IsFalse(string.IsNullOrEmpty(result.Templates[0].RemoteUrl));
        }
        public async Task SearchFeedMultipleTerms()
        {
            ITemplateSource source = new FeedTemplateSource(new Uri(LocalFeedPath));

            var result = await source.GetTemplatesAsync("flask,azure", null, CancellationToken.None);

            Assert.IsNull(result.ContinuationToken);
            Assert.AreEqual(2, result.Templates.Count);
            Assert.IsNotNull(result.Templates.SingleOrDefault(t => t.Name == "brettcannon/python-azure-web-app-cookiecutter"));
            Assert.IsNotNull(result.Templates.SingleOrDefault(t => t.Name == "sloria/cookiecutter-flask"));
        }
        public async Task LoadNonExistentFeed()
        {
            ITemplateSource source = new FeedTemplateSource(new Uri(NonExistentFeedPath));

            try {
                var result = await source.GetTemplatesAsync(null, null, CancellationToken.None);

                Assert.Fail("Expected an TemplateEnumerationException when loading invalid feed.");
            } catch (TemplateEnumerationException) {
            }
        }
        public async Task LoadLocalFeed()
        {
            ITemplateSource source = new FeedTemplateSource(new Uri(LocalFeedPath));

            Assert.IsTrue(File.Exists(LocalFeedPath));

            var result = await source.GetTemplatesAsync(null, null, CancellationToken.None);

            Assert.IsNull(result.ContinuationToken);
            Assert.AreEqual(6, result.Templates.Count);

            Template[] expected = new Template[] {
                new Template()
                {
                    RemoteUrl = "https://github.com/brettcannon/python-azure-web-app-cookiecutter",
                    Name      = "brettcannon/python-azure-web-app-cookiecutter",
                },
                new Template()
                {
                    RemoteUrl = "https://github.com/pydanny/cookiecutter-django",
                    Name      = "pydanny/cookiecutter-django",
                },
                new Template()
                {
                    RemoteUrl = "https://github.com/sloria/cookiecutter-flask",
                    Name      = "sloria/cookiecutter-flask",
                },
                new Template()
                {
                    RemoteUrl = "https://github.com/pydanny/cookiecutter-djangopackage",
                    Name      = "pydanny/cookiecutter-djangopackage",
                },
                new Template()
                {
                    RemoteUrl = "https://github.com/marcofucci/cookiecutter-simple-django",
                    Name      = "marcofucci/cookiecutter-simple-django",
                },
                new Template()
                {
                    RemoteUrl = "https://github.com/agconti/cookiecutter-django-rest",
                    Name      = "agconti/cookiecutter-django-rest",
                },
            };

            CollectionAssert.AreEqual(expected, result.Templates.ToArray(), new TemplateComparer());
        }
        public async Task LoadLocalFeed() {
            ITemplateSource source = new FeedTemplateSource(new Uri(LocalFeedPath));
            Assert.IsTrue(File.Exists(LocalFeedPath));

            var result = await source.GetTemplatesAsync(null, null, CancellationToken.None);

            Assert.IsNull(result.ContinuationToken);
            Assert.AreEqual(6, result.Templates.Count);

            var expected = new Template[] {
                new Template() {
                    RemoteUrl = "https://github.com/brettcannon/python-azure-web-app-cookiecutter",
                    Name = "brettcannon/python-azure-web-app-cookiecutter",
                },
                new Template() {
                    RemoteUrl = "https://github.com/pydanny/cookiecutter-django",
                    Name = "pydanny/cookiecutter-django",
                },
                new Template() {
                    RemoteUrl = "https://github.com/sloria/cookiecutter-flask",
                    Name = "sloria/cookiecutter-flask",
                },
                new Template() {
                    RemoteUrl = "https://github.com/pydanny/cookiecutter-djangopackage",
                    Name = "pydanny/cookiecutter-djangopackage",
                },
                new Template() {
                    RemoteUrl = "https://github.com/marcofucci/cookiecutter-simple-django",
                    Name = "marcofucci/cookiecutter-simple-django",
                },
                new Template() {
                    RemoteUrl = "https://github.com/agconti/cookiecutter-django-rest",
                    Name = "agconti/cookiecutter-django-rest",
                },
            };

            CollectionAssert.AreEqual(expected, result.Templates.ToArray(), new TemplateComparer());
        }
        public async Task LoadNonExistentFeed() {
            ITemplateSource source = new FeedTemplateSource(new Uri(NonExistentFeedPath));

            try {
                var result = await source.GetTemplatesAsync(null, null, CancellationToken.None);
                Assert.Fail("Expected an TemplateEnumerationException when loading invalid feed.");
            } catch (TemplateEnumerationException) {
            }
        }
        public async Task SearchFeedMultipleTerms() {
            ITemplateSource source = new FeedTemplateSource(new Uri(LocalFeedPath));

            var result = await source.GetTemplatesAsync("flask,azure", null, CancellationToken.None);
            Assert.IsNull(result.ContinuationToken);
            Assert.AreEqual(2, result.Templates.Count);
            Assert.IsNotNull(result.Templates.SingleOrDefault(t => t.Name == "brettcannon/python-azure-web-app-cookiecutter"));
            Assert.IsNotNull(result.Templates.SingleOrDefault(t => t.Name == "sloria/cookiecutter-flask"));
        }
        public async Task SearchFeedSingleTerm() {
            ITemplateSource source = new FeedTemplateSource(new Uri(LocalFeedPath));

            var result = await source.GetTemplatesAsync("azure", null, CancellationToken.None);
            Assert.IsNull(result.ContinuationToken);
            Assert.AreEqual(1, result.Templates.Count);
            Assert.AreEqual("brettcannon/python-azure-web-app-cookiecutter", result.Templates[0].Name);
        }