Adding SpecFlow bindings for integration testing user's permissions

Enables automated testing of urls and redirects with querystring
Adds bindings for:
-Creating account with a fixed set of permissions
-Login of a user
-Success criteria for seeing text on a page
-Success criteria for being denied access to a page

--HG--
branch : dev
extra : rebase_source : 66e7b33cf7a596050d27eda6351605ed86420af2
This commit is contained in:
Louis DeJardin
2010-12-14 17:50:47 -08:00
parent c56c5b7777
commit 06868e412a
8 changed files with 259 additions and 42 deletions

View File

@@ -15,41 +15,6 @@ namespace Orchard.Specs.Bindings {
[Binding]
public class ContentRights : BindingBase {
[When(@"I have a role ""(.*)\"" with permissions ""(.*)\""")]
public void WhenIHaveARoleWithPermissions(string roleName, string permissions) {
var webApp = Binding<WebAppHosting>();
webApp.Host.Execute(() => {
using ( var environment = MvcApplication.CreateStandaloneEnvironment("Default") ) {
var roleService = environment.Resolve<IRoleService>();
roleService.CreateRole(roleName);
foreach ( var permissionName in permissions.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) ) {
roleService.CreatePermissionForRole(roleName, permissionName);
}
}
});
}
[When(@"I have a user ""(.*)\"" with roles ""(.*)\""")]
public void GivenIHaveCreatedAUser(string username, string roles) {
var webApp = Binding<WebAppHosting>();
webApp.Host.Execute(() => {
using ( var environment = MvcApplication.CreateStandaloneEnvironment("Default") ) {
var memberShipService = environment.Resolve<IMembershipService>();
var roleService = environment.Resolve<IRoleService>();
var userRoleRepository = environment.Resolve<IRepository<UserRolesPartRecord>>();
var user = memberShipService.CreateUser(new CreateUserParams(username, "qwerty123!", username + "@foo.com", "", "", true));
foreach ( var roleName in roles.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) ) {
var role = roleService.GetRoleByName(roleName);
userRoleRepository.Create(new UserRolesPartRecord { UserId = user.Id, Role = role });
}
}
});
}
[Then(@"""(.*)\"" should be able to ""(.*)\"" a ""(.*)\"" owned by ""(.*)\""")]
public void UserShouldBeAbleToForOthers(string username, string action, string contentType, string otherName) {

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.Data;
using Orchard.Roles.Models;
using Orchard.Roles.Services;
using Orchard.Security;
using Orchard.Specs.Hosting.Orchard.Web;
using TechTalk.SpecFlow;
namespace Orchard.Specs.Bindings {
[Binding]
public class UsersPermissionsAndRoles : BindingBase {
[When(@"I have a role ""(.*)\"" with permissions ""(.*)\""")]
public void WhenIHaveARoleWithPermissions(string roleName, string permissions) {
var webApp = Binding<WebAppHosting>();
webApp.Host.Execute(() => {
using (var environment = MvcApplication.CreateStandaloneEnvironment("Default")) {
var roleService = environment.Resolve<IRoleService>();
roleService.CreateRole(roleName);
foreach (var permissionName in permissions.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)) {
roleService.CreatePermissionForRole(roleName, permissionName);
}
}
});
}
[When(@"I have a user ""(.*)\"" with roles ""(.*)\""")]
public void GivenIHaveCreatedAUser(string username, string roles) {
var webApp = Binding<WebAppHosting>();
webApp.Host.Execute(() => {
using (var environment = MvcApplication.CreateStandaloneEnvironment("Default")) {
var memberShipService = environment.Resolve<IMembershipService>();
var roleService = environment.Resolve<IRoleService>();
var userRoleRepository = environment.Resolve<IRepository<UserRolesPartRecord>>();
var user = memberShipService.CreateUser(new CreateUserParams(username, "qwerty123!", username + "@foo.com", "", "", true));
foreach (var roleName in roles.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)) {
var role = roleService.GetRoleByName(roleName);
userRoleRepository.Create(new UserRolesPartRecord { UserId = user.Id, Role = role });
}
}
});
}
[Given(@"I have a user ""(.*)"" with permissions ""(.*)""")]
public void GivenIHaveAUserWithPermissions(string username, string permissions) {
var roleName = Guid.NewGuid().ToString("n");
WhenIHaveARoleWithPermissions(roleName, permissions);
GivenIHaveCreatedAUser(username, roleName);
}
[When(@"I sign in as ""(.*)""")]
public void WhenISignInAs(string username) {
var webApp = Binding<WebAppHosting>();
var logonForm = TableData(
new { name = "userNameOrEmail", value = username },
new { name = "password", value = "qwerty123!" });
webApp.WhenIGoTo("/users/account/logoff");
webApp.WhenIGoTo("/users/account/logon");
webApp.WhenIFillIn(logonForm);
webApp.WhenIHit("Sign In");
webApp.WhenIAmRedirected();
}
}
}

