mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 10:54:50 +08:00
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:
@@ -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) {
|
||||
|
||||
|
74
src/Orchard.Specs/Bindings/UsersPermissionsAndRoles.cs
Normal file
74
src/Orchard.Specs/Bindings/UsersPermissionsAndRoles.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
|
27
src/Orchard.Specs/PermissionModel.feature
Normal file
27
src/Orchard.Specs/PermissionModel.feature
Normal 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"
|
||||
|
119
src/Orchard.Specs/PermissionModel.feature.cs
generated
Normal file
119
src/Orchard.Specs/PermissionModel.feature.cs
generated
Normal 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
|
@@ -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
|
||||
|
Reference in New Issue
Block a user