public List <HNPost> GetPostsData(int numberOfPosts) { HtmlDocument doc = _htmlRetriever.GetHtmlDocument(); //Searching for a <tr> with a class name 'athing' string nodeQueryString = "//tr[@class='" + _HNPostClassName + "']"; //Creates list of the <tr> elements that contains the rank, title and Url of Posts HtmlNodeCollection postTitleRows = doc.DocumentNode.SelectNodes(nodeQueryString); for (int i = 0; i < numberOfPosts; i++) { HNPost post = new HNPost(); //<td> elements within the title <tr> element for the rank and title HtmlNode postTitleCell = postTitleRows[i].ChildNodes[4]; HtmlNode postRankCell = postTitleRows[i].ChildNodes[1]; post.Title = postTitleCell.InnerText; post.Rank = int.Parse(postRankCell.FirstChild.InnerText.TrimEnd(new char[] { '.' })); //<a> element within the title <td> element for the Url post.Uri = postTitleCell.ChildNodes[0].Attributes.AttributesWithName("href").ToList()[0].Value; if (post.Rank != i + 1) { throw new HtmlWebException("Post rank does not match post order"); } // Subtext <tr> element after the title <tr> that contains the author, points and comments HtmlNode postSubtextRow = postTitleRows[i].NextSibling; //<td> subtext element within subtext <tr> HtmlNode postSubtextCell = postSubtextRow.ChildNodes[1]; post.Points = int.Parse(postSubtextCell.ChildNodes[1].InnerText.Split(" ")[0]); post.Author = postSubtextCell.ChildNodes[3].InnerText; int comments; if (int.TryParse(postSubtextCell.ChildNodes[11].InnerText.Split(" ")[0], out comments)) { post.Comments = comments; } //If there are no comments else if (postSubtextCell.ChildNodes[11].InnerText == "discuss") { post.Comments = 0; } _HNPosts.Add(post); } ValidateHNPostList(_HNPosts); return(_HNPosts); }
public void RankCannotBeNegative() { // ARRANGE: create a post with minus Rank var post = new HNPost { Rank = -1 }; var validator = new HNPostValidator(HNPage.BASE_URI); // ACT: run the validator on the post validator.ValidatePost(post); // ASSERT: the post should contain a validation error Assert.NotNull(post.ValidationErrors); Assert.True(post.ValidationErrors.Where(e => e.MemberNames.Contains("Rank")).Any()); }
public void UriIsAValidUri() { // ARRANGE: create a post with invalid Uri var post = new HNPost { Uri = "httppp:/notvalid" }; var validator = new HNPostValidator(HNPage.BASE_URI); // ACT: run the validator on the post validator.ValidatePost(post); // ASSERT: the post should contain a validation error Assert.NotNull(post.ValidationErrors); Assert.True(post.ValidationErrors.Where(e => e.MemberNames.Contains("Uri")).Any()); }
public void AuthorCannotBeEmptyString() { // ARRANGE: create a post with empty string author var post = new HNPost { Author = "" }; var validator = new HNPostValidator(HNPage.BASE_URI); // ACT: run the validator on the post validator.ValidatePost(post); // ASSERT: the post should contain a validation error Assert.NotNull(post.ValidationErrors); Assert.True(post.ValidationErrors.Where(e => e.MemberNames.Contains("Author")).Any()); }
public void TitleCannotBeOver256Chars() { // ARRANGE: create a post with Title 257 chars long var post = new HNPost { Title = new string('a', 257) }; var validator = new HNPostValidator(HNPage.BASE_URI); // ACT: run the validator on the post validator.ValidatePost(post); // ASSERT: the post should contain a validation error Assert.NotNull(post.ValidationErrors); Assert.True(post.ValidationErrors.Where(e => e.MemberNames.Contains("Title")).Any()); }