View File

@@ -294,20 +294,34 @@ namespace Orchard.Specs.Bindings {
Assert.That(Details.ResponseHeaders["Content-Type"], Is.StringMatching(contentType));
}
[Then(@"I should see ""(.*)""")]
[Then(@"I should see ""([^""]*)""")]
public void ThenIShouldSee(string text) {
Assert.That(Details.ResponseText, Is.StringMatching(text));
}
[Then(@"I should not see ""(.*)""")]
[Then(@"I should not see ""([^""]*)""")]
public void ThenIShouldNotSee(string text) {
Assert.That(Details.ResponseText, Is.Not.StringContaining(text));
}
[Then(@"the title contains ""(.*)""")]
[Then(@"the title contains ""([^""]*)""")]
public void ThenTheTitleContainsText(string text) {
ScenarioContext.Current.Pending();
}
[Then(@"I should see ""([^""]*)"" when I go to ""([^""]*)""")]
public void ThenIShouldSeeWhenIGoTo(string text, string urlPath) {
WhenIGoTo(urlPath);
ThenIShouldSee(text);
}
[Then(@"I should be denied access when I go to ""([^""]*)""")]
public void ThenIShouldBeDeniedAccessWhenIGoTo(string urlPath) {
WhenIGoTo(urlPath);
WhenIAmRedirected();
ThenIShouldSee("Access Denied");
}
}
public class Form {

View File

@@ -23,9 +23,15 @@ namespace Orchard.Specs.Hosting {
var details = new RequestDetails {
HostName = webHost.HostName,
UrlPath = urlPath,
Page = (isHomepage ? "" : physicalPath.Combine(urlPath.TrimStart('/', '\\')).GetRelativePath(physicalPath).ToString())
};
int queryIndex = urlPath.IndexOf('?');
if (queryIndex >= 0) {
details.UrlPath = urlPath.Substring(0, queryIndex);
details.Query = HttpUtility.UrlDecode(urlPath.Substring(queryIndex + 1));
}
details.Page = (isHomepage ? "" : physicalPath.Combine(details.UrlPath.TrimStart('/', '\\')).GetRelativePath(physicalPath).ToString());
if (!string.IsNullOrEmpty(webHost.Cookies)) {
details.RequestHeaders.Add("Cookie", webHost.Cookies);
}
@@ -123,7 +129,7 @@ namespace Orchard.Specs.Hosting {
if (_details.RequestHeaders.TryGetValue("Cookie", out value))
return value;
}
else if (index==HeaderHost) {
else if (index == HeaderHost) {
return _details.HostName;
}
return base.GetKnownRequestHeader(index);

View File

@@ -132,6 +132,7 @@
<Compile Include="Bindings\CommandLine.cs" />
<Compile Include="Bindings\ContentRights.cs" />
<Compile Include="Bindings\OrchardSiteFactory.cs" />
<Compile Include="Bindings\UsersPermissionsAndRoles.cs" />
<Compile Include="Blogs.feature.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@@ -180,6 +181,11 @@
<DesignTime>True</DesignTime>
<DependentUpon>Pages.feature</DependentUpon>
</Compile>
<Compile Include="PermissionModel.feature.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>PermissionModel.feature</DependentUpon>
</Compile>
<Compile Include="Setup.feature.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@@ -249,6 +255,10 @@
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>ContentTypes.feature.cs</LastGenOutput>
</None>
<None Include="PermissionModel.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>PermissionModel.feature.cs</LastGenOutput>
</None>
<Content Include="Hosting\TemplateConfigs\DisableDynamicCompilation.HostComponents.config">
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

View File

@@ -0,0 +1,27 @@
Feature: Addition
In order to prevent security model regressions
As a user with specific permissions
I should to be granted or denied access to various actions
@security
Scenario: Login can be automated
Given I have installed Orchard
And I have a user "bob" with permissions "AccessFrontEnd"
When I go to "users/account/logoff"
And I go to "users/account/logon"
And I fill in
| name | value |
| userNameOrEmail | bob |
| password | qwerty123! |
And I hit "Sign In"
And I am redirected
Then I should see "Welcome, <strong>bob</strong>!"
@security
Scenario: Anonymous user can see the home page but not the dashboard
Given I have installed Orchard
And I have a user "bob" with permissions "AccessFrontEnd"
When I sign in as "bob"
Then I should see "this is the homepage of your new site" when I go to "/"
And I should be denied access when I go to "admin"

View File

@@ -0,0 +1,119 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by SpecFlow (http://www.specflow.org/).
// SpecFlow Version:1.4.0.0
// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
#region Designer generated code
namespace Orchard.Specs
{
using TechTalk.SpecFlow;
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.4.0.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Addition")]
public partial class AdditionFeature
{
private static TechTalk.SpecFlow.ITestRunner testRunner;
#line 1 "PermissionModel.feature"
#line hidden
[NUnit.Framework.TestFixtureSetUpAttribute()]
public virtual void FeatureSetup()
{
testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Addition", "In order to prevent security model regressions\nAs a user with specific permission" +
"s\nI should to be granted or denied access to various actions", GenerationTargetLanguage.CSharp, ((string[])(null)));
testRunner.OnFeatureStart(featureInfo);
}
[NUnit.Framework.TestFixtureTearDownAttribute()]
public virtual void FeatureTearDown()
{
testRunner.OnFeatureEnd();
testRunner = null;
}
public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
{
testRunner.OnScenarioStart(scenarioInfo);
}
[NUnit.Framework.TearDownAttribute()]
public virtual void ScenarioTearDown()
{
testRunner.OnScenarioEnd();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("Login can be automated")]
[NUnit.Framework.CategoryAttribute("security")]
public virtual void LoginCanBeAutomated()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Login can be automated", new string[] {
"security"});
#line 7
this.ScenarioSetup(scenarioInfo);
#line 8
testRunner.Given("I have installed Orchard");
#line 9
testRunner.And("I have a user \"bob\" with permissions \"AccessFrontEnd\"");
#line 10
testRunner.When("I go to \"users/account/logoff\"");
#line 11
testRunner.And("I go to \"users/account/logon\"");
#line hidden
TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
"name",
"value"});
table1.AddRow(new string[] {
"userNameOrEmail",
"bob"});
table1.AddRow(new string[] {
"password",
"qwerty123!"});
#line 12
testRunner.And("I fill in", ((string)(null)), table1);
#line 16
testRunner.And("I hit \"Sign In\"");
#line 17
testRunner.And("I am redirected");
#line 18
testRunner.Then("I should see \"Welcome, <strong>bob</strong>!\"");
#line hidden
testRunner.CollectScenarioErrors();
}
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("Anonymous user can see the home page but not the dashboard")]
[NUnit.Framework.CategoryAttribute("security")]
public virtual void AnonymousUserCanSeeTheHomePageButNotTheDashboard()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Anonymous user can see the home page but not the dashboard", new string[] {
"security"});
#line 21
this.ScenarioSetup(scenarioInfo);
#line 22
testRunner.Given("I have installed Orchard");
#line 23
testRunner.And("I have a user \"bob\" with permissions \"AccessFrontEnd\"");
#line 24
testRunner.When("I sign in as \"bob\"");
#line 25
testRunner.Then("I should see \"this is the homepage of your new site\" when I go to \"/\"");
#line 26
testRunner.And("I should be denied access when I go to \"admin\"");
#line hidden
testRunner.CollectScenarioErrors();
}
}
}
#endregion

