Adding a specflow test for widgets (yeah, just one :|) and making some tweaks to the specflow capabilities to enable the flow required by that test...

--HG--
branch : 1.x
This commit is contained in:
Nathan Heskew
2011-04-07 15:58:30 -07:00
parent 8c336638b3
commit 62fa1da5f2
6 changed files with 115 additions and 16 deletions

View File

@@ -0,0 +1,11 @@
using HtmlAgilityPack;
namespace Orchard.Specs.Bindings {
public static class HtmlNodeExtensions {
public static string GetOptionValue(this HtmlNode node) {
return node.Attributes.Contains("value")
? node.GetAttributeValue("value", "")
: node.NextSibling != null && node.NextSibling.NodeType == HtmlNodeType.Text ? node.NextSibling.InnerText : "";
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using Castle.Core.Logging;
using HtmlAgilityPack;
@@ -181,21 +182,21 @@ namespace Orchard.Specs.Bindings {
Host.HostName = host;
Details = Host.SendRequest(urlPath);
_doc = new HtmlDocument();
_doc.Load(new StringReader(Details.ResponseText));
_doc.Load(new StringReader(Regex.Replace(Details.ResponseText, @">\s+<", "><")));
}
[When(@"I go to ""(.*)""")]
public void WhenIGoTo(string urlPath) {
Details = Host.SendRequest(urlPath);
_doc = new HtmlDocument();
_doc.Load(new StringReader(Details.ResponseText));
_doc.Load(new StringReader(Regex.Replace(Details.ResponseText, @">\s+<", "><")));
}
[When(@"I follow ""([^""]*)""")]
public void WhenIFollow(string linkText) {
var link = _doc.DocumentNode
.SelectNodes("//a")
.SingleOrDefault(elt => elt.InnerText == linkText)
.SingleOrDefault(elt => elt.InnerHtml == linkText)
?? _doc.DocumentNode
.SelectSingleNode(string.Format("//a[@title='{0}']", linkText));
@@ -208,7 +209,7 @@ namespace Orchard.Specs.Bindings {
public void WhenIFollow(string linkText, string hrefFilter) {
var link = _doc.DocumentNode
.SelectNodes("//a[@href]").Where(elt =>
(elt.InnerText == linkText ||
(elt.InnerHtml == linkText ||
(elt.Attributes["title"] != null && elt.Attributes["title"].Value == linkText)) &&
elt.Attributes["href"].Value.IndexOf(hrefFilter, StringComparison.OrdinalIgnoreCase) != -1).SingleOrDefault();
@@ -263,9 +264,9 @@ namespace Orchard.Specs.Bindings {
break;
default:
if (string.Equals(input.Name, "select", StringComparison.OrdinalIgnoreCase)) {
var options = input.ChildNodes;
var options = input.Descendants("option");
foreach (var option in options) {
if (option.GetAttributeValue("value", "") == row["value"])
if (option.GetAttributeValue("value", "") == row["value"] || (option.NextSibling.NodeType == HtmlNodeType.Text && option.NextSibling.InnerText == row["value"]))
option.Attributes.Add("selected", "selected");
else if (option.Attributes.Contains("selected"))
option.Attributes.Remove("selected");
@@ -286,7 +287,7 @@ namespace Orchard.Specs.Bindings {
.SelectSingleNode(string.Format("(//input[@type='submit'][@value='{0}']|//button[@type='submit'][text()='{0}'])", submitText));
var form = Form.LocateAround(submit);
var urlPath = form.Start.GetAttributeValue("action", Details.UrlPath);
var urlPath = HttpUtility.HtmlDecode(form.Start.GetAttributeValue("action", Details.UrlPath));
var inputs = form.Children
@@ -299,18 +300,18 @@ namespace Orchard.Specs.Bindings {
// select all <select> elements
form.Children.SelectMany(elt => elt.DescendantsAndSelf("select")).Where(elt => elt.Name.Equals("select", StringComparison.OrdinalIgnoreCase))
// group them by their name with value that comes from first of:
// (1) value of option with 'selected' attribute,
// (1) value of option with 'selecturlPath.Replace("127.0.0.1", "localhost")ed' attribute,
// (2) value of first option (none have 'selected'),
// (3) empty value (e.g. select with no options)
.GroupBy(
sel => sel.GetAttributeValue("name", sel.GetAttributeValue("id", "")),
sel => (sel.Descendants("option").SingleOrDefault(opt => opt.Attributes["selected"] != null) ?? sel.Descendants("option").FirstOrDefault() ?? new HtmlNode(HtmlNodeType.Element, _doc, 0)).GetAttributeValue("value", "")))
sel => (sel.Descendants("option").SingleOrDefault(opt => opt.Attributes["selected"] != null) ?? sel.Descendants("option").FirstOrDefault() ?? new HtmlNode(HtmlNodeType.Element, _doc, 0)).GetOptionValue()))
.ToDictionary(elt => elt.Key, elt => (IEnumerable<string>)elt);
if (submit.Attributes.Contains("name"))
inputs.Add(submit.GetAttributeValue("name", ""), new[] {submit.GetAttributeValue("value", "yes")});
Details = Host.SendRequest(urlPath, inputs);
Details = Host.SendRequest(urlPath, inputs, form.Start.GetAttributeValue("method", "GET").ToUpperInvariant());
_doc = new HtmlDocument();
_doc.Load(new StringReader(Details.ResponseText));
}
@@ -319,10 +320,10 @@ namespace Orchard.Specs.Bindings {
public void WhenIAmRedirected() {
var urlPath = "";
if (Details.ResponseHeaders.TryGetValue("Location", out urlPath)) {
WhenIGoTo(urlPath);
WhenIGoTo(urlPath.Replace("http://127.0.0.1/", ""));
}
else {
Assert.Fail("No Location header returned");
Assert.Fail("Expected to be redirected but no Location header returned");
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
@@ -11,7 +12,7 @@ using Orchard.Specs.Util;
namespace Orchard.Specs.Hosting {
public static class RequestExtensions {
public static RequestDetails SendRequest(this WebHost webHost, string urlPath, IDictionary<string, IEnumerable<string>> postData) {
public static RequestDetails SendRequest(this WebHost webHost, string urlPath, IDictionary<string, IEnumerable<string>> postData, string requestMethod = null) {
var physicalPath = Bleroy.FluentPath.Path.Get(webHost.PhysicalDirectory);
@@ -28,7 +29,7 @@ namespace Orchard.Specs.Hosting {
int queryIndex = urlPath.IndexOf('?');
if (queryIndex >= 0) {
details.UrlPath = urlPath.Substring(0, queryIndex);
details.Query = HttpUtility.UrlDecode(urlPath.Substring(queryIndex + 1));
details.Query = urlPath.Substring(queryIndex + 1);
}
details.Page = (isHomepage ? "" : physicalPath.Combine(details.UrlPath.TrimStart('/', '\\')).GetRelativePath(physicalPath).ToString());
@@ -41,7 +42,11 @@ namespace Orchard.Specs.Hosting {
.SelectMany(kv => kv.Value.Select(v => new { k = kv.Key, v }))
.Select((kv, n) => new { p = HttpUtility.UrlEncode(kv.k) + "=" + HttpUtility.UrlEncode(kv.v), n })
.Aggregate("", (a, x) => a + (x.n == 0 ? "" : "&") + x.p);
details.PostData = Encoding.Default.GetBytes(requestBodyText);
if (requestMethod == "POST")
details.PostData = Encoding.Default.GetBytes(requestBodyText);
else
details.Query = requestBodyText;
}
webHost.Execute(() => {

View File

@@ -131,6 +131,7 @@
<Compile Include="Bindings\BindingBase.cs" />
<Compile Include="Bindings\CommandLine.cs" />
<Compile Include="Bindings\ContentRights.cs" />
<Compile Include="Bindings\HtmlNodeExtensions.cs" />
<Compile Include="Bindings\OrchardSiteFactory.cs" />
<Compile Include="Bindings\UsersPermissionsAndRoles.cs" />
<Compile Include="Blogs.feature.cs">

View File

@@ -41,3 +41,25 @@ Scenario: I can delete a layer
And I am redirected
Then I should see "Layer was successfully deleted"
And I should not see "<option[^>]*>Default</option>"
Scenario: I can add a widget to a specific zone in a specific layer
Given I have installed Orchard
When I go to "admin/widgets"
And I fill in
| name | value |
| layerId | Disabled |
And I hit "Show"
Then I should see "<option[^>]*selected[^>]*>Disabled"
When I follow "Add" where href has "zone=Header"
Then I should see "<h1[^>]*>Choose A Widget</h1>"
When I follow "<h2>Html Widget</h2>"
Then I should see "<h1[^>]*>Add Widget</h1>"
When I fill in
| name | value |
| Title | Flashy HTML Widget |
| Body.Text | <p><blink>hi</blink></p> |
And I hit "Save"
And I am redirected
Then I should see "Your Html Widget has been added."
And I should see "<option[^>]*selected[^>]*>Disabled"
And I should see "<li[^>]*class="[^"]*widgets-this-layer[^"]*"[^>]*>\s*<form[^>]*>\s*<h3[^>]*>\s*<a[^>]*>Flashy HTML Widget</a>\s*</h3>"

View File

@@ -158,6 +158,65 @@ this.ScenarioSetup(scenarioInfo);
testRunner.Then("I should see \"Layer was successfully deleted\"");
#line 43
testRunner.And("I should not see \"<option[^>]*>Default</option>\"");
#line hidden
testRunner.CollectScenarioErrors();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("I can add a widget to a specific zone in a specific layer")]
public virtual void ICanAddAWidgetToASpecificZoneInASpecificLayer()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can add a widget to a specific zone in a specific layer", ((string[])(null)));
#line 45
this.ScenarioSetup(scenarioInfo);
#line 46
testRunner.Given("I have installed Orchard");
#line 47
testRunner.When("I go to \"admin/widgets\"");
#line hidden
TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table3.AddRow(new string[] {
"layerId",
"Disabled"});
#line 48
testRunner.And("I fill in", ((string)(null)), table3);
#line 51
testRunner.And("I hit \"Show\"");
#line 52
testRunner.Then("I should see \"<option[^>]*selected[^>]*>Disabled\"");
#line 53
testRunner.When("I follow \"Add\" where href has \"zone=Header\"");
#line 54
testRunner.Then("I should see \"<h1[^>]*>Choose A Widget</h1>\"");
#line 55
testRunner.When("I follow \"<h2>Html Widget</h2>\"");
#line 56
testRunner.Then("I should see \"<h1[^>]*>Add Widget</h1>\"");
#line hidden
TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table4.AddRow(new string[] {
"Title",
"Flashy HTML Widget"});
table4.AddRow(new string[] {
"Body.Text",
"<p><blink>hi</blink></p>"});
#line 57
testRunner.When("I fill in", ((string)(null)), table4);
#line 61
testRunner.And("I hit \"Save\"");
#line 62
testRunner.And("I am redirected");
#line 63
testRunner.Then("I should see \"Your Html Widget has been added.\"");
#line 64
testRunner.And("I should see \"<option[^>]*selected[^>]*>Disabled\"");
#line 65
testRunner.And("I should see \"<li[^>]*class=\"[^\"]*widgets-this-layer[^\"]*\"[^>]*>\\s*<form[^>]*>\\s*" +
"<h3[^>]*>\\s*<a[^>]*>Flashy HTML Widget</a>\\s*</h3>\"");
#line hidden
testRunner.CollectScenarioErrors();
}