View File

@@ -102,6 +102,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Scripting.Dlr", "Or
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Scripting", "Orchard.Web\Modules\Orchard.Scripting\Orchard.Scripting.csproj", "{99002B65-86F7-415E-BF4A-381AA8AB9CCC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{3E10BF6D-ADA5-417D-B36C-EBB0660B475E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeCoverage|Any CPU = CodeCoverage|Any CPU
@@ -587,12 +589,12 @@ Global
{F112851D-B023-4746-B6B1-8D2E5AD8F7AA} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{6CB3EB30-F725-45C0-9742-42599BA8E8D2} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{2FC1D9C8-446D-4414-B252-5E9FBE61EB63} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{7354DF37-934B-46CF-A13C-455D5F5F5413} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{94E694A2-D140-468D-A277-C5FCE1D13E9B} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
{5E5E7A21-C7B2-44D8-8593-2F9541AE041D} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
{4AB4B5B6-277E-4FF6-B69B-7AE9E16D2A56} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
{33B1BC8D-E292-4972-A363-22056B207156} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
{0DFA2E10-96C8-4E05-BC10-B710B97ECCDE} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
{CB70A642-8CEC-4DDE-8C9F-AD08900EC98D} = {74492CBC-7201-417E-BC29-28B4C25A58B0}
{7354DF37-934B-46CF-A13C-455D5F5F5413} = {3E10BF6D-ADA5-417D-B36C-EBB0660B475E}
{94E694A2-D140-468D-A277-C5FCE1D13E9B} = {3E10BF6D-ADA5-417D-B36C-EBB0660B475E}
EndGlobalSection
EndGlobal