From de53b28cddc8bebd50a36783beb1b5288bc71a14 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Mon, 5 Feb 2018 20:33:01 +0000 Subject: [PATCH 001/213] WIP #10 - Bulk removal of Screenplay Core & WebDriverFactory code This code is now part of other repositories, so it no longer needs to be here. --- .../Abilities/ConsumeJsonWebServices.cs | 66 -- .../Abilities/SynchronousJsonGateway.cs | 138 --- CSF.Screenplay.JsonApis/Actions/ExecuteApi.cs | 32 - .../Actions/GetApiResult.cs | 32 - CSF.Screenplay.JsonApis/Builders/Execute.cs | 14 - .../CSF.Screenplay.JsonApis.csproj | 65 -- .../CSF.Screenplay.JsonApis.nuspec | 25 - .../IProvidesInvocationDetails.cs | 12 - CSF.Screenplay.JsonApis/JsonApiException.cs | 43 - .../JsonServiceDescription.cs | 97 -- .../JsonServiceDescription`1.cs | 9 - .../Properties/AssemblyInfo.cs | 26 - CSF.Screenplay.JsonApis/packages.config | 4 - .../CSF.Screenplay.NUnit.csproj | 59 -- .../CSF.Screenplay.NUnit.nuspec | 23 - CSF.Screenplay.NUnit/IntegrationReader.cs | 70 -- .../Properties/AssemblyInfo.cs | 26 - CSF.Screenplay.NUnit/ScenarioAdapter.cs | 179 ---- .../ScreenplayAssemblyAttribute.cs | 55 -- CSF.Screenplay.NUnit/ScreenplayAttribute.cs | 102 -- CSF.Screenplay.NUnit/packages.config | 5 - .../CSF.Screenplay.Reporting.Html.csproj | 138 --- .../CSF.Screenplay.Reporting.Html.nuspec | 24 - .../HtmlReportWriter.cs | 50 - .../Models/ReportDocument.cs | 131 --- .../Properties/AssemblyInfo.cs | 26 - .../StreamSourceInfo.cs | 29 - .../Views/DocumentTemplate.pt | 875 ------------------ CSF.Screenplay.Reporting.Html/Views/Filter.js | 118 --- .../Views/Folding.js | 50 - .../Views/PageInteractions.js | 20 - .../Views/ViewProvider.cs | 18 - .../Views/interactions.css | 87 -- .../Views/jquery-3.2.1.slim.min.js | 4 - CSF.Screenplay.Reporting.Html/Views/page.css | 80 -- .../Views/report-interactions.js | 12 - .../Views/reports.css | 146 --- CSF.Screenplay.Reporting.Html/Views/reset.css | 48 - CSF.Screenplay.Reporting.Html/app.config | 46 - CSF.Screenplay.Reporting.Html/packages.config | 18 - .../Builders/PerformanceBuilder.cs | 104 --- .../Builders/ReportBuilder.cs | 172 ---- .../Builders/ScenarioBuilder.cs | 206 ----- .../CSF.Screenplay.Reporting.csproj | 102 -- .../CSF.Screenplay.Reporting.nuspec | 23 - .../CastReportingHelper.cs | 92 -- .../IModelBuildingReporter.cs | 17 - .../IObjectFormatterRegistry.cs | 23 - .../IObjectFormattingService.cs | 15 - CSF.Screenplay.Reporting/IReportWriter.cs | 17 - CSF.Screenplay.Reporting/IReporter.cs | 50 - CSF.Screenplay.Reporting/Models/Feature.cs | 58 -- .../Models/GainAbility.cs | 39 - .../Models/IReportFactory.cs | 17 - .../Models/Performance.cs | 96 -- .../Models/PerformanceOutcome.cs | 29 - .../Models/PerformanceType.cs | 29 - CSF.Screenplay.Reporting/Models/Report.cs | 96 -- .../Models/ReportFactory.cs | 36 - CSF.Screenplay.Reporting/Models/Reportable.cs | 53 -- CSF.Screenplay.Reporting/Models/Scenario.cs | 122 --- CSF.Screenplay.Reporting/NoOpReporter.cs | 319 ------- .../ObjectFormatterRegistry.cs | 41 - .../ObjectFormattingService.cs | 59 -- .../Properties/AssemblyInfo.cs | 26 - .../ReportBuildingReporter.cs | 194 ---- .../ReportingIntegrationBuilder.cs | 254 ----- .../ReportingIntegrationBuilderExtensions.cs | 31 - .../ReportingResolverExtensions.cs | 56 -- CSF.Screenplay.Reporting/TextReportWriter.cs | 224 ----- .../Trace/AbilityReport.cs | 49 - CSF.Screenplay.Reporting/Trace/ActorReport.cs | 29 - CSF.Screenplay.Reporting/Trace/BeginReport.cs | 28 - .../Trace/BeginScenarioReport.cs | 54 -- .../Trace/CompleteScenarioReport.cs | 24 - .../Trace/FailureReport.cs | 46 - .../Trace/IPerformanceEnd.cs | 24 - .../Trace/IPerformanceStart.cs | 24 - .../Trace/PerformableReportBase.cs | 40 - .../Trace/ResultReport.cs | 40 - .../Trace/SuccessReport.cs | 28 - .../Trace/TracableEvent.cs | 22 - .../Trace/TraceConstants.cs | 85 -- .../Trace/TraceReporter.cs | 204 ---- CSF.Screenplay.Reporting/packages.config | 5 - .../CSF.Screenplay.SpecFlow.csproj | 65 -- .../CSF.Screenplay.SpecFlow.nuspec | 23 - .../IntegrationProvider.cs | 48 - .../Properties/AssemblyInfo.cs | 26 - CSF.Screenplay.SpecFlow/ScenarioAdapter.cs | 95 -- .../ScenarioAndFeatureKey.cs | 83 -- .../ScreenplayAssemblyAttribute.cs | 29 - CSF.Screenplay.SpecFlow/ScreenplayBinding.cs | 82 -- CSF.Screenplay.SpecFlow/ScreenplayPlugin.cs | 30 - CSF.Screenplay.SpecFlow/packages.config | 6 - CSF.Screenplay/Abilities/Ability.cs | 80 -- CSF.Screenplay/Abilities/AbilityStore.cs | 122 --- CSF.Screenplay/Abilities/IAbility.cs | 13 - CSF.Screenplay/Abilities/IAbilityStore.cs | 35 - CSF.Screenplay/Actors/Actor.cs | 488 ---------- CSF.Screenplay/Actors/ActorEventArgs.cs | 27 - .../Actors/BeginPerformanceEventArgs.cs | 18 - CSF.Screenplay/Actors/Cast.cs | 234 ----- .../Actors/DuplicateActorException.cs | 43 - .../EndSuccessfulPerformanceEventArgs.cs | 18 - CSF.Screenplay/Actors/GainAbilityEventArgs.cs | 30 - CSF.Screenplay/Actors/IActor.cs | 72 -- CSF.Screenplay/Actors/ICanReceiveAbilities.cs | 41 - CSF.Screenplay/Actors/ICast.cs | 85 -- CSF.Screenplay/Actors/IGivenActor.cs | 39 - CSF.Screenplay/Actors/INamed.cs | 15 - CSF.Screenplay/Actors/IPerformer.cs | 46 - CSF.Screenplay/Actors/IStage.cs | 28 - CSF.Screenplay/Actors/IThenActor.cs | 40 - CSF.Screenplay/Actors/IWhenActor.cs | 40 - .../Actors/MissingAbilityException.cs | 43 - .../Actors/PerformanceEventArgsBase.cs | 30 - .../Actors/PerformanceFailureEventArgs.cs | 32 - .../Actors/PerformanceResultEventArgs.cs | 29 - CSF.Screenplay/Actors/Stage.cs | 35 - CSF.Screenplay/CSF.Screenplay.csproj | 121 --- CSF.Screenplay/CSF.Screenplay.nuspec | 22 - .../CastIntegrationBuilderExtensions.cs | 51 - CSF.Screenplay/CastResolverExtensions.cs | 69 -- CSF.Screenplay/IScreenplayScenario.cs | 41 - .../Integration/IIntegrationConfig.cs | 17 - .../Integration/IIntegrationConfigBuilder.cs | 45 - .../Integration/IScreenplayIntegration.cs | 43 - .../IntegrationConfigurationBuilder.cs | 55 -- .../Integration/IntegrationFactory.cs | 45 - .../Integration/ScreenplayIntegration.cs | 146 --- .../Integration/ServiceRegistrations.cs | 37 - CSF.Screenplay/Integration/TestRunEvents.cs | 25 - CSF.Screenplay/Performables/IAction.cs | 11 - CSF.Screenplay/Performables/IAction`1.cs | 11 - CSF.Screenplay/Performables/IPerformable.cs | 18 - .../Performables/IPerformableWithResult.cs | 19 - CSF.Screenplay/Performables/IPerformable`1.cs | 19 - CSF.Screenplay/Performables/IQuestion`1.cs | 21 - CSF.Screenplay/Performables/ITask.cs | 20 - CSF.Screenplay/Performables/ITask`1.cs | 20 - CSF.Screenplay/Performables/Performable.cs | 44 - CSF.Screenplay/Performables/Performable`1.cs | 61 -- CSF.Screenplay/Performables/Question.cs | 40 - CSF.Screenplay/Properties/AssemblyInfo.cs | 26 - .../Reporting/DefaultObjectFormatter.cs | 22 - .../Reporting/GenericObjectFormatter.cs | 54 -- CSF.Screenplay/Reporting/IObjectFormatter.cs | 33 - CSF.Screenplay/Reporting/IReportable.cs | 18 - .../Reporting/StringArrayFormatter.cs | 15 - .../Scenarios/BeginScenarioEventArgs.cs | 27 - .../Scenarios/ContainerExtensions.cs | 32 - .../Scenarios/EndScenarioEventArgs.cs | 33 - .../Scenarios/ICanBeginAndEndScenario.cs | 19 - .../Scenarios/IProvidesTestRunEvents.cs | 19 - CSF.Screenplay/Scenarios/IScenarioFactory.cs | 17 - CSF.Screenplay/Scenarios/IScenarioName.cs | 27 - CSF.Screenplay/Scenarios/IdAndName.cs | 72 -- CSF.Screenplay/Scenarios/ScenarioFactory.cs | 49 - .../Scenarios/ScreenplayScenario.cs | 236 ----- CSF.Screenplay/StepComposer.cs | 45 - CSF.Screenplay/packages.config | 5 - .../CSF.WebDriverFactory.csproj | 70 -- .../CSF.WebDriverFactory.nuspec | 22 - .../FactoryPropertyElementCollection.cs | 118 --- .../Config/IWebDriverFactoryConfiguration.cs | 24 - .../Config/WebDriverConfigurationSection.cs | 70 -- .../ConfigurationWebDriverFactoryProvider.cs | 137 --- .../IMarksWebDriverWithOutcome.cs | 23 - CSF.WebDriverFactory/IWebDriverFactory.cs | 37 - .../IWebDriverFactoryProvider.cs | 15 - .../Impl/ChromeWebDriverFactory.cs | 120 --- .../FirefoxGeckoDriverWebDriverFactory.cs | 116 --- .../Impl/InternetExplorerWebDriverFactory.cs | 103 --- .../Impl/RemoteWebDriverFactory.cs | 151 --- .../RemoteWebDriverFromEnvironmentFactory.cs | 152 --- .../Impl/SauceConnectWebDriverFactory.cs | 103 --- .../Properties/AssemblyInfo.cs | 26 - .../WebDriverFactoryExtensions.cs | 49 - CSF.WebDriverFactory/packages.config | 5 - .../Builders/Get.cs | 15 - .../Builders/Set.cs | 12 - .../Builders/Validate.cs | 11 - .../CSF.Screenplay.JsonApis.Tests.csproj | 81 -- .../ExecuteAJsonApiTests.cs | 103 --- .../ScenarioExtensions.cs | 18 - .../ScreenplayConfig.cs | 29 - .../Services/CheckDataService.cs | 13 - .../Services/GetDataService.cs | 23 - .../Services/GetNumberService.cs | 12 - .../Services/SetNumberService.cs | 12 - .../Services/SlowlyGetDataService.cs | 20 - .../packages.config | 5 - .../AutoMoqDataAttribute.cs | 14 - .../Autofixture/AbilityCustomisation.cs | 41 - .../Autofixture/FeatureCustomisation.cs | 20 - .../Autofixture/GainAbilityCustomisation.cs | 24 - .../Autofixture/NamedCustomisation.cs | 34 - .../Autofixture/PerformableCustomisation.cs | 25 - .../Autofixture/PerformanceCustomisation.cs | 22 - .../Autofixture/PerformanceSpecimenBuilder.cs | 112 --- .../Autofixture/RandomReportAttribute.cs | 21 - .../Autofixture/ReportCustomisation.cs | 23 - .../Autofixture/ScenarioCustomisation.cs | 75 -- .../Autofixture/StringFormatAttribute.cs | 37 - ...CSF.Screenplay.Reporting.Html.Tests.csproj | 136 --- .../HtmlReportWriterTests.cs | 27 - .../app.config | 64 -- .../packages.config | 24 - .../CSF.Screenplay.Reporting.Tests/App.config | 21 - .../AutoMoqDataAttribute.cs | 14 - .../Autofixture/ScenarioAttribute.cs | 29 - .../Autofixture/ScenarioCustomization.cs | 31 - .../CSF.Screenplay.Reporting.Tests.csproj | 75 -- .../ReportBuilderTests.cs | 276 ------ .../ReportFactoryTests.cs | 109 --- .../TextReportWriterTests.cs | 342 ------- .../packages.config | 9 - .../Abilities/AddNumbers.cs | 24 - .../Actions/AddTheNumber.cs | 33 - .../Actions/GetTheNumber.cs | 26 - .../Actions/StartWithTheNumber.cs | 33 - .../CSF.Screenplay.SpecFlow.Tests/App.config | 12 - .../CSF.Screenplay.SpecFlow.Tests.csproj | 90 -- .../ScenarioExtensions.cs | 28 - .../ScreenplayConfig.cs | 25 - .../Stage.feature | 10 - .../Stage.feature.cs | 85 -- .../StageSteps.cs | 47 - .../Test.feature | 15 - .../Test.feature.cs | 104 --- .../TestSteps.cs | 56 -- .../packages.config | 8 - .../Abilities/AbilityStoreTests.cs | 95 -- .../CSF.Screenplay.Tests/Actors/ActorTests.cs | 287 ------ .../CSF.Screenplay.Tests/Actors/CastTests.cs | 266 ------ .../CSF.Screenplay.Tests.csproj | 64 -- .../Integration/ScreenplayIntegrationTests.cs | 238 ----- Tests/CSF.Screenplay.Tests/packages.config | 7 - Tests/CSF.WebDriverFactory.Tests/App.config | 14 - .../AutoMoqDataAttribute.cs | 14 - .../CSF.WebDriverFactory.Tests.csproj | 64 -- ...figurationWebDriverFactoryProviderTests.cs | 63 -- .../packages.config | 9 - 244 files changed, 15241 deletions(-) delete mode 100644 CSF.Screenplay.JsonApis/Abilities/ConsumeJsonWebServices.cs delete mode 100644 CSF.Screenplay.JsonApis/Abilities/SynchronousJsonGateway.cs delete mode 100644 CSF.Screenplay.JsonApis/Actions/ExecuteApi.cs delete mode 100644 CSF.Screenplay.JsonApis/Actions/GetApiResult.cs delete mode 100644 CSF.Screenplay.JsonApis/Builders/Execute.cs delete mode 100644 CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.csproj delete mode 100644 CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.nuspec delete mode 100644 CSF.Screenplay.JsonApis/IProvidesInvocationDetails.cs delete mode 100644 CSF.Screenplay.JsonApis/JsonApiException.cs delete mode 100644 CSF.Screenplay.JsonApis/JsonServiceDescription.cs delete mode 100644 CSF.Screenplay.JsonApis/JsonServiceDescription`1.cs delete mode 100644 CSF.Screenplay.JsonApis/Properties/AssemblyInfo.cs delete mode 100644 CSF.Screenplay.JsonApis/packages.config delete mode 100644 CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.csproj delete mode 100644 CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.nuspec delete mode 100644 CSF.Screenplay.NUnit/IntegrationReader.cs delete mode 100644 CSF.Screenplay.NUnit/Properties/AssemblyInfo.cs delete mode 100644 CSF.Screenplay.NUnit/ScenarioAdapter.cs delete mode 100644 CSF.Screenplay.NUnit/ScreenplayAssemblyAttribute.cs delete mode 100644 CSF.Screenplay.NUnit/ScreenplayAttribute.cs delete mode 100644 CSF.Screenplay.NUnit/packages.config delete mode 100644 CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj delete mode 100644 CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.nuspec delete mode 100644 CSF.Screenplay.Reporting.Html/HtmlReportWriter.cs delete mode 100644 CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs delete mode 100644 CSF.Screenplay.Reporting.Html/Properties/AssemblyInfo.cs delete mode 100644 CSF.Screenplay.Reporting.Html/StreamSourceInfo.cs delete mode 100644 CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt delete mode 100644 CSF.Screenplay.Reporting.Html/Views/Filter.js delete mode 100644 CSF.Screenplay.Reporting.Html/Views/Folding.js delete mode 100644 CSF.Screenplay.Reporting.Html/Views/PageInteractions.js delete mode 100644 CSF.Screenplay.Reporting.Html/Views/ViewProvider.cs delete mode 100644 CSF.Screenplay.Reporting.Html/Views/interactions.css delete mode 100644 CSF.Screenplay.Reporting.Html/Views/jquery-3.2.1.slim.min.js delete mode 100644 CSF.Screenplay.Reporting.Html/Views/page.css delete mode 100644 CSF.Screenplay.Reporting.Html/Views/report-interactions.js delete mode 100644 CSF.Screenplay.Reporting.Html/Views/reports.css delete mode 100644 CSF.Screenplay.Reporting.Html/Views/reset.css delete mode 100644 CSF.Screenplay.Reporting.Html/app.config delete mode 100644 CSF.Screenplay.Reporting.Html/packages.config delete mode 100644 CSF.Screenplay.Reporting/Builders/PerformanceBuilder.cs delete mode 100644 CSF.Screenplay.Reporting/Builders/ReportBuilder.cs delete mode 100644 CSF.Screenplay.Reporting/Builders/ScenarioBuilder.cs delete mode 100644 CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.csproj delete mode 100644 CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.nuspec delete mode 100644 CSF.Screenplay.Reporting/CastReportingHelper.cs delete mode 100644 CSF.Screenplay.Reporting/IModelBuildingReporter.cs delete mode 100644 CSF.Screenplay.Reporting/IObjectFormatterRegistry.cs delete mode 100644 CSF.Screenplay.Reporting/IObjectFormattingService.cs delete mode 100644 CSF.Screenplay.Reporting/IReportWriter.cs delete mode 100644 CSF.Screenplay.Reporting/IReporter.cs delete mode 100755 CSF.Screenplay.Reporting/Models/Feature.cs delete mode 100644 CSF.Screenplay.Reporting/Models/GainAbility.cs delete mode 100755 CSF.Screenplay.Reporting/Models/IReportFactory.cs delete mode 100644 CSF.Screenplay.Reporting/Models/Performance.cs delete mode 100644 CSF.Screenplay.Reporting/Models/PerformanceOutcome.cs delete mode 100644 CSF.Screenplay.Reporting/Models/PerformanceType.cs delete mode 100644 CSF.Screenplay.Reporting/Models/Report.cs delete mode 100755 CSF.Screenplay.Reporting/Models/ReportFactory.cs delete mode 100644 CSF.Screenplay.Reporting/Models/Reportable.cs delete mode 100644 CSF.Screenplay.Reporting/Models/Scenario.cs delete mode 100644 CSF.Screenplay.Reporting/NoOpReporter.cs delete mode 100644 CSF.Screenplay.Reporting/ObjectFormatterRegistry.cs delete mode 100644 CSF.Screenplay.Reporting/ObjectFormattingService.cs delete mode 100644 CSF.Screenplay.Reporting/Properties/AssemblyInfo.cs delete mode 100644 CSF.Screenplay.Reporting/ReportBuildingReporter.cs delete mode 100644 CSF.Screenplay.Reporting/ReportingIntegrationBuilder.cs delete mode 100644 CSF.Screenplay.Reporting/ReportingIntegrationBuilderExtensions.cs delete mode 100644 CSF.Screenplay.Reporting/ReportingResolverExtensions.cs delete mode 100644 CSF.Screenplay.Reporting/TextReportWriter.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/AbilityReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/ActorReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/BeginReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/BeginScenarioReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/CompleteScenarioReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/FailureReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/IPerformanceEnd.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/IPerformanceStart.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/PerformableReportBase.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/ResultReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/SuccessReport.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/TracableEvent.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/TraceConstants.cs delete mode 100644 CSF.Screenplay.Reporting/Trace/TraceReporter.cs delete mode 100644 CSF.Screenplay.Reporting/packages.config delete mode 100644 CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.csproj delete mode 100644 CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.nuspec delete mode 100644 CSF.Screenplay.SpecFlow/IntegrationProvider.cs delete mode 100644 CSF.Screenplay.SpecFlow/Properties/AssemblyInfo.cs delete mode 100644 CSF.Screenplay.SpecFlow/ScenarioAdapter.cs delete mode 100644 CSF.Screenplay.SpecFlow/ScenarioAndFeatureKey.cs delete mode 100644 CSF.Screenplay.SpecFlow/ScreenplayAssemblyAttribute.cs delete mode 100644 CSF.Screenplay.SpecFlow/ScreenplayBinding.cs delete mode 100644 CSF.Screenplay.SpecFlow/ScreenplayPlugin.cs delete mode 100644 CSF.Screenplay.SpecFlow/packages.config delete mode 100644 CSF.Screenplay/Abilities/Ability.cs delete mode 100644 CSF.Screenplay/Abilities/AbilityStore.cs delete mode 100644 CSF.Screenplay/Abilities/IAbility.cs delete mode 100644 CSF.Screenplay/Abilities/IAbilityStore.cs delete mode 100644 CSF.Screenplay/Actors/Actor.cs delete mode 100644 CSF.Screenplay/Actors/ActorEventArgs.cs delete mode 100644 CSF.Screenplay/Actors/BeginPerformanceEventArgs.cs delete mode 100644 CSF.Screenplay/Actors/Cast.cs delete mode 100644 CSF.Screenplay/Actors/DuplicateActorException.cs delete mode 100644 CSF.Screenplay/Actors/EndSuccessfulPerformanceEventArgs.cs delete mode 100644 CSF.Screenplay/Actors/GainAbilityEventArgs.cs delete mode 100644 CSF.Screenplay/Actors/IActor.cs delete mode 100644 CSF.Screenplay/Actors/ICanReceiveAbilities.cs delete mode 100644 CSF.Screenplay/Actors/ICast.cs delete mode 100644 CSF.Screenplay/Actors/IGivenActor.cs delete mode 100644 CSF.Screenplay/Actors/INamed.cs delete mode 100644 CSF.Screenplay/Actors/IPerformer.cs delete mode 100644 CSF.Screenplay/Actors/IStage.cs delete mode 100644 CSF.Screenplay/Actors/IThenActor.cs delete mode 100644 CSF.Screenplay/Actors/IWhenActor.cs delete mode 100644 CSF.Screenplay/Actors/MissingAbilityException.cs delete mode 100644 CSF.Screenplay/Actors/PerformanceEventArgsBase.cs delete mode 100644 CSF.Screenplay/Actors/PerformanceFailureEventArgs.cs delete mode 100644 CSF.Screenplay/Actors/PerformanceResultEventArgs.cs delete mode 100644 CSF.Screenplay/Actors/Stage.cs delete mode 100644 CSF.Screenplay/CSF.Screenplay.csproj delete mode 100644 CSF.Screenplay/CSF.Screenplay.nuspec delete mode 100644 CSF.Screenplay/CastIntegrationBuilderExtensions.cs delete mode 100644 CSF.Screenplay/CastResolverExtensions.cs delete mode 100644 CSF.Screenplay/IScreenplayScenario.cs delete mode 100644 CSF.Screenplay/Integration/IIntegrationConfig.cs delete mode 100644 CSF.Screenplay/Integration/IIntegrationConfigBuilder.cs delete mode 100644 CSF.Screenplay/Integration/IScreenplayIntegration.cs delete mode 100644 CSF.Screenplay/Integration/IntegrationConfigurationBuilder.cs delete mode 100644 CSF.Screenplay/Integration/IntegrationFactory.cs delete mode 100644 CSF.Screenplay/Integration/ScreenplayIntegration.cs delete mode 100644 CSF.Screenplay/Integration/ServiceRegistrations.cs delete mode 100644 CSF.Screenplay/Integration/TestRunEvents.cs delete mode 100644 CSF.Screenplay/Performables/IAction.cs delete mode 100644 CSF.Screenplay/Performables/IAction`1.cs delete mode 100644 CSF.Screenplay/Performables/IPerformable.cs delete mode 100644 CSF.Screenplay/Performables/IPerformableWithResult.cs delete mode 100644 CSF.Screenplay/Performables/IPerformable`1.cs delete mode 100644 CSF.Screenplay/Performables/IQuestion`1.cs delete mode 100644 CSF.Screenplay/Performables/ITask.cs delete mode 100644 CSF.Screenplay/Performables/ITask`1.cs delete mode 100644 CSF.Screenplay/Performables/Performable.cs delete mode 100644 CSF.Screenplay/Performables/Performable`1.cs delete mode 100644 CSF.Screenplay/Performables/Question.cs delete mode 100644 CSF.Screenplay/Properties/AssemblyInfo.cs delete mode 100644 CSF.Screenplay/Reporting/DefaultObjectFormatter.cs delete mode 100644 CSF.Screenplay/Reporting/GenericObjectFormatter.cs delete mode 100644 CSF.Screenplay/Reporting/IObjectFormatter.cs delete mode 100644 CSF.Screenplay/Reporting/IReportable.cs delete mode 100644 CSF.Screenplay/Reporting/StringArrayFormatter.cs delete mode 100644 CSF.Screenplay/Scenarios/BeginScenarioEventArgs.cs delete mode 100644 CSF.Screenplay/Scenarios/ContainerExtensions.cs delete mode 100644 CSF.Screenplay/Scenarios/EndScenarioEventArgs.cs delete mode 100644 CSF.Screenplay/Scenarios/ICanBeginAndEndScenario.cs delete mode 100644 CSF.Screenplay/Scenarios/IProvidesTestRunEvents.cs delete mode 100644 CSF.Screenplay/Scenarios/IScenarioFactory.cs delete mode 100644 CSF.Screenplay/Scenarios/IScenarioName.cs delete mode 100644 CSF.Screenplay/Scenarios/IdAndName.cs delete mode 100644 CSF.Screenplay/Scenarios/ScenarioFactory.cs delete mode 100644 CSF.Screenplay/Scenarios/ScreenplayScenario.cs delete mode 100644 CSF.Screenplay/StepComposer.cs delete mode 100644 CSF.Screenplay/packages.config delete mode 100644 CSF.WebDriverFactory/CSF.WebDriverFactory.csproj delete mode 100644 CSF.WebDriverFactory/CSF.WebDriverFactory.nuspec delete mode 100644 CSF.WebDriverFactory/Config/FactoryPropertyElementCollection.cs delete mode 100644 CSF.WebDriverFactory/Config/IWebDriverFactoryConfiguration.cs delete mode 100644 CSF.WebDriverFactory/Config/WebDriverConfigurationSection.cs delete mode 100644 CSF.WebDriverFactory/ConfigurationWebDriverFactoryProvider.cs delete mode 100644 CSF.WebDriverFactory/IMarksWebDriverWithOutcome.cs delete mode 100644 CSF.WebDriverFactory/IWebDriverFactory.cs delete mode 100644 CSF.WebDriverFactory/IWebDriverFactoryProvider.cs delete mode 100644 CSF.WebDriverFactory/Impl/ChromeWebDriverFactory.cs delete mode 100644 CSF.WebDriverFactory/Impl/FirefoxGeckoDriverWebDriverFactory.cs delete mode 100644 CSF.WebDriverFactory/Impl/InternetExplorerWebDriverFactory.cs delete mode 100644 CSF.WebDriverFactory/Impl/RemoteWebDriverFactory.cs delete mode 100644 CSF.WebDriverFactory/Impl/RemoteWebDriverFromEnvironmentFactory.cs delete mode 100644 CSF.WebDriverFactory/Impl/SauceConnectWebDriverFactory.cs delete mode 100644 CSF.WebDriverFactory/Properties/AssemblyInfo.cs delete mode 100644 CSF.WebDriverFactory/WebDriverFactoryExtensions.cs delete mode 100644 CSF.WebDriverFactory/packages.config delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Builders/Get.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Builders/Set.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Builders/Validate.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/CSF.Screenplay.JsonApis.Tests.csproj delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/ExecuteAJsonApiTests.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/ScenarioExtensions.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/ScreenplayConfig.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Services/CheckDataService.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Services/GetDataService.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Services/GetNumberService.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Services/SetNumberService.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/Services/SlowlyGetDataService.cs delete mode 100644 Tests/CSF.Screenplay.JsonApis.Tests/packages.config delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/AutoMoqDataAttribute.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/AbilityCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/FeatureCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/GainAbilityCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/NamedCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformableCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceSpecimenBuilder.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/RandomReportAttribute.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ReportCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ScenarioCustomisation.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/StringFormatAttribute.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/CSF.Screenplay.Reporting.Html.Tests.csproj delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/HtmlReportWriterTests.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/app.config delete mode 100644 Tests/CSF.Screenplay.Reporting.Html.Tests/packages.config delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/App.config delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/AutoMoqDataAttribute.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioAttribute.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioCustomization.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/CSF.Screenplay.Reporting.Tests.csproj delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/ReportBuilderTests.cs delete mode 100755 Tests/CSF.Screenplay.Reporting.Tests/ReportFactoryTests.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/TextReportWriterTests.cs delete mode 100644 Tests/CSF.Screenplay.Reporting.Tests/packages.config delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Abilities/AddNumbers.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Actions/AddTheNumber.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Actions/GetTheNumber.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Actions/StartWithTheNumber.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/App.config delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/CSF.Screenplay.SpecFlow.Tests.csproj delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/ScenarioExtensions.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/ScreenplayConfig.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/StageSteps.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/TestSteps.cs delete mode 100644 Tests/CSF.Screenplay.SpecFlow.Tests/packages.config delete mode 100644 Tests/CSF.Screenplay.Tests/Abilities/AbilityStoreTests.cs delete mode 100644 Tests/CSF.Screenplay.Tests/Actors/ActorTests.cs delete mode 100644 Tests/CSF.Screenplay.Tests/Actors/CastTests.cs delete mode 100644 Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj delete mode 100644 Tests/CSF.Screenplay.Tests/Integration/ScreenplayIntegrationTests.cs delete mode 100644 Tests/CSF.Screenplay.Tests/packages.config delete mode 100644 Tests/CSF.WebDriverFactory.Tests/App.config delete mode 100644 Tests/CSF.WebDriverFactory.Tests/AutoMoqDataAttribute.cs delete mode 100644 Tests/CSF.WebDriverFactory.Tests/CSF.WebDriverFactory.Tests.csproj delete mode 100644 Tests/CSF.WebDriverFactory.Tests/ConfigurationWebDriverFactoryProviderTests.cs delete mode 100644 Tests/CSF.WebDriverFactory.Tests/packages.config diff --git a/CSF.Screenplay.JsonApis/Abilities/ConsumeJsonWebServices.cs b/CSF.Screenplay.JsonApis/Abilities/ConsumeJsonWebServices.cs deleted file mode 100644 index f42f8f35..00000000 --- a/CSF.Screenplay.JsonApis/Abilities/ConsumeJsonWebServices.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.IO; -using System.Net.Http; -using System.Threading.Tasks; -using CSF.Screenplay.Abilities; -using Newtonsoft.Json; - -namespace CSF.Screenplay.JsonApis.Abilities -{ - public class ConsumeJsonWebServices : Ability - { - #region fields - - static readonly TimeSpan SystemDefaultTimeout = new TimeSpan(0, 0, 30); - - readonly TimeSpan defaultTimeout; - readonly SynchronousJsonGateway jsonGateway; - - #endregion - - #region public API - - public virtual void Execute(IProvidesInvocationDetails invocationDetails) - => jsonGateway.GetResponse(invocationDetails.GetRequestMessage(), GetTimeout(invocationDetails)); - - public virtual T GetResult(IProvidesInvocationDetails invocationDetails) - => jsonGateway.GetResponse(invocationDetails.GetRequestMessage(), GetTimeout(invocationDetails)); - - #endregion - - #region private methods - - TimeSpan GetTimeout(IProvidesInvocationDetails invocationDetails) - => invocationDetails.GetTimeout().GetValueOrDefault(defaultTimeout); - - #endregion - - #region boilerplate Ability overrides - - protected override string GetReport(Actors.INamed actor) - => $"{actor.Name} can consume JSON web services."; - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if(disposing) - jsonGateway.Dispose(); - } - - #endregion - - #region constructor - - public ConsumeJsonWebServices(string baseUriString, TimeSpan? defaultTimeout = null) - : this(new Uri(baseUriString, UriKind.Absolute), defaultTimeout) {} - - public ConsumeJsonWebServices(Uri baseUri = null, TimeSpan? defaultTimeout = null) - { - this.defaultTimeout = defaultTimeout.GetValueOrDefault(SystemDefaultTimeout); - jsonGateway = new SynchronousJsonGateway(baseUri); - } - - #endregion - } -} diff --git a/CSF.Screenplay.JsonApis/Abilities/SynchronousJsonGateway.cs b/CSF.Screenplay.JsonApis/Abilities/SynchronousJsonGateway.cs deleted file mode 100644 index e859a727..00000000 --- a/CSF.Screenplay.JsonApis/Abilities/SynchronousJsonGateway.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace CSF.Screenplay.JsonApis.Abilities -{ - public class SynchronousJsonGateway : IDisposable - { - #region fields - - readonly HttpClient httpClient; - readonly JsonSerializer serializer; - - #endregion - - #region public API - - public void GetResponse(HttpRequestMessage request, TimeSpan timeout) - { - GetResponseMessage(request, timeout); - } - - public T GetResponse(HttpRequestMessage request, TimeSpan timeout) - { - var response = GetResponseMessage(request, timeout); - return ConvertResponse(response); - } - - #endregion - - #region methods - - HttpResponseMessage GetResponseMessage(HttpRequestMessage request, TimeSpan timeout) - { - var response = GetResponseRespectingTimeout(request, timeout); - AssertThatResultIsSuccess(response); - return response; - } - - HttpResponseMessage GetResponseRespectingTimeout(HttpRequestMessage request, TimeSpan timeout) - { - var tokenSource = new CancellationTokenSource(timeout); - var token = tokenSource.Token; - - try - { - return httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, token).Result; - } - catch(TaskCanceledException ex) - { - throw new TimeoutException($"The JSON API request timed out after {timeout.ToString("g")}.", ex); - } - catch(HttpRequestException ex) - { - throw new JsonApiException("The JSON API request failed.", ex); - } - catch(AggregateException ex) - { - if(ex.InnerExceptions.OfType().Any()) - throw new TimeoutException($"The JSON API request timed out after {timeout.ToString("g")}.", ex); - else if(ex.InnerExceptions.OfType().Any()) - throw new JsonApiException("The JSON API request failed.", ex); - - throw; - } - } - - void AssertThatResultIsSuccess(HttpResponseMessage result) - { - if(result.IsSuccessStatusCode) return; - - var responseBody = result.Content.ReadAsStringAsync().Result; - throw new JsonApiException($@"The JSON API request failed: HTTP {result.StatusCode.ToString()} -{responseBody}"); - } - - protected virtual T ConvertResponse(HttpResponseMessage response) - { - using(var buffer = new MemoryStream()) - { - var copyTask = response.Content.CopyToAsync(buffer); - var waitSuccess = copyTask.Wait(TimeSpan.FromSeconds(1)); - if(!waitSuccess) - throw new JsonApiException("Timeout whilst converting JSON response to string. This should probably never happen?!"); - - buffer.Position = 0; - - using(var reader = new StreamReader(buffer)) - { - return (T) serializer.Deserialize(reader, typeof(T)); - } - } - } - - #endregion - - #region IDisposable Support - bool disposedValue; - - protected virtual void Dispose(bool disposing) - { - if(!disposedValue) - { - if(disposing) - { - httpClient.Dispose(); - } - - disposedValue = true; - } - } - - public void Dispose() - { - Dispose(true); - } - #endregion - - #region constructor - - public SynchronousJsonGateway(Uri httpClientBaseUri) - { - disposedValue = false; - - httpClient = new HttpClient { - BaseAddress = httpClientBaseUri, - Timeout = Timeout.InfiniteTimeSpan, - }; - serializer = JsonSerializer.CreateDefault(); - } - - #endregion - } -} diff --git a/CSF.Screenplay.JsonApis/Actions/ExecuteApi.cs b/CSF.Screenplay.JsonApis/Actions/ExecuteApi.cs deleted file mode 100644 index 5d02c65b..00000000 --- a/CSF.Screenplay.JsonApis/Actions/ExecuteApi.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.JsonApis.Abilities; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.JsonApis.Actions -{ - public class ExecuteApi : Performable - { - readonly IProvidesInvocationDetails service; - - protected override string GetReport(INamed actor) - => $"{actor.Name} executes {service.ToString()}"; - - protected override void PerformAs(IPerformer actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - var ability = actor.GetAbility(); - ability.Execute(service); - } - - public ExecuteApi(IProvidesInvocationDetails service) - { - if(service == null) - throw new ArgumentNullException(nameof(service)); - - this.service = service; - } - } -} diff --git a/CSF.Screenplay.JsonApis/Actions/GetApiResult.cs b/CSF.Screenplay.JsonApis/Actions/GetApiResult.cs deleted file mode 100644 index 5f93c1f4..00000000 --- a/CSF.Screenplay.JsonApis/Actions/GetApiResult.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.JsonApis.Abilities; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.JsonApis.Actions -{ - public class GetApiResult : Question - { - readonly IProvidesInvocationDetails service; - - protected override string GetReport(INamed actor) - => $"{actor.Name} gets the result of {service.ToString()}"; - - protected override T PerformAs(IPerformer actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - var ability = actor.GetAbility(); - return ability.GetResult(service); - } - - public GetApiResult(IProvidesInvocationDetails service) - { - if(service == null) - throw new ArgumentNullException(nameof(service)); - - this.service = service; - } - } -} diff --git a/CSF.Screenplay.JsonApis/Builders/Execute.cs b/CSF.Screenplay.JsonApis/Builders/Execute.cs deleted file mode 100644 index f8c864fa..00000000 --- a/CSF.Screenplay.JsonApis/Builders/Execute.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using CSF.Screenplay.JsonApis.Actions; - -namespace CSF.Screenplay.JsonApis.Builders -{ - public static class Execute - { - public static ExecuteApi AJsonApi(JsonServiceDescription invocationDetails) - => new ExecuteApi(invocationDetails); - - public static GetApiResult AJsonApiAndGetTheResult(JsonServiceDescription invocationDetails) - => new GetApiResult(invocationDetails); - } -} diff --git a/CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.csproj b/CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.csproj deleted file mode 100644 index b3c7b199..00000000 --- a/CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.csproj +++ /dev/null @@ -1,65 +0,0 @@ - - - - Debug - AnyCPU - {9AA1246E-B5BC-499E-B0D9-EFA5F62F2E2C} - Library - CSF.Screenplay.JsonApis - CSF.Screenplay.JsonApis - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - false - - - true - bin\Release - prompt - 4 - false - - - - - - ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll - - - - - - - - - - - - - - - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.nuspec b/CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.nuspec deleted file mode 100644 index 849c6c74..00000000 --- a/CSF.Screenplay.JsonApis/CSF.Screenplay.JsonApis.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - CSF.Screenplay.JsonApis - 0.8.0-alpha - CSF.Screenplay.JsonApis - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - Screenplay Abilities and Actions for making use of JSON HTTP web APIs in Screenplay - Copyright 2018 - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.JsonApis/IProvidesInvocationDetails.cs b/CSF.Screenplay.JsonApis/IProvidesInvocationDetails.cs deleted file mode 100644 index 699de8b2..00000000 --- a/CSF.Screenplay.JsonApis/IProvidesInvocationDetails.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Net.Http; - -namespace CSF.Screenplay.JsonApis -{ - public interface IProvidesInvocationDetails - { - HttpRequestMessage GetRequestMessage(); - - TimeSpan? GetTimeout(); - } -} diff --git a/CSF.Screenplay.JsonApis/JsonApiException.cs b/CSF.Screenplay.JsonApis/JsonApiException.cs deleted file mode 100644 index 5aebeba0..00000000 --- a/CSF.Screenplay.JsonApis/JsonApiException.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -namespace CSF.Screenplay.JsonApis -{ - /// - /// Exception raised when there is a problem executing a JSON web API call. - /// - [System.Serializable] - public class JsonApiException : Exception - { - /// - /// Initializes a new instance of the class - /// - public JsonApiException() - { - } - - /// - /// Initializes a new instance of the class - /// - /// A that describes the exception. - public JsonApiException(string message) : base(message) - { - } - - /// - /// Initializes a new instance of the class - /// - /// A that describes the exception. - /// The exception that is the cause of the current exception. - public JsonApiException(string message, Exception inner) : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class - /// - /// The contextual information about the source or destination. - /// The object that holds the serialized object data. - protected JsonApiException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) - { - } - } -} diff --git a/CSF.Screenplay.JsonApis/JsonServiceDescription.cs b/CSF.Screenplay.JsonApis/JsonServiceDescription.cs deleted file mode 100644 index 1123a448..00000000 --- a/CSF.Screenplay.JsonApis/JsonServiceDescription.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Net.Mime; -using System.Text; -using Newtonsoft.Json; - -namespace CSF.Screenplay.JsonApis -{ - public abstract class JsonServiceDescription : IProvidesInvocationDetails - { - static readonly ContentType JsonContentType = new ContentType("application/json"); - - readonly TimeSpan? timeout; - readonly object requestPayload; - readonly JsonSerializer serializer; - - public HttpRequestMessage GetRequestMessage() - { - var output = new HttpRequestMessage - { - RequestUri = GetUri(), - Method = GetHttpMethod(), - Content = GetContent(), - }; - - ConfigureRequestHeaders(output); - - return output; - } - - public TimeSpan? GetTimeout() => timeout; - - protected virtual Uri GetUri() => new Uri(GetUriString(), UriKind.Relative); - - protected abstract string GetUriString(); - - protected virtual HttpMethod GetHttpMethod() => HttpMethod.Post; - - protected virtual IDictionary GetHeaders() => null; - - protected virtual Encoding GetEncoding() => Encoding.UTF8; - - void ConfigureRequestHeaders(HttpRequestMessage request) - { - var headers = GetHeaders(); - if(headers == null) - return; - - AddAcceptsJsonHeader(request); - - foreach(var header in headers.Keys) - { - request.Headers.Add(header, headers[header]); - } - } - - protected virtual void AddAcceptsJsonHeader(HttpRequestMessage request) - { - request.Headers.Add("Accept", JsonContentType.MediaType); - } - - HttpContent GetContent() - { - if(ReferenceEquals(requestPayload, null)) - return null; - - var serializedContent = SerializeContentToJson(requestPayload); - return new StringContent(serializedContent, GetEncoding(), JsonContentType.MediaType); - } - - string SerializeContentToJson(object content) - { - var sb = new StringBuilder(); - - using(var writer = new StringWriter(sb)) - { - serializer.Serialize(writer, content); - writer.Flush(); - } - - return sb.ToString(); - } - - public override string ToString() => $"the {GetType().Name} service"; - - public JsonServiceDescription(TimeSpan? timeout = null, - object requestPayload = null) - { - this.requestPayload = requestPayload; - this.timeout = timeout; - - serializer = JsonSerializer.CreateDefault(); - } - } -} diff --git a/CSF.Screenplay.JsonApis/JsonServiceDescription`1.cs b/CSF.Screenplay.JsonApis/JsonServiceDescription`1.cs deleted file mode 100644 index fba5b49d..00000000 --- a/CSF.Screenplay.JsonApis/JsonServiceDescription`1.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; -namespace CSF.Screenplay.JsonApis -{ - public abstract class JsonServiceDescription : JsonServiceDescription - { - public JsonServiceDescription(TimeSpan? timeout = null, - object requestPayload = null) : base(timeout, requestPayload) {} - } -} diff --git a/CSF.Screenplay.JsonApis/Properties/AssemblyInfo.cs b/CSF.Screenplay.JsonApis/Properties/AssemblyInfo.cs deleted file mode 100644 index ffea0887..00000000 --- a/CSF.Screenplay.JsonApis/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.Screenplay.JsonApis")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("0.8.0.0")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.Screenplay.JsonApis/packages.config b/CSF.Screenplay.JsonApis/packages.config deleted file mode 100644 index ee51c237..00000000 --- a/CSF.Screenplay.JsonApis/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.csproj b/CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.csproj deleted file mode 100644 index b5cbb08a..00000000 --- a/CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.csproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - Debug - AnyCPU - {78571AD2-4C55-4459-A4D9-2CD63A9AACC7} - Library - CSF.Screenplay.NUnit - CSF.Screenplay.NUnit - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - bin\Debug\CSF.Screenplay.NUnit.xml - false - - - true - bin\Release - prompt - 4 - bin\Release\CSF.Screenplay.NUnit.xml - false - - - - - ..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - ..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll - - - - - - - - - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - - \ No newline at end of file diff --git a/CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.nuspec b/CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.nuspec deleted file mode 100644 index 660b6ce4..00000000 --- a/CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - CSF.Screenplay.NUnit - 0.8.0-alpha - CSF.Screenplay.NUnit - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - Bindings and types for making use of CSF.Screenplay with NUnit Framework 3.x - Copyright 2017 - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.NUnit/IntegrationReader.cs b/CSF.Screenplay.NUnit/IntegrationReader.cs deleted file mode 100644 index 29c259f2..00000000 --- a/CSF.Screenplay.NUnit/IntegrationReader.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Reflection; -using CSF.Screenplay.Integration; -using NUnit.Framework.Interfaces; - -namespace CSF.Screenplay.NUnit -{ - /// - /// Helper type which provides access to the current Screenplay integration. - /// - public class IntegrationReader - { - static object syncRoot; - static IScreenplayIntegration integration; - - /// - /// Gets the integration from a given NUnit test method. - /// - /// The integration. - /// Method. - public IScreenplayIntegration GetIntegration(IMethodInfo method) - { - lock(syncRoot) - { - if(integration == null) - { - var assembly = method?.MethodInfo?.DeclaringType?.Assembly; - if(assembly == null) - { - throw new ArgumentException($"The method must have an associated {nameof(Assembly)}.", - nameof(method)); - } - - var assemblyAttrib = assembly.GetCustomAttribute(); - if(assemblyAttrib == null) - { - var message = $"All test methods must be contained within assemblies which are " + - $"decorated with `{nameof(ScreenplayAssemblyAttribute)}'."; - throw new InvalidOperationException(message); - } - - integration = assemblyAttrib.Integration; - } - } - - return integration; - } - - /// - /// Gets the integration from a given NUnit test instance. - /// - /// The integration. - /// Test. - public IScreenplayIntegration GetIntegration(ITest test) - { - if(test.Method == null) - throw new ArgumentException("The test must specify a method.", nameof(test)); - - return GetIntegration(test.Method); - } - - /// - /// Initializes the class. - /// - static IntegrationReader() - { - syncRoot = new object(); - } - } -} diff --git a/CSF.Screenplay.NUnit/Properties/AssemblyInfo.cs b/CSF.Screenplay.NUnit/Properties/AssemblyInfo.cs deleted file mode 100644 index 7b538258..00000000 --- a/CSF.Screenplay.NUnit/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.Screenplay.NUnit")] -[assembly: AssemblyDescription("NUnit 3 bindings for Screenplay")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("0.8.0.0")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.Screenplay.NUnit/ScenarioAdapter.cs b/CSF.Screenplay.NUnit/ScenarioAdapter.cs deleted file mode 100644 index 9b9e7bc8..00000000 --- a/CSF.Screenplay.NUnit/ScenarioAdapter.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using CSF.Screenplay.Integration; -using CSF.Screenplay.Scenarios; -using NUnit.Framework; -using NUnit.Framework.Interfaces; - -namespace CSF.Screenplay.NUnit -{ - /// - /// Adapter type which provides a simple API for getting feature/scenario identification information. - /// - public class ScenarioAdapter - { - internal const string ScreenplayScenarioKey = "Current scenario"; - - readonly ITest featureSuite; - readonly IMethodInfo scenarioMethod; - readonly IScreenplayIntegration integration; - - /// - /// Gets the name of the scenario. - /// - /// The name of the scenario. - public string ScenarioName - { - get { - var method = scenarioMethod.MethodInfo; - - if(method == null) - return null; - - return GetDescription(method); - } - } - - /// - /// Gets the scenario identifier. - /// - /// The scenario identifier. - public string ScenarioId => $"{FeatureId}.{scenarioMethod.Name}"; - - /// - /// Gets the name of the feature. - /// - /// The name of the feature. - public string FeatureName - { - get { - var fixtureType = scenarioMethod.MethodInfo.DeclaringType; - - if(fixtureType == null) - return null; - - return GetDescription(fixtureType); - } - } - - /// - /// Gets the feature identifier. - /// - /// The feature identifier. - public string FeatureId => featureSuite.FullName; - - /// - /// Creates a new Screenplay scenario using the state of the current instance, and the given integration. - /// - /// The scenario. - public IScreenplayScenario CreateScenario() - { - var factory = integration.GetScenarioFactory(); - return factory.GetScenario(FeatureIdAndName, ScenarioIdAndName); - } - - string GetDescription(MemberInfo member) - { - var attrib = member.GetCustomAttribute(); - - if(attrib == null) - return member.Name; - - var prop = attrib.Properties.Get("Description"); - if(prop == null) - return member.Name; - - return prop.ToString(); - } - - IdAndName FeatureIdAndName => new IdAndName(FeatureId, FeatureName); - - IdAndName ScenarioIdAndName => new IdAndName(ScenarioId, ScenarioName); - - /// - /// Initializes a new instance of the class. - /// - /// Feature suite. - /// Scenario method. - /// Screenplay integration. - public ScenarioAdapter(ITest featureSuite, IMethodInfo scenarioMethod, IScreenplayIntegration integration) - { - if(integration == null) - throw new ArgumentNullException(nameof(integration)); - if(scenarioMethod == null) - throw new ArgumentNullException(nameof(scenarioMethod)); - if(featureSuite == null) - throw new ArgumentNullException(nameof(featureSuite)); - - this.scenarioMethod = scenarioMethod; - this.featureSuite = featureSuite; - this.integration = integration; - } - - /// - /// Gets a value which indicates whether a single test passed. - /// - /// true, if the test was successful, false otherwise. - /// Test. - public static bool GetSuccess(ITest test) - { - var result = TestContext.CurrentContext.Result; - return result.Outcome.Status == TestStatus.Passed; - } - - /// - /// Gets a value which indicates whether a single test failed. - /// - /// true, if the test was a failure, false otherwise. - /// Test. - public static bool GetFailure(ITest test) - { - var result = TestContext.CurrentContext.Result; - return result.Outcome.Status == TestStatus.Failed; - } - - /// - /// Gets an from a given NUnit test instance. - /// - /// The scenario. - /// Test. - public static IScreenplayScenario GetScenario(ITest test) - { - var scenario = GetScenario(test.Properties); - if(scenario != null) - return scenario; - - scenario = GetScenario(test.Arguments); - if(scenario != null) - return scenario; - - var message = $"The test must contain an instance of `{nameof(IScreenplayScenario)}' in " + - $"its {nameof(ITest.Properties)} or its {nameof(ITest.Arguments)}."; - throw new ArgumentException(message, nameof(test)); - } - - /// - /// Gets an from a given NUnit property bad. - /// - /// The scenario. - /// Properties. - public static IScreenplayScenario GetScenario(IPropertyBag properties) - { - if(properties.ContainsKey(ScreenplayScenarioKey)) - return (IScreenplayScenario) properties.Get(ScreenplayScenarioKey); - - return null; - } - - /// - /// Gets an from the arguments to an NUnit test method. - /// - /// The scenario. - /// Method arguments. - public static IScreenplayScenario GetScenario(object[] methodArguments) - { - return (IScreenplayScenario) methodArguments.FirstOrDefault(x => x is IScreenplayScenario); - } - } -} diff --git a/CSF.Screenplay.NUnit/ScreenplayAssemblyAttribute.cs b/CSF.Screenplay.NUnit/ScreenplayAssemblyAttribute.cs deleted file mode 100644 index b362ba02..00000000 --- a/CSF.Screenplay.NUnit/ScreenplayAssemblyAttribute.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using CSF.Screenplay.Integration; -using NUnit.Framework; -using NUnit.Framework.Interfaces; - -namespace CSF.Screenplay.NUnit -{ - /// - /// Indicates that the assembly contains Screenplay tests. - /// - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] - public class ScreenplayAssemblyAttribute : TestActionAttribute - { - static Lazy integration; - - /// - /// Gets the current Screenplay integration. - /// - /// The integration. - public IScreenplayIntegration Integration => integration.Value; - - /// - /// Gets the targets for this attribute (the affected tests). - /// - /// The targets. - public override ActionTargets Targets => ActionTargets.Suite; - - /// - /// Executes actions after any tests in the current assembly. - /// - /// Test. - public override void AfterTest(ITest test) - { - Integration.AfterExecutedLastScenario(); - } - - /// - /// Executes actions before any tests in the current assembly. - /// - /// Test. - public override void BeforeTest(ITest test) - { - Integration.BeforeExecutingFirstScenario(); - } - - /// - /// Initializes a new instance of the class. - /// - /// Integration type. - public ScreenplayAssemblyAttribute(Type configType) - { - integration = integration?? new Lazy(() => new IntegrationFactory().Create(configType)); - } - } -} diff --git a/CSF.Screenplay.NUnit/ScreenplayAttribute.cs b/CSF.Screenplay.NUnit/ScreenplayAttribute.cs deleted file mode 100644 index 23e912b2..00000000 --- a/CSF.Screenplay.NUnit/ScreenplayAttribute.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using CSF.Screenplay.Integration; -using CSF.Screenplay.Scenarios; -using NUnit.Framework; -using NUnit.Framework.Interfaces; -using NUnit.Framework.Internal; -using NUnit.Framework.Internal.Builders; -using NUnit.Framework.Internal.Commands; - -namespace CSF.Screenplay.NUnit -{ - /// - /// Applied to an assembly, fixture or test - this indicates that a test (or all of the tests within the - /// scope of this attribute) are Screenplay tests. - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - public class ScreenplayAttribute : Attribute, ITestAction, ITestBuilder - { - readonly IntegrationReader integrationReader; - - /// - /// Gets the targets for the attribute (when performing before/after test actions). - /// - /// The targets. - public ActionTargets Targets => ActionTargets.Test; - - /// - /// Performs actions before each test. - /// - /// Test. - public void BeforeTest(ITest test) - { - var scenario = ScenarioAdapter.GetScenario(test); - var integration = integrationReader.GetIntegration(test); - integration.BeforeScenario(scenario); - } - - /// - /// Performs actions after each test. - /// - /// Test. - public void AfterTest(ITest test) - { - var scenario = ScenarioAdapter.GetScenario(test); - var outcome = GetOutcome(test); - var integration = integrationReader.GetIntegration(test); - integration.AfterScenario(scenario, outcome); - } - - /// - /// Builds a collectio of NUnit test methods from metadata about the test. - /// - /// The test methods. - /// Method information. - /// Test suite information. - public IEnumerable BuildFrom(IMethodInfo method, Test suite) - { - var scenario = CreateScenario(method, suite); - suite.Properties.Add(ScenarioAdapter.ScreenplayScenarioKey, scenario); - return BuildFrom(method, suite, scenario); - } - - bool? GetOutcome(ITest test) - { - var success = ScenarioAdapter.GetSuccess(test); - var failure = ScenarioAdapter.GetFailure(test); - - if(success) return true; - if(failure) return false; - - return null; - } - - IEnumerable BuildFrom(IMethodInfo method, Test suite, IScreenplayScenario scenario) - { - var builder = new NUnitTestCaseBuilder(); - var tcParams = new TestCaseParameters(new [] { scenario }); - - var testMethod = builder.BuildTestMethod(method, suite, tcParams); - - return new [] { testMethod }; - } - - IScreenplayScenario CreateScenario(IMethodInfo method, Test suite) - { - var integration = integrationReader.GetIntegration(method); - var adapter = new ScenarioAdapter(suite, method, integration); - return adapter.CreateScenario(); - } - - /// - /// Initializes a new instance of the class. - /// - public ScreenplayAttribute() - { - integrationReader = new IntegrationReader(); - } - } -} diff --git a/CSF.Screenplay.NUnit/packages.config b/CSF.Screenplay.NUnit/packages.config deleted file mode 100644 index 137cbda4..00000000 --- a/CSF.Screenplay.NUnit/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj b/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj deleted file mode 100644 index d5bf66d3..00000000 --- a/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - Debug - AnyCPU - {29AA4CCD-A7B7-414E-A57F-FDE74A04A19F} - Library - CSF.Screenplay.Reporting - CSF.Screenplay.Reporting.Html - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - false - - - true - bin\Release - prompt - 4 - false - - - - - ..\packages\CSF.Caches.1.0.0\lib\net45\CSF.Caches.dll - - - ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll - - - ..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll - - - ..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll - - - - - - - - ..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll - - - ..\packages\CSF.Zpt.Abstractions.1.0.3\lib\net45\CSF.Zpt.Abstractions.dll - - - ..\packages\CSF.Zpt.1.0.3\lib\net45\CSF.Zpt.dll - - - ..\packages\CSF.Zpt.DocumentProviders.XmlLinq.1.0.3\lib\net45\CSF.Zpt.DocumentProviders.XmlLinq.dll - - - ..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.dll - - - ..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpFramework.dll - - - ..\packages\CSF.Zpt.ExpressionEvaluators.NotExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.NotExpressions.dll - - - ..\packages\CSF.Zpt.ExpressionEvaluators.PathExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.PathExpressions.dll - - - ..\packages\CSF.Zpt.ExpressionEvaluators.StringExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.StringExpressions.dll - - - ..\packages\CSF.Zpt.DocumentProviders.HtmlHAP.1.0.3\lib\net45\CSF.Zpt.DocumentProviders.HtmlHAP.dll - - - ..\packages\CSF.Zpt.ExpressionEvaluators.LoadExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.LoadExpressions.dll - - - - - - - - - - - - - - - - - {18010B4E-22A7-4462-B057-7199B3386D48} - CSF.Screenplay.Reporting - - - - - - - - - DocumentTemplate.pt - - - Filter.js - - - Folding.js - - - interactions.css - - - jquery-3.2.1.slim.min.js - - - page.css - - - PageInteractions.js - - - report-interactions.js - - - reports.css - - - reset.css - - - - \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.nuspec b/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.nuspec deleted file mode 100644 index bc769b28..00000000 --- a/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.nuspec +++ /dev/null @@ -1,24 +0,0 @@ - - - - CSF.Screenplay.Reporting.Html - 0.8.0-alpha - CSF.Screenplay.Reporting.Html - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - Extension to Screenplay reporting which creates preety HTML from test runs, including filtering functionality. - Copyright 2017 - - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/HtmlReportWriter.cs b/CSF.Screenplay.Reporting.Html/HtmlReportWriter.cs deleted file mode 100644 index bf72c461..00000000 --- a/CSF.Screenplay.Reporting.Html/HtmlReportWriter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.IO; -using CSF.Screenplay.Reporting.Models; -using CSF.Zpt; -using CSF.Zpt.Rendering; - -namespace CSF.Screenplay.Reporting -{ - public class HtmlReportWriter : IReportWriter - { - readonly TextWriter writer; - readonly IObjectFormattingService formattingService; - readonly IZptDocumentFactory documentFactory; - - public void Write(Report report) - { - var doc = GetDocument(); - var emptyDoc = GetDocument(); - var model = GetDocumentModel(report, emptyDoc); - - doc.Render(model, writer); - } - - IZptDocument GetDocument() - { - using(var stream = GetDocumentStream()) - { - return documentFactory.CreateDocument(stream, RenderingMode.Html); - } - } - - ReportDocument GetDocumentModel(Report reportModel, IZptDocument document) - => new ReportDocument(reportModel, formattingService, document); - - Stream GetDocumentStream() - => Views.ViewProvider.GetDocumentTemplate(); - - public HtmlReportWriter(TextWriter writer, IObjectFormattingService formattingService) - { - if(formattingService == null) - throw new ArgumentNullException(nameof(formattingService)); - if(writer == null) - throw new ArgumentNullException(nameof(writer)); - - this.writer = writer; - this.formattingService = formattingService; - documentFactory = new ZptDocumentFactory(); - } - } -} diff --git a/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs b/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs deleted file mode 100644 index a651dfab..00000000 --- a/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.Zpt; -using CSF.Zpt.Metal; - -namespace CSF.Screenplay.Reporting.Models -{ - public class ReportDocument - { - const string - SuccessClass = "success", - FailureClass = "failure", - InconclusiveClass = "inconclusive", - AbilityClass = "ability", - PerformanceClass = "performance", - AbilityMacro = "ability", - PerformanceWithResultMacro = "performance_success_result", - PerformanceWithExceptionMacro = "performance_failure_exception", - PerformanceMacro = "performance"; - - readonly IObjectFormattingService formattingService; - readonly IZptDocument document; - readonly Report report; - - public Report Report => report; - - public IZptDocument Template => document; - - public IMetalMacroContainer GetMacros() - { - var output = Template.GetMacros(); - return output; - } - - public string Format(object obj) => formattingService.Format(obj); - - public string GetOutcomeClass(Scenario scenario) - { - if(scenario == null) return String.Empty; - var outcome = GetOutcomeClass(scenario.IsSuccess, scenario.IsFailure); - return $"scenario {outcome}"; - } - - public string GetOutcomeClass(Feature feature) - { - if(feature == null) return String.Empty; - var outcome = GetOutcomeClass(feature.IsSuccess, feature.HasFailures); - return $"feature {outcome}"; - } - - public string GetOutcomeClass(Reportable reportable) - { - - switch(reportable.Outcome) - { - case PerformanceOutcome.Success: - case PerformanceOutcome.SuccessWithResult: - return GetOutcomeClass(true, false); - - default: - return GetOutcomeClass(false, true); - } - } - - string GetOutcomeClass(bool success, bool failure) - { - if(success) return SuccessClass; - if(failure) return FailureClass; - return InconclusiveClass; - } - - public string GetReportableClass(Reportable reportable) - { - if(reportable == null) return String.Empty; - - if(reportable is GainAbility) - return AbilityClass; - - if(reportable is Performance) - return PerformanceClass; - - return String.Empty; - } - - public string GetMacroName(Reportable reportable) - { - if(reportable == null) return null; - - if(reportable is GainAbility) - return GetMacroName((GainAbility) reportable); - - if(reportable is Performance) - return GetMacroName((Performance) reportable); - - return null; - } - - string GetMacroName(GainAbility reportable) => AbilityMacro; - - string GetMacroName(Performance reportable) - { - switch(reportable.Outcome) - { - case PerformanceOutcome.SuccessWithResult: - return PerformanceWithResultMacro; - - case PerformanceOutcome.FailureWithException: - return PerformanceWithExceptionMacro; - - default: - return PerformanceMacro; - } - } - - public ReportDocument(Report report, - IObjectFormattingService formattingService, - IZptDocument document) - { - if(document == null) - throw new ArgumentNullException(nameof(document)); - if(formattingService == null) - throw new ArgumentNullException(nameof(formattingService)); - if(report == null) - throw new ArgumentNullException(nameof(report)); - - this.report = report; - this.formattingService = formattingService; - this.document = document; - } - } -} diff --git a/CSF.Screenplay.Reporting.Html/Properties/AssemblyInfo.cs b/CSF.Screenplay.Reporting.Html/Properties/AssemblyInfo.cs deleted file mode 100644 index 7962cd2c..00000000 --- a/CSF.Screenplay.Reporting.Html/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.Screenplay.Reporting.Html")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.Screenplay.Reporting.Html/StreamSourceInfo.cs b/CSF.Screenplay.Reporting.Html/StreamSourceInfo.cs deleted file mode 100644 index 4dd074fe..00000000 --- a/CSF.Screenplay.Reporting.Html/StreamSourceInfo.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using CSF.Zpt.Rendering; - -namespace CSF.Screenplay.Reporting -{ - public class StreamSourceInfo : ISourceInfo - { - readonly string name; - - public string FullName => name; - - public bool Equals(ISourceInfo other) - { - return (other is StreamSourceInfo) && ((StreamSourceInfo) other).FullName == FullName; - } - - public object GetContainer() => null; - - public string GetRelativeName(string root) => FullName; - - public StreamSourceInfo(string name) - { - if(name == null) - throw new ArgumentNullException(nameof(name)); - - this.name = name; - } - } -} diff --git a/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt b/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt deleted file mode 100644 index 6365ac69..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt +++ /dev/null @@ -1,875 +0,0 @@ - - -Screenplay report - - - - - - -
-

Screenplay report

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessFailureTotal
Features538
Scenarios102030
-
-
-
- -
    -
  • -
    -
    - - Another.Feature.Identifier -
    -

    - - Another feature name -

    -
    -
      -
    • -
      -
      - - Feature2.Scenario1.Identifier.Here -
      -

      - - A scenario in a different feature -

      -
      -
        -
      1. - -
        -

        - Given - the body of this reportable -

        - -
        -
      2. -
      3. - -
        -

        - Given - Joe is able to browse the web -

        -
        -
      4. -
      5. - -
        -

        - When - Joe attempts to do a thing -

        -
        - -
          -
        1. - -

          Child reportable content

          -
          -
        2. -
        -
        -
        -
      6. -
      7. - -
        -

        - Then - Joe reads some kind of value -

        -
        -
        -

        - Result - The performance result -

        -
        -
        -
        -
      8. -
      9. - -
        -

        - Then - Joe does something that fails -

        -
        -
        -

        - Failed - with an exception -

        -
        Exception
        -  at My.Funky.Stack.Trace.Line1 > Something
        -  at My.Funky.Stack.Trace.Line2 > Something else
        -  at My.Funky.Stack.Trace.Line3 > Something different
        -
        -
        -
        -
      10. -
      -
    • -
    -
  • -
  • -
    -
    - - Feature.Identifier.Here -
    -

    - - This is where the feature name goes -

    -
    -
      -
    • -
      -
      - - Scenario.Identifier.Here -
      -

      - - My very interesting scenario -

      -
      -
        -
      1. -
        -

        - Given - Reportable content -

        -
        -
      2. -
      -
    • -
    • -
      -
      - - Feature1.Scenario2.Identifier.Here -
      -

      - - A second scenario in the feature -

      -
      -
        -
      1. -
        -

        - Given - Reportable content -

        -
        -
      2. -
      -
    • -
    • -
      -
      - - Feature1.Scenario3.Identifier.Here -
      -

      - - A third scenario in the feature -

      -
      -
        -
      1. -
        -

        - Given - Reportable content -

        -
        -
      2. -
      -
    • -
    -
  • -
-
-
-

- This report was created at - 12:40:33 - on - 2011-03-01 - using CSF.Screenplay. -

-
- - diff --git a/CSF.Screenplay.Reporting.Html/Views/Filter.js b/CSF.Screenplay.Reporting.Html/Views/Filter.js deleted file mode 100644 index 448b291c..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/Filter.js +++ /dev/null @@ -1,118 +0,0 @@ -(function(window, $, report, undefined) { - 'use strict'; - - function getFilterClassName(level, type) - { - return 'filter_' + level + '_' + type; - } - - function setSummaryTableStyle(level, type, active) - { - var - selector = 'tr.' + level + ' .' + type, - element = $(selector, this.summaryTable); - if(active) - element.addClass('active'); - else - element.removeClass('active'); - } - - function clearFilter(level) - { - var types = [ 'success', 'failing', 'total' ]; - for(var i = 0; i < types.length; i++) - { - var type = types[i]; - this.reportBody.removeClass(getFilterClassName(level, type)); - setSummaryTableStyle.apply(this, [ level, type, false ]) - } - } - - function markFirstAndLastFeatures() - { - $('.feature', this.reportBody) - .removeClass('first_visible') - .removeClass('last_visible'); - - $('.feature:visible:first', this.reportBody) - .addClass('first_visible'); - - $('.feature:visible:last', this.reportBody) - .addClass('last_visible'); - } - - function markFirstAndLastScenarios() - { - $('.feature .scenario', this.reportBody) - .removeClass('first_visible') - .removeClass('last_visible'); - - $('.feature', this.reportBody) - .each(function(id, feature) { - var $feature = $(feature); - $('.scenario:visible:first', $feature) - .addClass('first_visible'); - - $('.scenario:visible:last', $feature) - .addClass('last_visible'); - }); - } - - function applyFilter(level, type) - { - clearFilter.apply(this, [ level ]); - this.reportBody.addClass(getFilterClassName(level, type)); - setSummaryTableStyle.apply(this, [ level, type, true ]) - if(level === 'features') - { - markFirstAndLastFeatures.apply(this); - } - if(level === 'scenarios') - { - markFirstAndLastScenarios.apply(this); - } - } - - function bindEvents() - { - var self = this; - - self.summaryTable.on('click', 'td', function() { - var - $this = $(this), - cellClass = $this.attr('class'), - rowClass = $this.parent().attr('class'); - - if($this.hasClass('active')) return; - - applyFilter.apply(self, [ rowClass, cellClass ]); - }); - } - - function activateTotals() - { - applyFilter.apply(this, [ 'features', 'total' ]); - applyFilter.apply(this, [ 'scenarios', 'total' ]); - } - - function addHelpText() - { - this.summaryTable.before('

Click on the totals to filter the report

'); - } - - function FilterCtor() - { - this.summaryTable = $('#summary_table'); - this.reportBody = $('section.report'); - } - - FilterCtor.prototype.init = function() - { - bindEvents.apply(this); - activateTotals.apply(this); - addHelpText.apply(this); - } - - report.Filter = FilterCtor; - -}(window, window.jQuery || null, report = window.report || {})); \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/Views/Folding.js b/CSF.Screenplay.Reporting.Html/Views/Folding.js deleted file mode 100644 index 3a929a7a..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/Folding.js +++ /dev/null @@ -1,50 +0,0 @@ -(function(window, $, report, undefined) { - 'use strict'; - - var collapsed = 'collapsed'; - - function bindEvents() - { - var self = this; - - self.reportBody.on('click', self.selectors.featureHeaders, function() { - var $this = $(this); - $this.parent().toggleClass(collapsed); - }) - - self.reportBody.on('click', self.selectors.scenarioHeaders, function() { - var $this = $(this); - $this.parent().toggleClass(collapsed); - }) - } - - function collapseAll() - { - var self = this; - - $(self.selectors.features, self.reportBody) - .add(self.selectors.scenarios, self.reportBody) - .addClass(collapsed); - } - - function FoldingCtor() - { - this.reportBody = $('section.report'); - - this.selectors = { - featureHeaders: '.feature>header', - scenarioHeaders: '.scenario>header', - features: '.feature', - scenarios: '.scenario', - }; - } - - FoldingCtor.prototype.init = function() - { - bindEvents.apply(this); - collapseAll.apply(this); - } - - report.Folding = FoldingCtor; - -}(window, window.jQuery || null, report = window.report || {})); \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/Views/PageInteractions.js b/CSF.Screenplay.Reporting.Html/Views/PageInteractions.js deleted file mode 100644 index 8d12fc93..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/PageInteractions.js +++ /dev/null @@ -1,20 +0,0 @@ -(function(report, undefined) { - 'use strict'; - - function PageInteractionsCtor() - { - var self = this; - - self.filter = new report.Filter(); - self.folding = new report.Folding(); - } - - PageInteractionsCtor.prototype.init = function() - { - this.filter.init(); - this.folding.init(); - } - - report.PageInteractions = PageInteractionsCtor; - -}(report = window.report || {})); \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/Views/ViewProvider.cs b/CSF.Screenplay.Reporting.Html/Views/ViewProvider.cs deleted file mode 100644 index 1d76cca2..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/ViewProvider.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Reflection; -using System.IO; -using System.Linq; -using CSF.Reflection; - -namespace CSF.Screenplay.Reporting.Views -{ - public static class ViewProvider - { - const string DocumentTemplateName = "DocumentTemplate.pt"; - - internal static Stream GetDocumentTemplate() - => ThisAssembly.GetManifestResourceStream(DocumentTemplateName); - - static Assembly ThisAssembly => Assembly.GetExecutingAssembly(); - } -} diff --git a/CSF.Screenplay.Reporting.Html/Views/interactions.css b/CSF.Screenplay.Reporting.Html/Views/interactions.css deleted file mode 100644 index e4e3f938..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/interactions.css +++ /dev/null @@ -1,87 +0,0 @@ -html.js body>header .summary .help_text { - display: block; -} -html.js #summary_table td { - cursor: pointer; -} -html.js #summary_table td.active { - background: #FFD; -} - -html.js .feature.collapsed .scenarios, -html.js .scenario.collapsed .reportables { - display: none; -} -html.js .feature.collapsed { - border-bottom: 1px solid #A9A9A9; -} -html.js .feature.collapsed.last_visible { - border-bottom-width: 0; -} -html.js .feature.collapsed header, -html.js .scenario.collapsed header { - border-bottom: 0 none; -} -html.js .feature:last-child.collapsed header { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; -} -html.js .feature>header, -html.js .scenario>header { - cursor: pointer; -} -.feature>header:before, -.scenario>header:before { - float: left; - margin-left: -1.2em; - font-size: 90%; - vertical-align: middle; - color: #999; - padding: 0 0.2em; - width: 1em; - display: block; - text-align: center; -} -.feature>header:before { - line-height: 1.4em; -} -.scenario>header:before { - line-height: 1.1em; -} -html.js .feature>header:before, -html.js .scenario>header:before { - content: '▼'; -} -html.js .feature.collapsed>header:before, -html.js .scenario.collapsed>header:before { - content: '▶'; -} - -html.js section.report.filter_features_success .feature.failure, -html.js section.report.filter_features_failing .feature.success, -html.js section.report.filter_scenarios_success .scenario.failure, -html.js section.report.filter_scenarios_failing .scenario.success { - display: none; -} -html.js .feature.first_visible, -html.js .feature.first_visible>header { - border-top-left-radius: 6px; - border-top-right-radius: 6px; -} -html.js .feature.last_visible { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-bottom-width: 0; -} -html.js .feature.last_visible .scenario.last_visible { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-bottom-width: 0; -} -html.js .scenario.last_visible, -html.js .scenario.last_visible>header { -} -.feature.last_visible .scenario.last_visible .reportable:last-child { - border-bottom-right-radius: 6px; - padding-bottom: 0.4em; -} \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/Views/jquery-3.2.1.slim.min.js b/CSF.Screenplay.Reporting.Html/Views/jquery-3.2.1.slim.min.js deleted file mode 100644 index 105d00e6..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/jquery-3.2.1.slim.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v3.2.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector | (c) JS Foundation and other contributors | jquery.org/license */ -!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a); -}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S),a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}}),r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var _a,ab=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return T(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?_a:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),_a={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ab[b]||r.find.attr;ab[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ab[g],ab[g]=e,e=null!=c(a,b,d)?g:null,ab[g]=f),e}});var bb=/^(?:input|select|textarea|button)$/i,cb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function db(a){var b=a.match(L)||[];return b.join(" ")}function eb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,eb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=eb(c),d=1===c.nodeType&&" "+db(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=db(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,eb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=eb(c),d=1===c.nodeType&&" "+db(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=db(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,eb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=eb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+db(eb(c))+" ").indexOf(b)>-1)return!0;return!1}});var fb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(fb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:db(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var gb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!gb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,gb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var hb=/\[\]$/,ib=/\r?\n/g,jb=/^(?:submit|button|image|reset|file)$/i,kb=/^(?:input|select|textarea|keygen)/i;function lb(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||hb.test(a)?d(a,e):lb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d); -});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)lb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)lb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&kb.test(this.nodeName)&&!jb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ib,"\r\n")}}):{name:b.name,value:c.replace(ib,"\r\n")}}).get()}}),r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="
",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=C.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=qa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),b=f.ownerDocument,c=b.documentElement,e=b.defaultView,{top:d.top+e.pageYOffset-c.clientTop,left:d.left+e.pageXOffset-c.clientLeft}):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),B(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||ra})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return T(this,function(a,d,e){var f;return r.isWindow(a)?f=a:9===a.nodeType&&(f=a.defaultView),void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Pa(o.pixelPosition,function(a,c){if(c)return c=Oa(a,b),Ma.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return T(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.holdReady=function(a){a?r.readyWait++:r.ready(!0)},r.isArray=Array.isArray,r.parseJSON=JSON.parse,r.nodeName=B,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var mb=a.jQuery,nb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=nb),b&&a.jQuery===r&&(a.jQuery=mb),r},b||(a.jQuery=a.$=r),r}); diff --git a/CSF.Screenplay.Reporting.Html/Views/page.css b/CSF.Screenplay.Reporting.Html/Views/page.css deleted file mode 100644 index 9a027bce..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/page.css +++ /dev/null @@ -1,80 +0,0 @@ -body { - font-family: "DejaVu Sans", "Droid Sans", "Verdana", Arial, sans; - padding: 0.6em; -} -body>header { - border-bottom: 1px solid #CCC; - margin-bottom: 1em; - padding-bottom: 0.1em; - padding-right: 0.1em; - overflow: auto; -} -body>header h1 { - font-size: 200%; - line-height: 140%; - color: #999; - float: left; -} -body>header .summary { - float: right; - font-size: 85%; -} -.hidden { - display: none; -} -body>header .summary .help_text { - float: left; - color: #666; - max-width: 10em; - line-height: 140%; - margin-top: 1em; - margin-right: 1em; - display: none; -} -#summary_table { - float: right; -} -#summary_table col.success, -#summary_table col.failing, -#summary_table col.total { - width: 5em; -} -#summary_table tbody td, -#summary_table tbody th { - padding: 0.4em 0; -} -#summary_table td { - text-align: center; - border: 1px solid #CCC; -} -#summary_table th { - font-weight: bold; - color: #666; -} -#summary_table thead th { - padding-bottom: 0.2em; -} -#summary_table tbody th { - text-align: right; - padding-right: 0.2em; -} - - -body>footer { - border-top: 1px solid #CCC; - margin-top: 1em; - line-height: 140%; - font-size: 90%; - color: #999; -} -body>footer .timestamp, -body>footer .datestamp { - color: #444; -} -body>footer a { - text-decoration: none; - color: #337; -} -body>footer a:hover { - border-bottom: 1px solid #337; -} diff --git a/CSF.Screenplay.Reporting.Html/Views/report-interactions.js b/CSF.Screenplay.Reporting.Html/Views/report-interactions.js deleted file mode 100644 index b1438078..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/report-interactions.js +++ /dev/null @@ -1,12 +0,0 @@ -(function($, report, undefined) { - 'use strict'; - - if(!$) return; - - $(function() { - $('html').addClass('js'); - var page = new report.PageInteractions(); - page.init(); - }) - -}(window.jQuery || null, report = window.report || {})); \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/Views/reports.css b/CSF.Screenplay.Reporting.Html/Views/reports.css deleted file mode 100644 index 832229c1..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/reports.css +++ /dev/null @@ -1,146 +0,0 @@ -.report .features { - border-radius: 6px; - border: 1px solid #EB9; -} -.feature { - background-color: #E0E0E0; -} -.feature:first-child, -.feature:first-child>header { - border-top-left-radius: 6px; - border-top-right-radius: 6px; -} -.feature:last-child { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-bottom-width: 0; -} -.feature>header { - padding: 0.8em 0.4em 0.4em 1.4em; - background: linear-gradient(to bottom, #FFF 0%,#E0E0E0 100%); - overflow: auto; - border-bottom: 1px solid #B9B9B9; -} -.feature.failure>header { - background: linear-gradient(to bottom, #FAA 0%,#E0E0E0 100%); -} -.feature>header .identifier { - font-size: 80%; - color: #777; - float: right; -} -.feature>header .name { - font-size: 140%; - float: left; -} -.scenario>header { - padding: 1.4em 0.4em 0.4em 2em; - background: linear-gradient(to bottom, #E0E0E0 0%,#D0D0D0 100%); - overflow: auto; -} -.scenario.failure>header { - background: linear-gradient(to bottom, #F99 0%,#D0D0D0 100%); -} -.scenario { - border-bottom: 1px solid #B9B9B9; - background-color: #D0D0D0; -} -.feature:last-child .scenario:last-child { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; -} -.scenario>header .identifier { - font-size: 80%; - color: #777; - float: right; -} -.scenario>header .name { - font-size: 110%; - float: left; - font-style: italic; -} -.scenario>.reportables { - font-size: 90%; -} -.scenario>.reportables>.reportable { - background: #E0E0E0; - margin-left: 6.4em; - border-left: 1px solid #B0B0B0; -} -.scenario>.reportables>.reportable .failure { - color: #900; - font-style: italic; -} -.scenario>.reportables>.reportable .performance:before, -.scenario>.reportables>.reportable .ability:before { - float: right; - font-size: 110%; - margin: 0.1em 0.6em 0 0.2em; - padding-top: 0.2em; - line-height: 140%; - vertical-align: middle; -} -.scenario>.reportables>.reportable .failure:before { - content: "✘"; - color: #900; -} -.scenario>.reportables>.reportable .success:before { - content: "✔"; - color: #999; -} -.scenario>.reportables>.reportable .failure .additional_content { - color: #000; - font-style: normal; -} -.feature:last-child .scenario:last-child .reportable:last-child { - border-bottom-right-radius: 6px; - padding-bottom: 0.4em; -} -.reportable { - margin-left: 0; -} -.reportable .reportables { - padding-left: 2em; - margin-top: -0.4em; -} -.reportable .description { - overflow: auto; - padding: 0.4em 0; - line-height: 140%; -} -.scenario>.reportables>.reportable>* { - margin-left: -3.6em; -} -.reportable .description .performance_type { - display: block; - float: left; - min-width: 4em; - font-weight: bold; -} -.reportable .description .body { - display: block; - float: left; -} -.reportable .additional_content { - margin: 0.4em 0 0 4em; -} -.reportable .reportable .additional_content { - margin-left: 0; -} -.reportable .extended_content { - font-size: 90%; - line-height: 120%; - padding-bottom: 0.6em; -} -.reportable .extended_content strong { - font-weight: bold; -} -.reportable .extended_content pre { - font-family: "Droid Sans Mono", "DejaVu Sans Mono", "Lucida Console", monospace; - margin-right: 0.4em; - background: #D0D0D0; - border: 1px solid #B0B0B0; - padding: 0.2em; - max-height: 15em; - overflow: auto; -} diff --git a/CSF.Screenplay.Reporting.Html/Views/reset.css b/CSF.Screenplay.Reporting.Html/Views/reset.css deleted file mode 100644 index 9ce89e8b..00000000 --- a/CSF.Screenplay.Reporting.Html/Views/reset.css +++ /dev/null @@ -1,48 +0,0 @@ -/* http://meyerweb.com/eric/tools/css/reset/ - v2.0 | 20110126 - License: none (public domain) -*/ - -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -/* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; -} -body { - line-height: 1; -} -ol, ul { - list-style: none; -} -blockquote, q { - quotes: none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} \ No newline at end of file diff --git a/CSF.Screenplay.Reporting.Html/app.config b/CSF.Screenplay.Reporting.Html/app.config deleted file mode 100644 index 51df5c29..00000000 --- a/CSF.Screenplay.Reporting.Html/app.config +++ /dev/null @@ -1,46 +0,0 @@ - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CSF.Screenplay.Reporting.Html/packages.config b/CSF.Screenplay.Reporting.Html/packages.config deleted file mode 100644 index 2d0c1285..00000000 --- a/CSF.Screenplay.Reporting.Html/packages.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.Reporting/Builders/PerformanceBuilder.cs b/CSF.Screenplay.Reporting/Builders/PerformanceBuilder.cs deleted file mode 100644 index 4ae4316f..00000000 --- a/CSF.Screenplay.Reporting/Builders/PerformanceBuilder.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting.Builders -{ - /// - /// Builder type which creates a instance. - /// - public class PerformanceBuilder - { - readonly IList reportables; - - /// - /// Gets or sets the . - /// - /// The type of the performance. - public PerformanceType PerformanceType { get; set; } - - /// - /// Gets or sets the actor. - /// - /// The actor. - public INamed Actor { get; set; } - - /// - /// Gets or sets the performable. - /// - /// The performable. - public IPerformable Performable { get; set; } - - /// - /// Gets or sets a value indicating whether this - /// has a result. - /// - /// true if has result; otherwise, false. - public bool HasResult { get; set; } - - /// - /// Gets or sets the result. - /// - /// The result. - public object Result { get; set; } - - /// - /// Gets or sets a value indicating whether this - /// is a failure. - /// - /// true if is failure; otherwise, false. - public bool IsFailure { get; set; } - - /// - /// Gets or sets the exception. - /// - /// The exception. - public Exception Exception { get; set; } - - /// - /// Gets a collection of child reportables. - /// - /// The reportables. - public IList Reportables => reportables; - - /// - /// Builds and returns a from the state of the current instance. - /// - /// The performance. - public Performance GetPerformance() - { - return new Performance(Actor, - GetOutcome(), - Performable, - PerformanceType, - Result, - Exception, - Reportables.ToArray()); - } - - PerformanceOutcome GetOutcome() - { - if(IsFailure && Exception != null) - return PerformanceOutcome.FailureWithException; - - if(IsFailure) - return PerformanceOutcome.Failure; - - if(HasResult) - return PerformanceOutcome.SuccessWithResult; - - return PerformanceOutcome.Success; - } - - /// - /// Initializes a new instance of the class. - /// - public PerformanceBuilder() - { - reportables = new List(); - } - } -} diff --git a/CSF.Screenplay.Reporting/Builders/ReportBuilder.cs b/CSF.Screenplay.Reporting/Builders/ReportBuilder.cs deleted file mode 100644 index 6e0f8b0f..00000000 --- a/CSF.Screenplay.Reporting/Builders/ReportBuilder.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting.Builders -{ - /// - /// Builder type which creates instances of . - /// - public class ReportBuilder - { - readonly IReportFactory reportFactory; - readonly ConcurrentDictionary scenarios; - - /// - /// Begins reporting upon a new scenario. - /// - /// The friendly scenario name. - /// The feature name. - /// The uniquely identifying name for the test. - /// The uniquely identifying name for the feature. - /// The screenplay scenario identity. - public void BeginNewScenario(string idName, - string friendlyName, - string featureName, - string featureId, - Guid scenarioId) - { - var success = scenarios.TryAdd(scenarioId, new ScenarioBuilder(idName, friendlyName, featureName, featureId)); - if(!success) - throw new InvalidOperationException("The current scenario already exists in the current builder instance"); - } - - /// - /// Reports the end of a scenario. - /// - /// If set to false then the scenario is marked as a failure. - /// The screenplay scenario identity. - public void EndScenario(bool? outcome, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.Finalise(outcome); - } - - /// - /// Begins reporting of a new performable. - /// - /// Actor. - /// Performable. - /// The screenplay scenario identity. - public void BeginPerformance(INamed actor, Performables.IPerformable performable, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.BeginPerformance(actor, performable); - } - - /// - /// Begins reporting of a performance of a given type. - /// - /// Performance type. - /// The screenplay scenario identity. - public void BeginPerformanceType(PerformanceType performanceType, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.BeginPerformanceType(performanceType); - } - - /// - /// Records that the current performable has received a result. - /// - /// Performable. - /// Result. - /// The screenplay scenario identity. - public void RecordResult(Performables.IPerformable performable, object result, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.RecordResult(performable, result); - } - - /// - /// Records that the current performable has failed with an exception. - /// - /// Performable. - /// Exception. - /// The screenplay scenario identity. - public void RecordFailure(Performables.IPerformable performable, Exception exception, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.RecordFailure(performable, exception); - } - - /// - /// Records that the current performable has completed successfully. - /// - /// Performable. - /// The screenplay scenario identity. - public void RecordSuccess(Performables.IPerformable performable, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.RecordSuccess(performable); - } - - /// - /// Ends the performance of the current type. - /// - public void EndPerformanceType(Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.EndPerformanceType(); - } - - /// - /// Reports that the given actor has gained the given ability. - /// - /// Actor. - /// Ability. - /// The screenplay scenario identity. - public void GainAbility(INamed actor, IAbility ability, - Guid scenarioId) - { - var scenario = GetScenario(scenarioId); - scenario.GainAbility(actor, ability); - } - - /// - /// Builds and returns the report from the current instance. - /// - /// The report. - public Report GetReport() - { - var builtScenarios = scenarios.Values.Select(x => x.GetScenario()); - return reportFactory.GetReport(builtScenarios.ToArray()); - } - - ScenarioBuilder GetScenario(Guid identity) - { - ScenarioBuilder scenario; - if(!scenarios.TryGetValue(identity, out scenario)) - throw new InvalidOperationException("There is no matching scenario in the current builder."); - - return scenario; - } - - /// - /// Initializes a new instance of the class. - /// - public ReportBuilder() : this(new ReportFactory()) { } - - /// - /// Initializes a new instance of the class. - /// - /// Report factory - public ReportBuilder(IReportFactory reportFactory) - { - if(reportFactory == null) - throw new ArgumentNullException(nameof(reportFactory)); - - this.reportFactory = reportFactory; - scenarios = new ConcurrentDictionary(); - } - } -} diff --git a/CSF.Screenplay.Reporting/Builders/ScenarioBuilder.cs b/CSF.Screenplay.Reporting/Builders/ScenarioBuilder.cs deleted file mode 100644 index f51c190f..00000000 --- a/CSF.Screenplay.Reporting/Builders/ScenarioBuilder.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting.Builders -{ - /// - /// Builder type for the reporting on a single Screenplay Scenario. - /// - public class ScenarioBuilder - { - readonly Scenario scenario; - readonly Stack builderStack; - PerformanceType currentPerformanceType; - bool finalised; - - /// - /// Finalise the current scenario, recording whether or not it was a success. - /// - /// If set to true success. - public void Finalise(bool? outcome) - { - EnsureNotFinalised(); - finalised = true; - scenario.Outcome = outcome; - } - - /// - /// Gets the underlying scenario report model. - /// - /// The scenario. - public Scenario GetScenario() => scenario; - - /// - /// Begins reporting of a new performable. - /// - /// Actor. - /// Performable. - public void BeginPerformance(INamed actor, Performables.IPerformable performable) - { - EnsureNotFinalised(); - var builder = new PerformanceBuilder { - Performable = performable, - Actor = actor, - PerformanceType = currentPerformanceType, - }; - AddPerformanceBuilder(builder); - } - - /// - /// Begins reporting of a performance of a given type. - /// - /// Performance type. - public void BeginPerformanceType(PerformanceType performanceType) - { - EnsureNotFinalised(); - performanceType.RequireDefinedValue(nameof(performanceType)); - currentPerformanceType = performanceType; - } - - /// - /// Records that the current performable has received a result. - /// - /// Performable. - /// Result. - public void RecordResult(Performables.IPerformable performable, object result) - { - EnsureNotFinalised(); - var builder = PeekCurrentBuilder(performable); - - builder.HasResult = true; - builder.Result = result; - } - - /// - /// Records that the current performable has failed with an exception. - /// - /// Performable. - /// Exception. - public void RecordFailure(Performables.IPerformable performable, Exception exception) - { - EnsureNotFinalised(); - var builder = PeekCurrentBuilder(performable); - - builder.IsFailure = true; - builder.Exception = exception; - - FinalisePerformance(performable); - } - - /// - /// Records that the current performable has completed successfully. - /// - /// Performable. - public void RecordSuccess(Performables.IPerformable performable) - { - EnsureNotFinalised(); - FinalisePerformance(performable); - } - - /// - /// Ends the performance of the current type. - /// - public void EndPerformanceType() - { - EnsureNotFinalised(); - currentPerformanceType = PerformanceType.Unspecified; - } - - /// - /// Reports that the given actor has gained the given ability. - /// - /// Actor. - /// Ability. - public void GainAbility(INamed actor, IAbility ability) - { - EnsureNotFinalised(); - var item = new GainAbility(actor, PerformanceOutcome.Success, ability, currentPerformanceType); - AddReportable(item); - } - - void EnsureNotFinalised() - { - if(finalised) - throw new InvalidOperationException("The scenario has already been finalised"); - } - - void AddReportable(Reportable item) - { - if(item == null) - throw new ArgumentNullException(nameof(item)); - - var list = GetCurrentReportables(); - list.Add(item); - } - - void FinalisePerformance(Performables.IPerformable performable) - { - var builder = PopCurrentBuilder(performable); - var performance = builder.GetPerformance(); - AddReportable(performance); - } - - void AddPerformanceBuilder(PerformanceBuilder builder) - { - if(builder == null) - throw new ArgumentNullException(nameof(builder)); - - builderStack.Push(builder); - } - - PerformanceBuilder PopCurrentBuilder(Performables.IPerformable expectedPerformable) - { - PeekCurrentBuilder(expectedPerformable); - return builderStack.Pop(); - } - - PerformanceBuilder PeekCurrentBuilder(Performables.IPerformable expectedPerformable = null) - { - if(builderStack.Count == 0 && expectedPerformable == null) - return null; - else if(builderStack.Count == 0) - throw new InvalidOperationException("An expected performable was specified but the builder stack was empty, this is not permitted."); - - var current = builderStack.Peek(); - - if(expectedPerformable == null) - return current; - - if(!ReferenceEquals(expectedPerformable, current.Performable)) - { - throw new ArgumentException("The expected performable must be the same as the current builder.", - nameof(expectedPerformable)); - } - - return current; - } - - IList GetCurrentReportables() - { - var currentBuilder = PeekCurrentBuilder(); - if(currentBuilder != null) - return currentBuilder.Reportables; - - return scenario.Reportables; - } - - /// - /// Initializes a new instance of the class. - /// - /// Identifier name. - /// Friendly name. - /// Feature name. - /// Feature identifier. - public ScenarioBuilder(string idName, - string friendlyName, - string featureName, - string featureId) - { - builderStack = new Stack(); - scenario = new Scenario(idName, friendlyName, featureName, featureId); - } - } -} diff --git a/CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.csproj b/CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.csproj deleted file mode 100644 index 325d6d35..00000000 --- a/CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.csproj +++ /dev/null @@ -1,102 +0,0 @@ - - - - Debug - AnyCPU - {18010B4E-22A7-4462-B057-7199B3386D48} - Library - CSF.Screenplay.Reporting - CSF.Screenplay.Reporting - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG;TRACE - prompt - 4 - bin\Debug\CSF.Screenplay.Reporting.xml - false - - - true - bin\Release - TRACE - prompt - 4 - bin\Release\CSF.Screenplay.Reporting.xml - false - - - - - ..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll - - - ..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.nuspec b/CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.nuspec deleted file mode 100644 index d65aae92..00000000 --- a/CSF.Screenplay.Reporting/CSF.Screenplay.Reporting.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - CSF.Screenplay.Reporting - 0.8.0-alpha - CSF.Screenplay.Reporting - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - Types related to the creation of reports from Screenplay performances - Copyright 2017 - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.Reporting/CastReportingHelper.cs b/CSF.Screenplay.Reporting/CastReportingHelper.cs deleted file mode 100644 index 81d117ab..00000000 --- a/CSF.Screenplay.Reporting/CastReportingHelper.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Sets up subscriptions between a and an . - /// - public class CastReportingHelper - { - readonly ICast cast; - readonly IReporter reporter; - readonly ScreenplayContext context; - - /// - /// Gets the cast. - /// - /// The cast. - protected ICast Cast => cast; - - /// - /// Gets the reporter. - /// - /// The reporter. - protected IReporter Reporter => reporter; - - /// - /// Gets the context. - /// - /// The context. - protected ScreenplayContext Context => context; - - /// - /// Sets up the subscriptions between the cast and the reporter. - /// - public virtual void SetupSubscriptions() - { - cast.ActorAdded += HandleActorAddedToCast; - cast.ActorCreated += HandleActorCreatedInCast; - } - - /// - /// Handles the creation of a new actor within an instance. - /// - /// Sender. - /// Arguments. - protected virtual void HandleActorCreatedInCast(object sender, ActorEventArgs args) - { - SubscribeReporter(args.Actor); - } - - /// - /// Handles the addition of a new actor to an instance. - /// - /// Sender. - /// Arguments. - protected virtual void HandleActorAddedToCast(object sender, ActorEventArgs args) - { - // Intentional no-op, method is here for subclasses to override. - } - - /// - /// Gets the from the current context and subscribes it to the given actor. - /// - /// Actor. - protected virtual void SubscribeReporter(IActor actor) - { - reporter.Subscribe(actor); - } - - /// - /// Initializes a new instance of the class. - /// - /// Cast. - /// Reporter. - /// The current context. - public CastReportingHelper(ICast cast, IReporter reporter, ScreenplayContext context) - { - if(reporter == null) - throw new ArgumentNullException(nameof(reporter)); - if(cast == null) - throw new ArgumentNullException(nameof(cast)); - if(context == null) - throw new ArgumentNullException(nameof(context)); - - - this.cast = cast; - this.reporter = reporter; - this.context = context; - } - } -} diff --git a/CSF.Screenplay.Reporting/IModelBuildingReporter.cs b/CSF.Screenplay.Reporting/IModelBuildingReporter.cs deleted file mode 100644 index 8d490090..00000000 --- a/CSF.Screenplay.Reporting/IModelBuildingReporter.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Implementation of an which creates a report model. - /// - public interface IModelBuildingReporter : IReporter - { - /// - /// Gets the report model. - /// - /// The report. - Report GetReport(); - } -} diff --git a/CSF.Screenplay.Reporting/IObjectFormatterRegistry.cs b/CSF.Screenplay.Reporting/IObjectFormatterRegistry.cs deleted file mode 100644 index a625b4ed..00000000 --- a/CSF.Screenplay.Reporting/IObjectFormatterRegistry.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Registry type which holds a collection of object formatters and provides access to them. - /// - public interface IObjectFormatterRegistry - { - /// - /// Adds a formatter to the collection. - /// - /// Formatter. - void AddFormatter(IObjectFormatter formatter); - - /// - /// Gets a collection of all of the registered formatters. - /// - /// The all formatters. - IReadOnlyCollection GetAllFormatters(); - } -} diff --git a/CSF.Screenplay.Reporting/IObjectFormattingService.cs b/CSF.Screenplay.Reporting/IObjectFormattingService.cs deleted file mode 100644 index 53ac94fa..00000000 --- a/CSF.Screenplay.Reporting/IObjectFormattingService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting -{ - /// - /// Formats an object into a human-readable string. - /// - public interface IObjectFormattingService - { - /// - /// Format the specified object. - /// - /// Object. - string Format(object obj); - } -} diff --git a/CSF.Screenplay.Reporting/IReportWriter.cs b/CSF.Screenplay.Reporting/IReportWriter.cs deleted file mode 100644 index 3f7023cb..00000000 --- a/CSF.Screenplay.Reporting/IReportWriter.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting -{ - /// - /// A service which can format and write the result of a Screenplay report to some kind of destination. - /// - public interface IReportWriter - { - /// - /// Write the specified report to the destination. - /// - /// Report model. - void Write(Report reportModel); - } -} diff --git a/CSF.Screenplay.Reporting/IReporter.cs b/CSF.Screenplay.Reporting/IReporter.cs deleted file mode 100644 index add6c999..00000000 --- a/CSF.Screenplay.Reporting/IReporter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Reporting -{ - /// - /// A service which is informed when actors gain abilities or perform any performable items. The reporter - /// is then responsible for publishing that information in some manner, such as to a - /// System.Diagnostics.TraceSource. - /// - public interface IReporter - { - /// - /// Subscribe to the given actor and report upon their actions. - /// - /// Actor. - void Subscribe(IActor actor); - - /// - /// Unsubscribe from the given actor; cease reporting upon their actions. - /// - /// Actor. - void Unsubscribe(IActor actor); - - /// - /// Subscribe to the specified test run. - /// - /// Test run. - void Subscribe(IProvidesTestRunEvents testRun); - - /// - /// Unsubscribe to the specified test run. - /// - /// Test run. - void Unsubscribe(IProvidesTestRunEvents testRun); - - /// - /// Subscribe to the specified scenario. - /// - /// Test run. - void Subscribe(IScreenplayScenario scenario); - - /// - /// Unsubscribe to the specified scenario. - /// - /// Test run. - void Unsubscribe(IScreenplayScenario scenario); - } -} diff --git a/CSF.Screenplay.Reporting/Models/Feature.cs b/CSF.Screenplay.Reporting/Models/Feature.cs deleted file mode 100755 index eb3c0b36..00000000 --- a/CSF.Screenplay.Reporting/Models/Feature.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Represents a single feature within a report (a logical grouping of scenarios - in NUnit terminology a TestFixture). - /// - public class Feature - { - readonly string id, friendlyName; - readonly IReadOnlyCollection scenarios; - - /// - /// Gets the identity of this feature. - /// - public string Id => id; - - /// - /// Gets the human-readable friendly-name of this feature. - /// - public string FriendlyName => friendlyName; - - /// - /// Gets a collection of the scenarios in the current feature. - /// - public IReadOnlyCollection Scenarios => scenarios; - - /// - /// Gets or sets a value indicating whether this contains any scenarios which are themselves failures. - /// - /// true if this feature contains any failures; otherwise, false. - public bool HasFailures => Scenarios.Any(x => x.IsFailure); - - /// - /// Gets or sets a value indicating whether every within this is a success. - /// - /// true if the feature contains only successful scenarios; otherwise, false. - public bool IsSuccess => Scenarios.All(x => x.IsSuccess); - - /// - /// Initialises a new instance of the class. - /// - /// - /// - /// - public Feature(string id, string friendlyName, IReadOnlyCollection scenarios) - { - if (id == null) throw new ArgumentNullException(nameof(id)); - if(scenarios == null) throw new ArgumentNullException(nameof(scenarios)); - - this.id = id; - this.friendlyName = friendlyName; - this.scenarios = scenarios; - } - } -} \ No newline at end of file diff --git a/CSF.Screenplay.Reporting/Models/GainAbility.cs b/CSF.Screenplay.Reporting/Models/GainAbility.cs deleted file mode 100644 index 8949ac0a..00000000 --- a/CSF.Screenplay.Reporting/Models/GainAbility.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// A report model item indicating that an actor has gained an ability. - /// - public class GainAbility : Reportable - { - readonly IAbility ability; - - /// - /// Gets the ability. - /// - /// The ability. - public virtual IAbility Ability => ability; - - /// - /// Initializes a new instance of the class. - /// - /// Actor. - /// Outcome. - /// Ability. - /// Performance type. - public GainAbility(INamed actor, - PerformanceOutcome outcome, - IAbility ability, - PerformanceType performanceType = PerformanceType.Unspecified) - : base(actor, outcome, performanceType) - { - if(ability == null) - throw new ArgumentNullException(nameof(ability)); - - this.ability = ability; - } - } -} diff --git a/CSF.Screenplay.Reporting/Models/IReportFactory.cs b/CSF.Screenplay.Reporting/Models/IReportFactory.cs deleted file mode 100755 index 4a079d38..00000000 --- a/CSF.Screenplay.Reporting/Models/IReportFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Factory service which creates instances of . - /// - public interface IReportFactory - { - /// - /// Creates and returns a instance. - /// - /// - /// - Report GetReport(IReadOnlyCollection scenarios); - } -} \ No newline at end of file diff --git a/CSF.Screenplay.Reporting/Models/Performance.cs b/CSF.Screenplay.Reporting/Models/Performance.cs deleted file mode 100644 index d2fcea9f..00000000 --- a/CSF.Screenplay.Reporting/Models/Performance.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// A report model item indicating that an actor has performed some kind of interaction. - /// - public class Performance : Reportable - { - readonly IPerformable performable; - readonly object result; - readonly Exception exception; - readonly IList children; - - /// - /// Gets the contained reportables. - /// - /// The reportables. - public virtual IList Reportables => children; - - /// - /// Gets a value indicating whether this performance has any child reportables or not. - /// - /// true if this performance has child reportables; otherwise, false. - public virtual bool HasReportables => Reportables != null && Reportables.Any(); - - /// - /// Gets a value indicating whether this performance has a result. - /// - /// true if this performance has a result; otherwise, false. - public virtual bool HasResult => Result != null; - - /// - /// Gets a value indicating whether this performance has an exception. - /// - /// true if this performance has an exception; otherwise, false. - public virtual bool HasException => Exception != null; - - /// - /// Gets a value indicating whether this performance has additional content (child reportables, a result or an - /// exception). - /// - /// true if this performance has additional content; otherwise, false. - public virtual bool HasAdditionalContent => HasReportables || HasResult || HasException; - - /// - /// Gets the performable associated with the current instance. - /// - /// The performable. - public virtual IPerformable Performable => performable; - - /// - /// Gets the result received from the performable. - /// - /// The result. - public virtual object Result => result; - - /// - /// Gets an exception raised by the performable. - /// - /// The exception. - public virtual Exception Exception => exception; - - /// - /// Initializes a new instance of the class. - /// - /// Actor. - /// Outcome. - /// Performable. - /// Performance type. - /// Result. - /// Exception. - /// Children. - public Performance(INamed actor, - PerformanceOutcome outcome, - IPerformable performable, - PerformanceType performanceType = PerformanceType.Unspecified, - object result = null, - Exception exception = null, - IList children = null) : base(actor, outcome, performanceType) - { - if(performable == null) - throw new ArgumentNullException(nameof(performable)); - - this.performable = performable; - this.result = result; - this.exception = exception; - - this.children = children?? new List(); - } - } -} diff --git a/CSF.Screenplay.Reporting/Models/PerformanceOutcome.cs b/CSF.Screenplay.Reporting/Models/PerformanceOutcome.cs deleted file mode 100644 index 956b5853..00000000 --- a/CSF.Screenplay.Reporting/Models/PerformanceOutcome.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Enumerates the possible outcomes of a performance. - /// - public enum PerformanceOutcome - { - /// - /// The performance was a success. - /// - Success, - - /// - /// The performance was a success and yielded a result. - /// - SuccessWithResult, - - /// - /// The performance was a failure. - /// - Failure, - - /// - /// The performance was a failure and has an associated exception. - /// - FailureWithException - } -} diff --git a/CSF.Screenplay.Reporting/Models/PerformanceType.cs b/CSF.Screenplay.Reporting/Models/PerformanceType.cs deleted file mode 100644 index 22b84e96..00000000 --- a/CSF.Screenplay.Reporting/Models/PerformanceType.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Enumerates the available types of performance. - /// - public enum PerformanceType - { - /// - /// An unspecified type of performance. - /// - Unspecified = 0, - - /// - /// A given (arrange) performance. - /// - Given, - - /// - /// A when (act) performance. - /// - When, - - /// - /// A then (assert) performance. - /// - Then - } -} diff --git a/CSF.Screenplay.Reporting/Models/Report.cs b/CSF.Screenplay.Reporting/Models/Report.cs deleted file mode 100644 index 71b89b7a..00000000 --- a/CSF.Screenplay.Reporting/Models/Report.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// The root of the report model, representing the report for an entire test run. - /// - public class Report - { - readonly IReadOnlyList features; - readonly DateTime timestamp; - - /// - /// Gets a collection of the scenarios in this report. - /// - /// The scenarios. - public virtual IReadOnlyList Features => features; - - /// - /// Gets the count of features (total) in this report. - /// - /// The feature count. - public virtual int TotalFeatureCount => Features.Count; - - /// - /// Gets the count of successful features in this report. - /// - /// The successful feature count. - public virtual int SuccessfulFeatureCount => Features.Count(x => x.IsSuccess); - - /// - /// Gets the count of failing features in this report. - /// - /// The failing feature count. - public virtual int FailingFeatureCount => Features.Count(x => x.HasFailures); - - /// - /// Gets the scenarios in the current report instance. - /// - /// The scenarios. - public virtual IReadOnlyList Scenarios => Features.SelectMany(x => x.Scenarios).ToArray(); - - /// - /// Gets the count of scenarios (total) in this report. - /// - /// The scenario count. - public virtual int TotalScenarioCount => Scenarios.Count; - - /// - /// Gets the count of successful scenarios in this report. - /// - /// The successful scenario count. - public virtual int SuccessfulScenarioCount => Scenarios.Count(x => x.IsSuccess); - - /// - /// Gets the count of failing scenarios in this report. - /// - /// The failing scenario count. - public virtual int FailingScenarioCount => Scenarios.Count(x => x.IsFailure); - - /// - /// Gets the timestamp for the creation of this report. - /// - /// The timestamp. - public virtual DateTime Timestamp => timestamp; - - /// - /// Initializes a new instance of the class. - /// - /// Features. - public Report(IReadOnlyList features) - { - if(features == null) - throw new ArgumentNullException(nameof(features)); - - this.features = features; - timestamp = DateTime.UtcNow; - } - - /// - /// Initializes a new instance of the class. - /// - /// Scenarios. - public Report(IReadOnlyList scenarios) - { - if(scenarios == null) - throw new ArgumentNullException(nameof(scenarios)); - - var feature = new Feature("Unspecified", "Unspecified", scenarios); - this.features = new [] { feature }; - timestamp = DateTime.UtcNow; - } - } -} diff --git a/CSF.Screenplay.Reporting/Models/ReportFactory.cs b/CSF.Screenplay.Reporting/Models/ReportFactory.cs deleted file mode 100755 index ca284054..00000000 --- a/CSF.Screenplay.Reporting/Models/ReportFactory.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Reporting.Builders; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Factory service which creates instances of . - /// - public class ReportFactory : IReportFactory - { - /// - /// Creates and returns a instance. - /// - /// - /// - public Report GetReport(IReadOnlyCollection scenarios) - { - if(scenarios == null) - throw new ArgumentNullException(nameof(scenarios)); - - var features = (from scenario in scenarios - group scenario by scenario.FeatureId - into featureGroups - let featureId = featureGroups.Key - select new Feature(featureId, - featureGroups.First().FeatureName, - featureGroups.OrderBy(x => x.FriendlyName).ToArray())) - .OrderBy(x => x.FriendlyName) - .ToArray(); - - return new Report(features); - } - } -} \ No newline at end of file diff --git a/CSF.Screenplay.Reporting/Models/Reportable.cs b/CSF.Screenplay.Reporting/Models/Reportable.cs deleted file mode 100644 index eb69e877..00000000 --- a/CSF.Screenplay.Reporting/Models/Reportable.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Base type of the report model. - /// - public class Reportable - { - readonly INamed actor; - readonly PerformanceOutcome outcome; - readonly PerformanceType performanceType; - - /// - /// Gets the actor. - /// - /// The actor. - public virtual INamed Actor => actor; - - /// - /// Gets the type of the performance. - /// - /// The type of the performance. - public virtual PerformanceType PerformanceType => performanceType; - - /// - /// Gets the outcome of the reported-upon action. - /// - /// The outcome. - public virtual PerformanceOutcome Outcome => outcome; - - /// - /// Initializes a new instance of the class. - /// - /// Actor. - /// Outcome. - /// Performance type. - public Reportable(INamed actor, - PerformanceOutcome outcome, - PerformanceType performanceType = PerformanceType.Unspecified) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - outcome.RequireDefinedValue(nameof(outcome)); - performanceType.RequireDefinedValue(nameof(performanceType)); - - this.actor = actor; - this.outcome = outcome; - this.performanceType = performanceType; - } - } -} diff --git a/CSF.Screenplay.Reporting/Models/Scenario.cs b/CSF.Screenplay.Reporting/Models/Scenario.cs deleted file mode 100644 index 0c9e33d0..00000000 --- a/CSF.Screenplay.Reporting/Models/Scenario.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CSF.Screenplay.Reporting.Models -{ - /// - /// Represents a single scenrio within a report (equivalent to a single test case, if not using Gherkin terminology). - /// - public class Scenario - { - const string UnknownFeatureId = "Unknown feature"; - - readonly string featureName, featureId, idName, friendlyName; - readonly IList children; - - /// - /// Gets the unique identifier name of the scenario. - /// - /// The identifier. - public virtual string Id => idName; - - /// - /// Gets the name of the scenario. - /// - /// The scenario name. - public virtual string FriendlyName => friendlyName; - - /// - /// Gets the name of the feature. - /// - /// The feature name. - public virtual string FeatureName => featureName; - - /// - /// Gets the identifier for the feature. - /// - /// The feature identifier. - public virtual string FeatureId => featureId; - - /// - /// Gets the contained reportables. - /// - /// The reportables. - public virtual IList Reportables => children; - - /// - /// Gets or sets the outcome for the test scenario. - /// - /// The outcome. - public virtual bool? Outcome { get; set; } - - /// - /// Gets or sets a value indicating whether this - /// is inconclusive (neither success nor failure). - /// - /// true if this scenario is inconclusive; otherwise, false. - public virtual bool IsInconclusive => !Outcome.HasValue; - - /// - /// Gets or sets a value indicating whether this - /// is a failure. - /// - /// true if this scenario is a failure; otherwise, false. - public virtual bool IsFailure => Outcome.HasValue && !Outcome.Value; - - /// - /// Gets a value indicating whether this is a success. - /// - /// true if is success; otherwise, false. - public virtual bool IsSuccess => Outcome.HasValue && Outcome.Value; - - /// - /// Gets a collection of the reportables contained within the current scenario. - /// - /// The reportables. - protected virtual IEnumerable FindReportables() - { - return Reportables.ToArray() - .Union(children.SelectMany(x => FindReportables(x))) - .ToArray(); - } - - /// - /// Gets a collection of the reportables contained within the given reportable. - /// - /// The reportables. - /// Current. - protected virtual IEnumerable FindReportables(Reportable current) - { - var performance = current as Performance; - if(performance == null) - return Enumerable.Empty(); - - return performance.Reportables.ToArray() - .Union(performance.Reportables.SelectMany(x => FindReportables(x))) - .ToArray(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The friendly scenario name. - /// The feature name. - /// The uniquely identifying name for the test. - /// The uniquely identifying name for the feature. - public Scenario(string idName, - string friendlyName = null, - string featureName = null, - string featureId = null) - { - if(idName == null) - throw new ArgumentNullException(nameof(idName)); - - this.idName = idName; - this.friendlyName = friendlyName; - this.featureName = featureName; - this.featureId = featureId?? UnknownFeatureId; - this.children = new List(); - } - } -} diff --git a/CSF.Screenplay.Reporting/NoOpReporter.cs b/CSF.Screenplay.Reporting/NoOpReporter.cs deleted file mode 100644 index 0ba046dc..00000000 --- a/CSF.Screenplay.Reporting/NoOpReporter.cs +++ /dev/null @@ -1,319 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Reporting -{ - /// - /// A reporter which does nothing. This is a suitable base type for reporter implementations. - /// - public class NoOpReporter : IReporter - { - #region Actor-related handlers - - /// - /// Subscribe to the given actor and report upon their actions. - /// - /// Actor. - public virtual void Subscribe(IActor actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - actor.GainedAbility += OnGainAbility; - actor.BeginPerformance += OnBegin; - actor.EndPerformance += OnSuccess; - actor.PerformanceResult += OnResult; - actor.PerformanceFailed += OnFailure; - actor.BeginGiven += OnBeginGiven; - actor.EndGiven += OnEndGiven; - actor.BeginWhen += OnBeginWhen; - actor.EndWhen += OnEndWhen; - actor.BeginThen += OnBeginThen; - actor.EndThen += OnEndThen; - } - - /// - /// Unsubscribe from the given actor; cease reporting upon their actions. - /// - /// Actor. - public virtual void Unsubscribe(IActor actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - actor.GainedAbility -= OnGainAbility; - actor.BeginPerformance -= OnBegin; - actor.EndPerformance -= OnSuccess; - actor.PerformanceResult -= OnResult; - actor.PerformanceFailed -= OnFailure; - actor.BeginGiven -= OnBeginGiven; - actor.EndGiven -= OnEndGiven; - actor.BeginWhen -= OnBeginWhen; - actor.EndWhen -= OnEndWhen; - actor.BeginThen -= OnBeginThen; - actor.EndThen -= OnEndThen; - } - - void OnGainAbility(object sender, GainAbilityEventArgs ev) - { - GainAbility(ev.Actor, ev.Ability, ev.Actor.ScenarioIdentity); - } - - void OnBegin(object sender, BeginPerformanceEventArgs ev) - { - Begin(ev.Actor, ev.Performable, ev.Actor.ScenarioIdentity); - } - - void OnSuccess(object sender, EndSuccessfulPerformanceEventArgs ev) - { - Success(ev.Actor, ev.Performable, ev.Actor.ScenarioIdentity); - } - - void OnResult(object sender, PerformanceResultEventArgs ev) - { - Result(ev.Actor, ev.Performable, ev.Result, ev.Actor.ScenarioIdentity); - } - - void OnFailure(object sender, PerformanceFailureEventArgs ev) - { - Failure(ev.Actor, ev.Performable, ev.Exception, ev.Actor.ScenarioIdentity); - } - - void OnBeginGiven(object sender, ActorEventArgs ev) - { - BeginGiven(ev.Actor, ev.Actor.ScenarioIdentity); - } - - void OnEndGiven(object sender, ActorEventArgs ev) - { - EndGiven(ev.Actor, ev.Actor.ScenarioIdentity); - } - - void OnBeginWhen(object sender, ActorEventArgs ev) - { - BeginWhen(ev.Actor, ev.Actor.ScenarioIdentity); - } - - void OnEndWhen(object sender, ActorEventArgs ev) - { - EndWhen(ev.Actor, ev.Actor.ScenarioIdentity); - } - - void OnBeginThen(object sender, ActorEventArgs ev) - { - BeginThen(ev.Actor, ev.Actor.ScenarioIdentity); - } - - void OnEndThen(object sender, ActorEventArgs ev) - { - EndThen(ev.Actor, ev.Actor.ScenarioIdentity); - } - - /// - /// Reports that an actor has gained an ability. - /// - /// The actor. - /// The ability. - /// The screenplay scenario identity. - protected virtual void GainAbility(INamed actor, IAbility ability, Guid scenarioIdentity) {} - - /// - /// Reports that a performable item has begun. - /// - /// The actor. - /// The performable item. - /// The screenplay scenario identity. - protected virtual void Begin(INamed actor, IPerformable performable, Guid scenarioIdentity) {} - - /// - /// Reports that a performable item has completed successfully. - /// - /// The actor. - /// The performable item. - /// The screenplay scenario identity. - protected virtual void Success(INamed actor, IPerformable performable, Guid scenarioIdentity) {} - - /// - /// Reports that a performable item has produced a result. - /// - /// The actor. - /// The performable item. - /// The result produced. - /// The screenplay scenario identity. - protected virtual void Result(INamed actor, IPerformable performable, object result, Guid scenarioIdentity) {} - - /// - /// Reports that a performable item has failed and possible terminated early. - /// - /// The actor. - /// The performable item. - /// An exception encountered whilst attempting to perform the item. - /// The screenplay scenario identity. - protected virtual void Failure(INamed actor, IPerformable performable, Exception exception, Guid scenarioIdentity) {} - - /// - /// Reports that an actor has begun a 'given' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected virtual void BeginGiven(INamed actor, Guid scenarioIdentity) {} - - /// - /// Reports that an actor has ended the 'given' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected virtual void EndGiven(INamed actor, Guid scenarioIdentity) {} - - /// - /// Reports that an actor has begun a 'when' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected virtual void BeginWhen(INamed actor, Guid scenarioIdentity) {} - - /// - /// Reports that an actor has ended the 'when' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected virtual void EndWhen(INamed actor, Guid scenarioIdentity) {} - - /// - /// Reports that an actor has begun a 'then' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected virtual void BeginThen(INamed actor, Guid scenarioIdentity) {} - - /// - /// Reports that an actor has ended the 'then' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected virtual void EndThen(INamed actor, Guid scenarioIdentity) {} - - #endregion - - #region Scenario-related handlers - - /// - /// Subscribe to the specified scenario. - /// - /// Test run. - public void Subscribe(IScreenplayScenario scenario) - { - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - - scenario.BeginScenario += OnNewScenario; - scenario.EndScenario += OnEndScenario; - } - - /// - /// Unsubscribe to the specified scenario. - /// - /// Test run. - public void Unsubscribe(IScreenplayScenario scenario) - { - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - - scenario.BeginScenario -= OnNewScenario; - scenario.EndScenario -= OnEndScenario; - } - - void OnNewScenario(object sender, BeginScenarioEventArgs ev) - { - BeginNewScenario(ev.ScenarioId.Identity, - ev.ScenarioId.Name, - ev.FeatureId.Name, - ev.FeatureId.Identity, - ev.ScenarioIdentity); - } - - void OnEndScenario(object sender, EndScenarioEventArgs ev) - { - CompleteScenario(ev.ScenarioOutcome, ev.ScenarioIdentity); - } - - /// - /// Indicates to the reporter that a new scenario has begun. - /// - /// The friendly scenario name. - /// The feature name. - /// The uniquely identifying name for the test. - /// The uniquely identifying name for the feature. - /// The screenplay scenario identity. - protected virtual void BeginNewScenario(string idName, - string friendlyName, - string featureName, - string featureId, - Guid scenarioIdentity) {} - - /// - /// Indicates to the reporter that a scenario has finished. - /// - /// true if the scenario was a success; false otherwise. - /// The screenplay scenario identity. - protected virtual void CompleteScenario(bool? outcome, Guid scenarioIdentity) {} - - #endregion - - #region Test-run-related handlers - - /// - /// Subscribe to the specified test run. - /// - /// Test run. - public void Subscribe(IProvidesTestRunEvents testRun) - { - if(testRun == null) - throw new ArgumentNullException(nameof(testRun)); - - testRun.BeginTestRun += OnNewTestRun; - testRun.CompleteTestRun += OnEndTestRun; - } - - /// - /// Unsubscribe to the specified test run. - /// - /// Test run. - public void Unsubscribe(IProvidesTestRunEvents testRun) - { - if(testRun == null) - throw new ArgumentNullException(nameof(testRun)); - - testRun.BeginTestRun -= OnNewTestRun; - testRun.CompleteTestRun -= OnEndTestRun; - } - - void OnNewTestRun(object sender, EventArgs ev) - { - BeginNewTestRun(); - } - - void OnEndTestRun(object sender, EventArgs ev) - { - CompleteTestRun(); - } - - /// - /// Indicates to the reporter that a new test-run has begun. - /// - protected virtual void BeginNewTestRun() {} - - /// - /// Indicates to the reporter that the test run has completed and that the report should be finalised. - /// - protected virtual void CompleteTestRun() {} - - #endregion - } -} diff --git a/CSF.Screenplay.Reporting/ObjectFormatterRegistry.cs b/CSF.Screenplay.Reporting/ObjectFormatterRegistry.cs deleted file mode 100644 index 77288726..00000000 --- a/CSF.Screenplay.Reporting/ObjectFormatterRegistry.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Implementation of which uses an in-memory collection. - /// - public class ObjectFormatterRegistry : IObjectFormatterRegistry - { - readonly ICollection formatters; - - /// - /// Adds a formatter to the collection. - /// - /// Formatter. - public void AddFormatter(IObjectFormatter formatter) - { - if(formatter == null) - throw new ArgumentNullException(nameof(formatter)); - - formatters.Add(formatter); - } - - /// - /// Gets a collection of all of the registered formatters. - /// - /// The all formatters. - public IReadOnlyCollection GetAllFormatters() => formatters.ToArray(); - - /// - /// Initializes a new instance of the class. - /// - public ObjectFormatterRegistry() - { - formatters = new HashSet(); - formatters.Add(new DefaultObjectFormatter()); - } - } -} diff --git a/CSF.Screenplay.Reporting/ObjectFormattingService.cs b/CSF.Screenplay.Reporting/ObjectFormattingService.cs deleted file mode 100644 index 7d473f09..00000000 --- a/CSF.Screenplay.Reporting/ObjectFormattingService.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Linq; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Provides a wrapper around , selecting the best registered formatter - /// and outputting the formatted name. - /// - public class ObjectFormattingService : IObjectFormattingService - { - static IObjectFormattingService defaultInstance; - readonly IObjectFormatterRegistry registry; - - /// - /// Format the specified object. - /// - /// Object. - public string Format(object obj) - { - var formatter = SelectBestFormatter(obj); - if(formatter == null) - return null; - - return formatter.GetFormattedName(obj); - } - - IObjectFormatter SelectBestFormatter(object obj) - => registry.GetAllFormatters() - .OrderByDescending(x => x.GetFormattingPriority(obj)) - .FirstOrDefault(); - - /// - /// Initializes a new instance of the class. - /// - /// Registry. - public ObjectFormattingService(IObjectFormatterRegistry registry) - { - if(registry == null) - throw new ArgumentNullException(nameof(registry)); - this.registry = registry; - } - - /// - /// Initializes the class. - /// - static ObjectFormattingService() - { - var defaultRegistry = new ObjectFormatterRegistry(); - defaultInstance = new ObjectFormattingService(defaultRegistry); - } - - /// - /// Gets a default/singleton instance which has no registered formatters except the default. - /// - /// The default formatting service. - public static IObjectFormattingService Default => defaultInstance; - } -} diff --git a/CSF.Screenplay.Reporting/Properties/AssemblyInfo.cs b/CSF.Screenplay.Reporting/Properties/AssemblyInfo.cs deleted file mode 100644 index a1d8a6ad..00000000 --- a/CSF.Screenplay.Reporting/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.Screenplay.Reporting")] -[assembly: AssemblyDescription("Reporting components for Screenplay")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("0.8.0.0")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.Screenplay.Reporting/ReportBuildingReporter.cs b/CSF.Screenplay.Reporting/ReportBuildingReporter.cs deleted file mode 100644 index 6be685f9..00000000 --- a/CSF.Screenplay.Reporting/ReportBuildingReporter.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using CSF.Screenplay.Reporting.Builders; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Implementation of which builds a report model. Does nothing on its own but may be - /// subclassed to provide reporting functionality based upon the report model. - /// - public class ReportBuildingReporter : NoOpReporter, IModelBuildingReporter - { - ReportBuilder builder; - - /// - /// Gets the report builder. - /// - /// The report builder. - protected ReportBuilder ReportBuilder => builder; - - /// - /// Indicates to the reporter that a new test-run has begun. - /// - protected override void BeginNewTestRun() - { - BeginNewReport(); - } - - /// - /// Indicates to the reporter that a new scenario has begun. - /// - /// The friendly scenario name. - /// The feature name. - /// The uniquely identifying name for the test. - /// The uniquely identifying name for the feature. - /// The screenplay scenario identity. - protected override void BeginNewScenario(string idName, string friendlyName, string featureName, string featureId, Guid scenarioIdentity) - { - builder.BeginNewScenario(idName, friendlyName, featureName, featureId, scenarioIdentity); - } - - /// - /// Indicates to the reporter that a scenario has finished. - /// - /// true if the scenario was a success; false otherwise. - /// The screenplay scenario identity. - protected override void CompleteScenario(bool? outcome, Guid scenarioIdentity) - { - builder.EndScenario(outcome, scenarioIdentity); - } - - /// - /// Gets the completed report model. - /// - /// The report. - public virtual Report GetReport() - { - return builder.GetReport(); - } - - /// - /// Reports that an actor has begun a 'given' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void BeginGiven(Actors.INamed actor, Guid scenarioIdentity) - { - builder.BeginPerformanceType(Models.PerformanceType.Given, scenarioIdentity); - } - - /// - /// Reports that an actor has ended the 'given' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void EndGiven(Actors.INamed actor, Guid scenarioIdentity) - { - builder.EndPerformanceType(scenarioIdentity); - } - - /// - /// Reports that an actor has begun a 'when' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void BeginWhen(Actors.INamed actor, Guid scenarioIdentity) - { - builder.BeginPerformanceType(Models.PerformanceType.When, scenarioIdentity); - } - - /// - /// Reports that an actor has ended the 'when' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void EndWhen(Actors.INamed actor, Guid scenarioIdentity) - { - builder.EndPerformanceType(scenarioIdentity); - } - - /// - /// Reports that an actor has begun a 'then' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void BeginThen(Actors.INamed actor, Guid scenarioIdentity) - { - builder.BeginPerformanceType(Models.PerformanceType.Then, scenarioIdentity); - } - - /// - /// Reports that an actor has ended the 'then' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void EndThen(Actors.INamed actor, Guid scenarioIdentity) - { - builder.EndPerformanceType(scenarioIdentity); - } - - /// - /// Reports that an actor has gained an ability. - /// - /// The actor. - /// The ability. - /// The screenplay scenario identity. - protected override void GainAbility(Actors.INamed actor, Abilities.IAbility ability, Guid scenarioIdentity) - { - builder.GainAbility(actor, ability, scenarioIdentity); - } - - /// - /// Reports that a performable item has begun. - /// - /// The actor. - /// The performable item. - /// The screenplay scenario identity. - protected override void Begin(Actors.INamed actor, Performables.IPerformable performable, Guid scenarioIdentity) - { - builder.BeginPerformance(actor, performable, scenarioIdentity); - } - - /// - /// Reports that a performable item has produced a result. - /// - /// The actor. - /// The performable item. - /// The result produced. - /// The screenplay scenario identity. - protected override void Result(Actors.INamed actor, Performables.IPerformable performable, object result, Guid scenarioIdentity) - { - builder.RecordResult(performable, result, scenarioIdentity); - } - - /// - /// Reports that a performable item has failed and possible terminated early. - /// - /// The actor. - /// The performable item. - /// An exception encountered whilst attempting to perform the item. - /// The screenplay scenario identity. - protected override void Failure(Actors.INamed actor, Performables.IPerformable performable, Exception exception, Guid scenarioIdentity) - { - builder.RecordFailure(performable, exception, scenarioIdentity); - } - - /// - /// Reports that a performable item has completed successfully. - /// - /// The actor. - /// The performable item. - /// The screenplay scenario identity. - protected override void Success(Actors.INamed actor, Performables.IPerformable performable, Guid scenarioIdentity) - { - builder.RecordSuccess(performable, scenarioIdentity); - } - - void BeginNewReport() - { - builder = new ReportBuilder(); - } - - /// - /// Initializes a new instance of the class. - /// - public ReportBuildingReporter() - { - BeginNewReport(); - } - } -} diff --git a/CSF.Screenplay.Reporting/ReportingIntegrationBuilder.cs b/CSF.Screenplay.Reporting/ReportingIntegrationBuilder.cs deleted file mode 100644 index 4c01b11d..00000000 --- a/CSF.Screenplay.Reporting/ReportingIntegrationBuilder.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using CSF.Screenplay.Integration; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Builder type which permits the configuration of reporting throughout a Screenplay test run. - /// - public class ReportingIntegrationBuilder - { - #region fields - - IReporter reporterToUse; - string name, castName; - bool subscribeToCastActorCreation, subscribeToCastActorAddition; - Action afterTestRunCallback; - Action writeReportCallback; - readonly IObjectFormatterRegistry formatterRegistry; - - #endregion - - #region builder methods - - /// - /// Indicates that a given reporter should be used throughout the test run. - /// - /// Reporter. - public ReportingIntegrationBuilder WithReporter(IReporter reporter) - { - if(reporter == null) - throw new ArgumentNullException(nameof(reporter)); - - this.reporterToUse = reporter; - return this; - } - - /// - /// Adds an object formatter to the given reporter. - /// - /// The formatter. - /// The object formatter type. - public ReportingIntegrationBuilder WithFormatter() where T : IObjectFormatter,new() - { - return WithFormatter(new T()); - } - - /// - /// Adds an object formatter to the given reporter. - /// - /// The formatter. - /// Formatter. - public ReportingIntegrationBuilder WithFormatter(IObjectFormatter formatter) - { - formatterRegistry.AddFormatter(formatter); - return this; - } - - /// - /// Names the reporter instance that the current builder is configuring. - /// - /// Name. - public ReportingIntegrationBuilder Name(string name) - { - this.name = name; - return this; - } - - /// - /// Causes the builder to subscribe to actors whenever they are created within a cast instance. - /// If actors are merely added to the cast (but created externally) then the reporter will not subscribe to them. - /// Requires a cast to be in use. - /// - /// Cast name. - public ReportingIntegrationBuilder SubscribeToActorsCreatedInCast(string castName = null) - { - subscribeToCastActorCreation = true; - subscribeToCastActorAddition = false; - this.castName = castName; - return this; - } - - /// - /// Causes the builder to subscribe to actors whenever they are added to a cast instance. - /// This will cause the reporter to subscribe to all actors participating in the cast, those created within it and - /// also those added to it externally. - /// Requires a cast to be in use. - /// - /// Cast name. - public ReportingIntegrationBuilder SubscribeToActorsAddedToCast(string castName = null) - { - subscribeToCastActorCreation = false; - subscribeToCastActorAddition = true; - this.castName = castName; - return this; - } - - /// - /// Provides a callback with which the reporter may take actions after the test run is complete. - /// - /// The test run. - /// Callback. - public ReportingIntegrationBuilder AfterTestRun(Action callback) - { - this.afterTestRunCallback = callback; - return this; - } - - /// - /// Provides a callback exposing the report created by the reporter, from which you may write that report to - /// whatever destination you wish. - /// Requires that the reporter in use imlpements (this is the default behaviour). - /// - /// The report. - /// Callback. - public ReportingIntegrationBuilder WriteReport(Action callback) - { - writeReportCallback = (formatService, report) => callback(report); - return this; - } - - /// - /// Provides a callback exposing the report created by the reporter, from which you may write that report to - /// whatever destination you wish. - /// Requires that the reporter in use imlpements (this is the default behaviour). - /// - /// The report. - /// Callback. - public ReportingIntegrationBuilder WriteReport(Action callback) - { - writeReportCallback = callback; - return this; - } - - #endregion - - #region private methods - - internal void ApplyToIntegration(IIntegrationConfigBuilder integration) - { - if(integration == null) - throw new ArgumentNullException(nameof(integration)); - - RegisterReporter(integration); - RegisterObjectFormatters(integration); - SubscribeToCast(integration); - SubscribeToBeginAndEndTestRun(integration); - SubscribeToScenario(integration); - WriteReport(integration); - } - - void RegisterObjectFormatters(IIntegrationConfigBuilder integration) - { - integration.ServiceRegistrations.PerTestRun.Add(h => { - h.RegisterInstance(formatterRegistry).As(); - var formatService = new ObjectFormattingService(formatterRegistry); - h.RegisterInstance(formatService).As(); - }); - } - - void RegisterReporter(IIntegrationConfigBuilder integration) - { - var reporter = new ReportBuildingReporter(); - - integration.ServiceRegistrations.PerTestRun.Add(h => { - h.RegisterInstance(reporter).As(); - h.RegisterInstance(reporter).As(); - }); - } - - void SubscribeToCast(IIntegrationConfigBuilder integration) - { - integration.BeforeScenario.Add((scenario) => { - - if(!subscribeToCastActorCreation && !subscribeToCastActorAddition) - return; - - var cast = scenario.Resolver.GetCast(castName); - var reporter = scenario.Resolver.GetReporter(name); - - if(subscribeToCastActorCreation) - { - cast.ActorCreated += (sender, e) => { - reporter.Subscribe(e.Actor); - }; - } - else - { - cast.ActorAdded += (sender, e) => { - reporter.Subscribe(e.Actor); - }; - } - }); - } - - void SubscribeToBeginAndEndTestRun(IIntegrationConfigBuilder integration) - { - integration.BeforeFirstScenario.Add((events, resolver) => { - var reporter = resolver.GetReporter(name); - reporter.Subscribe(events); - }); - } - - void SubscribeToScenario(IIntegrationConfigBuilder integration) - { - integration.BeforeScenario.Add((scenario) => { - var reporter = scenario.Resolver.GetReporter(name); - reporter.Subscribe(scenario); - }); - - integration.AfterScenario.Add((scenario) => { - var reporter = scenario.Resolver.GetReporter(name); - reporter.Unsubscribe(scenario); - }); - } - - void WriteReport(IIntegrationConfigBuilder integration) - { - integration.AfterLastScenario.Add((resolver) => { - - var reporter = resolver.GetReporter(name); - var modelReporter = reporter as IModelBuildingReporter; - var formatter = resolver.GetObjectFormattingService(); - - if(modelReporter != null && writeReportCallback != null) - { - var report = modelReporter.GetReport(); - writeReportCallback(formatter, report); - return; - } - - if(reporter != null && afterTestRunCallback != null) - { - afterTestRunCallback(reporter); - return; - } - }); - } - - #endregion - - #region constructor - - /// - /// Initializes a new instance of the class. - /// - public ReportingIntegrationBuilder() - { - formatterRegistry = new ObjectFormatterRegistry(); - } - - #endregion - } -} diff --git a/CSF.Screenplay.Reporting/ReportingIntegrationBuilderExtensions.cs b/CSF.Screenplay.Reporting/ReportingIntegrationBuilderExtensions.cs deleted file mode 100644 index cdd667a1..00000000 --- a/CSF.Screenplay.Reporting/ReportingIntegrationBuilderExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using CSF.Screenplay.Reporting; -using CSF.Screenplay.Integration; - -namespace CSF.Screenplay -{ - /// - /// Extension methods related to integrating an with Screenplay. - /// - public static class ReportingIntegrationBuilderExtensions - { - /// - /// Registers and configures reporting within the Screenplay test run. A configuration builder is used to - /// actually configure reporting, as there are several options available. - /// - /// Helper. - /// Config. - public static void UseReporting(this IIntegrationConfigBuilder helper, - Action config) - { - if(helper == null) - throw new ArgumentNullException(nameof(helper)); - if(config == null) - throw new ArgumentNullException(nameof(config)); - - var reportingHelper = new ReportingIntegrationBuilder(); - config(reportingHelper); - reportingHelper.ApplyToIntegration(helper); - } - } -} diff --git a/CSF.Screenplay.Reporting/ReportingResolverExtensions.cs b/CSF.Screenplay.Reporting/ReportingResolverExtensions.cs deleted file mode 100644 index c7a02dcb..00000000 --- a/CSF.Screenplay.Reporting/ReportingResolverExtensions.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using CSF.FlexDi; -using CSF.Screenplay.Reporting; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay -{ - /// - /// Extension methods related to the resolving of reporting-related services. - /// - public static class ReportingResolverExtensions - { - /// - /// Gets the reporter from the current service resolver. - /// - /// The reporter. - /// Resolver. - /// Name. - public static IReporter GetReporter(this IResolvesServices resolver, string name = null) - { - if(resolver == null) - throw new ArgumentNullException(nameof(resolver)); - - return resolver.Resolve(name); - } - - /// - /// Gets the reporter from the current service resolver, expecting that reporter to be an instance of - /// . - /// - /// The reporter. - /// Resolver. - /// Name. - public static IModelBuildingReporter GetReportBuildingReporter(this IResolvesServices resolver, string name = null) - { - if(resolver == null) - throw new ArgumentNullException(nameof(resolver)); - - return resolver.Resolve(name); - } - - /// - /// Gets the object formatting service from the current resolver. - /// - /// The object formatting service. - /// Resolver. - /// Name. - public static IObjectFormattingService GetObjectFormattingService(this IResolvesServices resolver, string name = null) - { - if(resolver == null) - throw new ArgumentNullException(nameof(resolver)); - - return resolver.Resolve(name); - } - } -} diff --git a/CSF.Screenplay.Reporting/TextReportWriter.cs b/CSF.Screenplay.Reporting/TextReportWriter.cs deleted file mode 100644 index 01edcfcb..00000000 --- a/CSF.Screenplay.Reporting/TextReportWriter.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting -{ - /// - /// An which writes the report to a System.IO.TextWriter, be that a text file or - /// an output stream. This writer uses a simple text-based format to render the results of the report in a - /// human-readable format. - /// - public class TextReportWriter : IReportWriter - { - const char INDENT_CHAR = ' '; - const int INDENT_WIDTH = 4, RESULT_OR_FAILURE_INDENT_WIDTH = 6; - - readonly TextWriter writer; - readonly IObjectFormattingService formattingService; - - /// - /// Write the specified report to the text writer. - /// - /// Report model. - public void Write(Report reportModel) - { - foreach(var scenario in reportModel.Features.SelectMany(x => x.Scenarios)) - { - WriteScenario(scenario); - } - } - - void WriteScenario(Models.Scenario scenario) - { - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - - WriteScenarioHeader(scenario); - - foreach(var reportable in scenario.Reportables) - { - WriteReportable(reportable); - } - } - - void WriteScenarioHeader(Models.Scenario scenario) - { - writer.WriteLine(); - - var featureText = GetFeatureText(scenario); - if(featureText != null) - writer.WriteLine(featureText); - - writer.WriteLine(GetScenarioText(scenario)); - - WriteScenarioOutcome(scenario); - } - - string GetFeatureText(Models.Scenario scenario) - { - if(scenario.FeatureName != null) - return $"Feature: {scenario.FeatureName}"; - - return null; - } - - string GetScenarioText(Models.Scenario scenario) - { - return $"Scenario: {scenario.FriendlyName?? scenario.Id}"; - } - - void WriteReportable(Reportable reportable, int currentIndentLevel = 0) - { - if(reportable == null) - throw new ArgumentNullException(nameof(reportable)); - - if(reportable is GainAbility) - WriteGainAbility((GainAbility) reportable, currentIndentLevel); - else if(reportable is Performance) - WritePerformance((Performance) reportable, currentIndentLevel); - else - throw new ArgumentException($"The reportable must be either a {typeof(GainAbility).Name} or a {typeof(Performance).Name}."); - } - - void WriteGainAbility(GainAbility reportable, int currentIndentLevel) - { - WriteIndent(currentIndentLevel); - WritePerformanceType(reportable, currentIndentLevel); - - writer.Write(reportable.Ability.GetReport(reportable.Actor)); - writer.WriteLine(); - } - - void WritePerformance(Performance reportable, int currentIndentLevel) - { - WriteIndent(currentIndentLevel); - WritePerformanceType(reportable, currentIndentLevel); - - writer.Write(reportable.Performable.GetReport(reportable.Actor)); - writer.WriteLine(); - - if(reportable.Outcome == PerformanceOutcome.SuccessWithResult) - WriteResult(reportable, currentIndentLevel); - else if(reportable.Outcome == PerformanceOutcome.Failure) - WriteFailure(reportable, currentIndentLevel); - else if(reportable.Outcome == PerformanceOutcome.FailureWithException && !reportable.Reportables.Any()) - WriteFailure(reportable, currentIndentLevel); - - foreach(var child in reportable.Reportables) - { - WriteReportable(child, currentIndentLevel + 1); - } - } - - string GetPerformanceTypeString(PerformanceType type, int currentIndentLevel) - { - if(type == PerformanceType.Unspecified) - return String.Empty; - - // Don't keep writing the performance type after the base indent level - if(currentIndentLevel > 0) - return String.Empty; - - return type.ToString(); - } - - void WriteScenarioOutcome(Models.Scenario scenario) - { - writer.WriteLine("**** {0} ****", GetScenarioOutcome(scenario)); - } - - string GetScenarioOutcome(Models.Scenario scenario) - { - if(scenario.IsSuccess) return "Success"; - if(scenario.IsFailure) return "Failure"; - return "Inconclusive"; - } - - void WriteIndent(int currentLevel) - { - writer.Write(GetIndent(currentLevel)); - } - - void WriteResultOrFailureIndent(int currentLevel) - { - WriteIndent(currentLevel); - writer.Write(new String(INDENT_CHAR, RESULT_OR_FAILURE_INDENT_WIDTH)); - } - - void WritePerformanceType(Reportable reportable, int currentIndentLevel) - { - writer.Write("{0,5} ", GetPerformanceTypeString(reportable.PerformanceType, currentIndentLevel)); - } - - void WriteResult(Performance reportable, int currentIndentLevel) - { - WriteResultOrFailureIndent(currentIndentLevel); - writer.WriteLine("Result:{0}", Format(reportable.Result)); - } - - void WriteFailure(Performance reportable, int currentIndentLevel) - { - WriteResultOrFailureIndent(currentIndentLevel); - - var reportableException = reportable.Exception as IReportable; - if(reportableException != null) - { - writer.WriteLine("FAILED {0}", reportableException.GetReport(reportable.Actor)); - return; - } - - var exception = reportable.Exception?.ToString(); - if(exception != null) - writer.WriteLine("FAILED with an exception:{1}{0}", exception, Environment.NewLine); - else - writer.WriteLine("FAILED"); - } - - string Format(object obj) => formattingService.Format(obj); - - string GetIndent(int currentLevel) - => String.Join(String.Empty, Enumerable.Range(0, currentLevel).Select(x => new String(INDENT_CHAR, INDENT_WIDTH))); - - /// - /// Initializes a new instance of the class. - /// - /// Writer. - public TextReportWriter(TextWriter writer) - { - if(writer == null) - throw new ArgumentNullException(nameof(writer)); - - this.writer = writer; - formattingService = ObjectFormattingService.Default; - } - - /// - /// Initializes a new instance of the class. - /// - /// Writer. - /// Formatting service. - public TextReportWriter(TextWriter writer, IObjectFormattingService formattingService) - : this(writer) - { - this.formattingService = formattingService ?? ObjectFormattingService.Default; - } - - /// - /// Write the report to a file path. - /// - /// The report. - /// Destination file path. - /// Object formatting service. - public static void WriteToFile(Report report, string path, IObjectFormattingService formattingService = null) - { - using(var writer = new StreamWriter(path)) - { - var reportWriter = new TextReportWriter(writer, formattingService); - reportWriter.Write(report); - writer.Flush(); - } - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/AbilityReport.cs b/CSF.Screenplay.Reporting/Trace/AbilityReport.cs deleted file mode 100644 index 3d349939..00000000 --- a/CSF.Screenplay.Reporting/Trace/AbilityReport.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Represents a report upon an actor gaining an ability. - /// - public class AbilityReport - { - /// - /// Gets the ability which was added to the actor. - /// - /// The ability. - public IAbility Ability { get; private set; } - - /// - /// Gets the actor which gained the ability - /// - /// The actor. - public INamed Actor { get; private set; } - - /// - /// Returns a System.String that represents the current . - /// - /// A System.String that represents the current . - public override string ToString() - { - return $"ABILITY: {Ability.GetReport(Actor)}"; - } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The ability. - public AbilityReport(INamed actor, IAbility ability) - { - if(ability == null) - throw new ArgumentNullException(nameof(ability)); - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - Ability = ability; - Actor = actor; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/ActorReport.cs b/CSF.Screenplay.Reporting/Trace/ActorReport.cs deleted file mode 100644 index b60a02cd..00000000 --- a/CSF.Screenplay.Reporting/Trace/ActorReport.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Represents a trace report relating to an actor. - /// - public class ActorReport - { - /// - /// Gets the actor which is performing the item. - /// - /// The actor. - public INamed Actor { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// Actor. - public ActorReport(INamed actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - Actor = actor; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/BeginReport.cs b/CSF.Screenplay.Reporting/Trace/BeginReport.cs deleted file mode 100644 index 717de7dd..00000000 --- a/CSF.Screenplay.Reporting/Trace/BeginReport.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Represents a report that an actor is beginning to perform an action, task or ask a question. - /// - public class BeginReport : PerformableReportBase, IPerformanceStart - { - /// - /// Returns a System.String that represents the current . - /// - /// A System.String that represents the current . - public override string ToString() - { - return $"BEGIN: {Performable.GetReport(Actor)}"; - } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public BeginReport(INamed actor, IPerformable performable) : base(actor, performable) {} - } -} diff --git a/CSF.Screenplay.Reporting/Trace/BeginScenarioReport.cs b/CSF.Screenplay.Reporting/Trace/BeginScenarioReport.cs deleted file mode 100644 index 231a7485..00000000 --- a/CSF.Screenplay.Reporting/Trace/BeginScenarioReport.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Reports the beginning of a new scenario. - /// - public class BeginScenarioReport - { - /// - /// Gets the scenario identifier. - /// - /// The scenario identifier. - public string ScenarioId { get; private set; } - - /// - /// Gets the name of the scenario. - /// - /// The name of the scenario. - public string ScenarioName { get; private set; } - - /// - /// Gets the feature identifier. - /// - /// The feature identifier. - public string FeatureId { get; private set; } - - /// - /// Gets the name of the feature. - /// - /// The name of the feature. - public string FeatureName { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// Scenario identifier. - /// Scenario name. - /// Feature identifier. - /// Feature name. - public BeginScenarioReport(string scenarioId, - string scenarioName = null, - string featureId = null, - string featureName = null) - { - if(scenarioId == null) - throw new ArgumentNullException(nameof(scenarioId)); - - ScenarioId = scenarioId; - ScenarioName = scenarioName; - FeatureId = featureId; - FeatureName = featureName; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/CompleteScenarioReport.cs b/CSF.Screenplay.Reporting/Trace/CompleteScenarioReport.cs deleted file mode 100644 index 60dae537..00000000 --- a/CSF.Screenplay.Reporting/Trace/CompleteScenarioReport.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Reports the completion of a test scenario. - /// - public class CompleteScenarioReport - { - /// - /// Gets a value indicating whether the scenario was a success. - /// - /// true if the scenario was a success; otherwise, false. - public bool? Outcome { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// If set to true success. - public CompleteScenarioReport(bool? outcome) - { - Outcome = outcome; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/FailureReport.cs b/CSF.Screenplay.Reporting/Trace/FailureReport.cs deleted file mode 100644 index 2f089263..00000000 --- a/CSF.Screenplay.Reporting/Trace/FailureReport.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Represents a report that the performing of an item has failed, possibly due to an exception. - /// - public class FailureReport : PerformableReportBase, IPerformanceEnd - { - /// - /// Gets the exception which is responsible for this failure, if applicable. - /// - /// The exception. - public Exception Exception { get; private set; } - - /// - /// Returns a System.String that represents the current . - /// - /// A System.String that represents the current . - public override string ToString() - { - return $"FAILURE: {Performable.GetReport(Actor)}"; - } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - /// The exception. - public FailureReport(INamed actor, IPerformable performable, Exception exception) - : base(actor, performable) - { - Exception = exception; - } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public FailureReport(INamed actor, IPerformable performable) : this(actor, performable, null) {} - } -} diff --git a/CSF.Screenplay.Reporting/Trace/IPerformanceEnd.cs b/CSF.Screenplay.Reporting/Trace/IPerformanceEnd.cs deleted file mode 100644 index 86b92572..00000000 --- a/CSF.Screenplay.Reporting/Trace/IPerformanceEnd.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Marks the moment at which an actor finishes performing a performable item. - /// - public interface IPerformanceEnd - { - /// - /// Gets the performable. - /// - /// The performable. - IPerformable Performable { get; } - - /// - /// Gets the actor which is performing the . - /// - /// The actor. - INamed Actor { get; } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/IPerformanceStart.cs b/CSF.Screenplay.Reporting/Trace/IPerformanceStart.cs deleted file mode 100644 index 6c4b9f96..00000000 --- a/CSF.Screenplay.Reporting/Trace/IPerformanceStart.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Marks the moment at which an actor begins performing a performable item. - /// - public interface IPerformanceStart - { - /// - /// Gets the performable. - /// - /// The performable. - IPerformable Performable { get; } - - /// - /// Gets the actor which is performing the . - /// - /// The actor. - INamed Actor { get; } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/PerformableReportBase.cs b/CSF.Screenplay.Reporting/Trace/PerformableReportBase.cs deleted file mode 100644 index b8e21abc..00000000 --- a/CSF.Screenplay.Reporting/Trace/PerformableReportBase.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Base type for a report upon an actor's performance. - /// - public abstract class PerformableReportBase - { - /// - /// Gets the performable item which is being reported-upon. - /// - /// The performable. - public IPerformable Performable { get; private set; } - - /// - /// Gets the actor which is performing the item. - /// - /// The actor. - public INamed Actor { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public PerformableReportBase(INamed actor, IPerformable performable) - { - if(performable == null) - throw new ArgumentNullException(nameof(performable)); - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - Performable = performable; - Actor = actor; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/ResultReport.cs b/CSF.Screenplay.Reporting/Trace/ResultReport.cs deleted file mode 100644 index 7d7a8b25..00000000 --- a/CSF.Screenplay.Reporting/Trace/ResultReport.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Represents a report that an actor has retrieved a result from an action, task or question. - /// - public class ResultReport : PerformableReportBase - { - /// - /// Gets the result value. - /// - /// The result. - public object Result { get; private set; } - - /// - /// Returns a System.String that represents the current . - /// - /// A System.String that represents the current . - public override string ToString() - { - var resultString = (Result != null)? Result.ToString() : ""; - return $"RESULT: {Performable.GetReport(Actor)} : {resultString}"; - } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - /// The result value. - public ResultReport(INamed actor, IPerformable performable, object result) - : base(actor, performable) - { - Result = result; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/SuccessReport.cs b/CSF.Screenplay.Reporting/Trace/SuccessReport.cs deleted file mode 100644 index e00663ad..00000000 --- a/CSF.Screenplay.Reporting/Trace/SuccessReport.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Represents a report that an actor has successfully performed an action, task or asked a question. - /// - public class SuccessReport : PerformableReportBase, IPerformanceEnd - { - /// - /// Returns a System.String that represents the current . - /// - /// A System.String that represents the current . - public override string ToString() - { - return $"SUCCESS: {Performable.GetReport(Actor)}"; - } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public SuccessReport(INamed actor, IPerformable performable) : base(actor, performable) {} - } -} diff --git a/CSF.Screenplay.Reporting/Trace/TracableEvent.cs b/CSF.Screenplay.Reporting/Trace/TracableEvent.cs deleted file mode 100644 index 28cd6265..00000000 --- a/CSF.Screenplay.Reporting/Trace/TracableEvent.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Diagnostics; - -namespace CSF.Screenplay.Reporting.Trace -{ - class TracableEvent - { - internal TraceEventType EventType { get; private set; } - - internal int EventId { get; private set; } - - internal TracableEvent(TraceEventType eventType, int eventId) - { - eventType.RequireDefinedValue(nameof(eventType)); - if(eventId < 1) - throw new ArgumentOutOfRangeException(nameof(eventId), eventId, "Event ID must be a positive integer"); - - EventType = eventType; - EventId = eventId; - } - } -} diff --git a/CSF.Screenplay.Reporting/Trace/TraceConstants.cs b/CSF.Screenplay.Reporting/Trace/TraceConstants.cs deleted file mode 100644 index 17d20b86..00000000 --- a/CSF.Screenplay.Reporting/Trace/TraceConstants.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Diagnostics; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Singleton which contains information about the trace source configured for this assembly. - /// - static class TraceConstants - { - /// - /// Gets the name of the trace source. - /// - internal static readonly string SourceName = typeof(IReporter).Namespace; - - /// - /// Gets the trace source itself. - /// - internal static readonly TraceSource Source = new TraceSource(SourceName); - - internal static readonly TracableEvent - GainAbility = new TracableEvent(EventTypes.GainAbility, EventIds.GainAbility), - BeginPerformance = new TracableEvent(EventTypes.BeginPerformance, EventIds.BeginPerformance), - PerformanceSuccess = new TracableEvent(EventTypes.PerformanceSuccess, EventIds.PerformanceSuccess), - PerformanceResult = new TracableEvent(EventTypes.PerformanceResult, EventIds.PerformanceResult), - PerformanceFailure = new TracableEvent(EventTypes.PerformanceFailure, EventIds.PerformanceFailure), - BeginGiven = new TracableEvent(EventTypes.BeginGiven, EventIds.BeginGiven), - EndGiven = new TracableEvent(EventTypes.EndGiven, EventIds.EndGiven), - BeginWhen = new TracableEvent(EventTypes.BeginWhen, EventIds.BeginWhen), - EndWhen = new TracableEvent(EventTypes.EndWhen, EventIds.EndWhen), - BeginThen = new TracableEvent(EventTypes.BeginThen, EventIds.BeginThen), - EndThen = new TracableEvent(EventTypes.EndThen, EventIds.EndThen), - BeginNewTestRun = new TracableEvent(EventTypes.BeginNewTestRun, EventIds.BeginNewTestRun), - CompleteTestRun = new TracableEvent(EventTypes.CompleteTestRun, EventIds.CompleteTestRun), - BeginNewScenario = new TracableEvent(EventTypes.BeginNewScenario, EventIds.BeginNewScenario), - CompleteScenario = new TracableEvent(EventTypes.CompleteScenario, EventIds.CompleteScenario); - - } - - /// - /// Numeric identifiers for traceable events. - /// - class EventIds - { - internal const int - GainAbility = 1, - BeginPerformance = 2, - PerformanceSuccess = 3, - PerformanceResult = 4, - PerformanceFailure = 5, - BeginGiven = 6, - EndGiven = 7, - BeginWhen = 8, - EndWhen = 9, - BeginThen = 10, - EndThen = 11, - BeginNewTestRun = 12, - CompleteTestRun = 13, - BeginNewScenario = 14, - CompleteScenario = 15; - } - - /// - /// Trace event types for various traceable events. - /// - class EventTypes - { - internal const TraceEventType - GainAbility = TraceEventType.Verbose, - BeginPerformance = TraceEventType.Verbose, - PerformanceSuccess = TraceEventType.Information, - PerformanceResult = TraceEventType.Verbose, - PerformanceFailure = TraceEventType.Error, - BeginGiven = TraceEventType.Verbose, - EndGiven = TraceEventType.Verbose, - BeginWhen = TraceEventType.Verbose, - EndWhen = TraceEventType.Verbose, - BeginThen = TraceEventType.Verbose, - EndThen = TraceEventType.Verbose, - BeginNewTestRun = TraceEventType.Information, - CompleteTestRun = TraceEventType.Verbose, - BeginNewScenario = TraceEventType.Information, - CompleteScenario = TraceEventType.Verbose; - } -} diff --git a/CSF.Screenplay.Reporting/Trace/TraceReporter.cs b/CSF.Screenplay.Reporting/Trace/TraceReporter.cs deleted file mode 100644 index b7eb8f6a..00000000 --- a/CSF.Screenplay.Reporting/Trace/TraceReporter.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Diagnostics; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Reporting.Trace -{ - /// - /// Implementation of which writes report data to the System.Diagnostics.TraceSource - /// held within the class. - /// - public class TraceReporter : NoOpReporter - { - /// - /// Reports that an actor has gained an ability. - /// - /// The actor. - /// The ability. - /// The screenplay scenario identity. - protected override void GainAbility(INamed actor, IAbility ability, Guid scenarioIdentity) - { - var report = new AbilityReport(actor, ability); - Trace(TraceConstants.GainAbility, report); - } - - /// - /// Reports that a performable item has begun. - /// - /// The actor. - /// The performable item. - /// The screenplay scenario identity. - protected override void Begin(INamed actor, IPerformable performable, Guid scenarioIdentity) - { - var report = new BeginReport(actor, performable); - Trace(TraceConstants.BeginPerformance, report); - } - - /// - /// Reports that a performable item has completed successfully. - /// - /// The actor. - /// The performable item. - /// The screenplay scenario identity. - protected override void Success(INamed actor, IPerformable performable, Guid scenarioIdentity) - { - var report = new SuccessReport(actor, performable); - Trace(TraceConstants.PerformanceSuccess, report); - } - - /// - /// Reports that a performable item has produced a result. - /// - /// The actor. - /// The performable item. - /// The result produced. - /// The screenplay scenario identity. - protected override void Result(INamed actor, IPerformable performable, object result, Guid scenarioIdentity) - { - var report = new ResultReport(actor, performable, result); - Trace(TraceConstants.PerformanceResult, report); - } - - /// - /// Reports that a performable item has failed and possible terminated early. - /// - /// The actor. - /// The performable item. - /// An exception encountered whilst attempting to perform the item. - /// The screenplay scenario identity. - protected override void Failure(INamed actor, IPerformable performable, Exception exception, Guid scenarioIdentity) - { - var report = new FailureReport(actor, performable, exception); - Trace(TraceConstants.PerformanceFailure, report); - } - - /// - /// Reports that an actor has begun a 'given' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void BeginGiven(INamed actor, Guid scenarioIdentity) - { - var report = new ActorReport(actor); - Trace(TraceConstants.BeginGiven, report); - } - - /// - /// Reports that an actor has ended the 'given' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void EndGiven(INamed actor, Guid scenarioIdentity) - { - var report = new ActorReport(actor); - Trace(TraceConstants.EndGiven, report); - } - - /// - /// Reports that an actor has begun a 'when' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void BeginWhen(INamed actor, Guid scenarioIdentity) - { - var report = new ActorReport(actor); - Trace(TraceConstants.BeginWhen, report); - } - /// - /// Reports that an actor has ended the 'when' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void EndWhen(INamed actor, Guid scenarioIdentity) - { - var report = new ActorReport(actor); - Trace(TraceConstants.EndWhen, report); - } - - /// - /// Reports that an actor has begun a 'then' part of their performance and that subsequent performables occur - /// in this context. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void BeginThen(INamed actor, Guid scenarioIdentity) - { - var report = new ActorReport(actor); - Trace(TraceConstants.BeginThen, report); - } - - /// - /// Reports that an actor has ended the 'then' part of their performance. - /// - /// The actor. - /// The screenplay scenario identity. - protected override void EndThen(INamed actor, Guid scenarioIdentity) - { - var report = new ActorReport(actor); - Trace(TraceConstants.EndThen, report); - } - - /// - /// Indicates to the reporter that a new test-run has begun. - /// - protected override void BeginNewTestRun() - { - Trace(TraceConstants.BeginNewTestRun); - } - - /// - /// Indicates to the reporter that the test run has completed and that the report should be finalised. - /// - protected override void CompleteTestRun() - { - Trace(TraceConstants.CompleteTestRun); - } - - /// - /// Indicates to the reporter that a new scenario has begun. - /// - /// The friendly scenario name. - /// The feature name. - /// The uniquely identifying name for the test. - /// The uniquely identifying name for the feature. - /// The screenplay scenario identity. - protected override void BeginNewScenario(string idName, string friendlyName, string featureName, string featureId, Guid scenarioIdentity) - { - var report = new BeginScenarioReport(idName, friendlyName, featureId, featureName); - Trace(TraceConstants.BeginNewScenario, report); - } - - /// - /// Indicates to the reporter that a scenario has finished. - /// - /// - /// true if the scenario was a success; false otherwise. - /// The screenplay scenario identity. - protected override void CompleteScenario(bool? outcome, Guid scenarioIdentity) - { - var report = new CompleteScenarioReport(outcome); - Trace(TraceConstants.CompleteScenario, report); - } - - void Trace(TracableEvent tracableEvent, object report) - { - if(tracableEvent == null) - throw new ArgumentNullException(nameof(tracableEvent)); - - TraceConstants.Source.TraceData(tracableEvent.EventType, tracableEvent.EventId, report); - } - - void Trace(TracableEvent tracableEvent) - { - if(tracableEvent == null) - throw new ArgumentNullException(nameof(tracableEvent)); - - TraceConstants.Source.TraceEvent(tracableEvent.EventType, tracableEvent.EventId); - } - - } -} diff --git a/CSF.Screenplay.Reporting/packages.config b/CSF.Screenplay.Reporting/packages.config deleted file mode 100644 index aea13d1a..00000000 --- a/CSF.Screenplay.Reporting/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.csproj b/CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.csproj deleted file mode 100644 index 1c2442a8..00000000 --- a/CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.csproj +++ /dev/null @@ -1,65 +0,0 @@ - - - - Debug - AnyCPU - {5FC41182-AE52-4324-BA3B-456DA91FE30C} - Library - CSF.Screenplay.SpecFlow - CSF.Screenplay.SpecFlowPlugin - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - bin\Debug\CSF.Screenplay.SpecFlowPlugin.xml - false - - - true - bin\Release - prompt - 4 - bin\Release\CSF.Screenplay.SpecFlowPlugin.xml - false - - - - - ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - - ..\packages\SpecFlow.2.2.0\lib\net45\TechTalk.SpecFlow.dll - - - - ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll - - - - - - - - - - - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - - \ No newline at end of file diff --git a/CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.nuspec b/CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.nuspec deleted file mode 100644 index 2227035a..00000000 --- a/CSF.Screenplay.SpecFlow/CSF.Screenplay.SpecFlow.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - CSF.Screenplay.SpecFlow - 0.8.0-alpha - CSF.Screenplay.SpecFlow - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - Bindings and types for making use of CSF.Screenplay with the SpecFlow BDD framework - Copyright 2017 - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay.SpecFlow/IntegrationProvider.cs b/CSF.Screenplay.SpecFlow/IntegrationProvider.cs deleted file mode 100644 index 4313501a..00000000 --- a/CSF.Screenplay.SpecFlow/IntegrationProvider.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using CSF.Screenplay.Integration; - -namespace CSF.Screenplay.SpecFlow -{ - /// - /// Helper which encapsulates the logic required to create a new . - /// - public class IntegrationProvider - { - /// - /// Gets the integration (via lazy-initialisation). - /// - /// The integration. - public Lazy GetIntegration() - { - return new Lazy(CreateIntegration); - } - - IScreenplayIntegration CreateIntegration() - { - var integration = GetScreenplayAssemblyAttribute()?.Integration; - - if(integration == null) - { - var message = $"There must be an assembly with the {nameof(ScreenplayAssemblyAttribute)}, stating the location to the Screenplay integration configuration."; - throw new InvalidOperationException(message); - } - - return integration; - } - - ScreenplayAssemblyAttribute GetScreenplayAssemblyAttribute() - { - var appDomain = AppDomain.CurrentDomain; - var assemblies = appDomain.GetAssemblies(); - - return (from assembly in assemblies - where !assembly.IsDynamic - let attrib = assembly.GetCustomAttribute() - where attrib != null - select attrib) - .FirstOrDefault(); - } - } -} diff --git a/CSF.Screenplay.SpecFlow/Properties/AssemblyInfo.cs b/CSF.Screenplay.SpecFlow/Properties/AssemblyInfo.cs deleted file mode 100644 index bd3a6de4..00000000 --- a/CSF.Screenplay.SpecFlow/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.Screenplay.SpecFlow")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.Screenplay.SpecFlow/ScenarioAdapter.cs b/CSF.Screenplay.SpecFlow/ScenarioAdapter.cs deleted file mode 100644 index 9336be86..00000000 --- a/CSF.Screenplay.SpecFlow/ScenarioAdapter.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using CSF.Screenplay.Integration; -using CSF.Screenplay.Scenarios; -using TechTalk.SpecFlow; - -namespace CSF.Screenplay.SpecFlow -{ - /// - /// Helper type which encapsulates the mappings/relationships between a Screenplay scenario and SpecFlow - /// contexts. - /// - public class ScenarioAdapter - { - static IDictionary scenarioIds; - static IDictionary featureIds; - - readonly ScenarioContext scenarioContext; - readonly FeatureContext featureContext; - readonly IScreenplayIntegration integration; - - /// - /// Creates a Screenplay scenario. - /// - /// The scenario. - public IScreenplayScenario CreateScenario() - { - var factory = integration.GetScenarioFactory(); - return factory.GetScenario(FeatureIdAndName, ScenarioIdAndName); - } - - IdAndName FeatureIdAndName - => new IdAndName(GetFeatureId(featureContext).ToString(), featureContext.FeatureInfo.Title); - - IdAndName ScenarioIdAndName - => new IdAndName(GetScenarioId(scenarioContext, featureContext).ToString(), scenarioContext.ScenarioInfo.Title); - - Guid GetFeatureId(FeatureContext feature) - { - if(!featureIds.ContainsKey(feature)) - featureIds.Add(feature, Guid.NewGuid()); - - return featureIds[feature]; - } - - Guid GetScenarioId(ScenarioContext scenario, FeatureContext feature) - { - var key = new ScenarioAndFeatureKey(scenario, feature); - - if(!scenarioIds.ContainsKey(key)) - scenarioIds.Add(key, Guid.NewGuid()); - - return scenarioIds[key]; - } - - /// - /// Initializes a new instance of the class. - /// - /// Scenario context. - /// Feature context. - /// Integration. - public ScenarioAdapter(ScenarioContext scenarioContext, - FeatureContext featureContext, - IScreenplayIntegration integration) - { - if(integration == null) - throw new ArgumentNullException(nameof(integration)); - if(featureContext == null) - throw new ArgumentNullException(nameof(featureContext)); - if(scenarioContext == null) - throw new ArgumentNullException(nameof(scenarioContext)); - - this.integration = integration; - this.featureContext = featureContext; - this.scenarioContext = scenarioContext; - } - - /// - /// Initializes the class. - /// - static ScenarioAdapter() - { - scenarioIds = new ConcurrentDictionary(); - featureIds = new ConcurrentDictionary(); - } - - /// - /// Gets a value which indicates whether or not a given scenario was a success or not. - /// - /// true, if the scenario was a success, false otherwise. - /// Scenario. - public static bool GetScenarioSuccess(ScenarioContext scenario) => scenario.TestError == null; - } -} diff --git a/CSF.Screenplay.SpecFlow/ScenarioAndFeatureKey.cs b/CSF.Screenplay.SpecFlow/ScenarioAndFeatureKey.cs deleted file mode 100644 index 4de55941..00000000 --- a/CSF.Screenplay.SpecFlow/ScenarioAndFeatureKey.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using TechTalk.SpecFlow; - -namespace CSF.Screenplay.SpecFlow -{ - /// - /// Describes a Feature and Scenario combination, uniquely identifying a scenario. - /// - public class ScenarioAndFeatureKey : IEquatable - { - readonly int cachedHashCode; - readonly ScenarioContext scenario; - readonly FeatureContext feature; - - /// - /// Gets the scenario. - /// - /// The scenario. - public virtual ScenarioContext Scenario => scenario; - - /// - /// Gets the feature. - /// - /// The feature. - public virtual FeatureContext Feature => feature; - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current - /// ; otherwise, false. - public override bool Equals(object obj) - { - return Equals(obj as ScenarioAndFeatureKey); - } - - /// - /// Determines whether the specified is equal to the - /// current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current - /// ; otherwise, false. - public bool Equals(ScenarioAndFeatureKey other) - { - if(ReferenceEquals(this, other)) - return true; - if(ReferenceEquals(null, other)) - return false; - - return ReferenceEquals(Scenario, other.Scenario) && ReferenceEquals(Feature, other.Feature); - } - - /// - /// Serves as a hash function for a object. - /// - /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table. - public override int GetHashCode() - { - return cachedHashCode; - } - - /// - /// Initializes a new instance of the class. - /// - /// Scenario. - /// Feature. - public ScenarioAndFeatureKey(ScenarioContext scenario, FeatureContext feature) - { - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - if(feature == null) - throw new ArgumentNullException(nameof(feature)); - - this.scenario = scenario; - this.feature = feature; - - cachedHashCode = (scenario.ScenarioInfo.Title.GetHashCode() - ^ feature.FeatureInfo.Title.GetHashCode()); - } - } -} diff --git a/CSF.Screenplay.SpecFlow/ScreenplayAssemblyAttribute.cs b/CSF.Screenplay.SpecFlow/ScreenplayAssemblyAttribute.cs deleted file mode 100644 index 5f72f7c9..00000000 --- a/CSF.Screenplay.SpecFlow/ScreenplayAssemblyAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using CSF.Screenplay.Integration; - -namespace CSF.Screenplay.SpecFlow -{ - /// - /// Indicates that the assembly contains Screenplay tests. - /// - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] - public class ScreenplayAssemblyAttribute : Attribute - { - static Lazy integration; - - /// - /// Gets the current Screenplay integration. - /// - /// The integration. - public IScreenplayIntegration Integration => integration.Value; - - /// - /// Initializes a new instance of the class. - /// - /// Integration type. - public ScreenplayAssemblyAttribute(Type configType) - { - integration = integration?? new Lazy(() => new IntegrationFactory().Create(configType)); - } - } -} diff --git a/CSF.Screenplay.SpecFlow/ScreenplayBinding.cs b/CSF.Screenplay.SpecFlow/ScreenplayBinding.cs deleted file mode 100644 index cc767a5c..00000000 --- a/CSF.Screenplay.SpecFlow/ScreenplayBinding.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using BoDi; -using CSF.Screenplay.Integration; -using TechTalk.SpecFlow; - -namespace CSF.Screenplay.SpecFlow -{ - /// - /// Binding type for the SpecFlow/Screenplay integration. - /// - [Binding] - public class ScreenplayBinding - { - static Lazy integration; - static IScreenplayIntegration Integration => integration.Value; - - readonly IObjectContainer container; - - /// - /// Executed before each scenario. - /// - [Before] - public void BeforeScenario() - { - var scenarioContext = container.Resolve(); - var featureContext = container.Resolve(); - - var adapter = new ScenarioAdapter(scenarioContext, featureContext, Integration); - var scenario = adapter.CreateScenario(); - container.RegisterInstanceAs(scenario); - - Integration.BeforeScenario(scenario); - } - - /// - /// Executed after each scenario. - /// - [After] - public void AfterScenario() - { - var scenario = container.Resolve(); - var success = ScenarioAdapter.GetScenarioSuccess(container.Resolve()); - Integration.AfterScenario(scenario, success); - } - - /// - /// Executed before a test run. - /// - [BeforeTestRun] - public static void BeforeTestRun() - { - Integration.BeforeExecutingFirstScenario(); - } - - /// - /// Executed after a test run. - /// - [AfterTestRun] - public static void AfterTestRun() - { - Integration.AfterExecutedLastScenario(); - } - - /// - /// Initializes a new instance of the class. - /// - /// Container. - public ScreenplayBinding(IObjectContainer container) - { - this.container = container; - } - - /// - /// Initializes the class. - /// - static ScreenplayBinding() - { - var provider = new IntegrationProvider(); - integration = provider.GetIntegration(); - } - } -} diff --git a/CSF.Screenplay.SpecFlow/ScreenplayPlugin.cs b/CSF.Screenplay.SpecFlow/ScreenplayPlugin.cs deleted file mode 100644 index 53d5de43..00000000 --- a/CSF.Screenplay.SpecFlow/ScreenplayPlugin.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Reflection; -using TechTalk.SpecFlow.Plugins; - -[assembly: RuntimePlugin(typeof(CSF.Screenplay.SpecFlow.ScreenplayPlugin))] - -namespace CSF.Screenplay.SpecFlow -{ - /// - /// SpecFlow plugin type for Screenplay - /// - public class ScreenplayPlugin : IRuntimePlugin - { - /// - /// The entry-point for an . This initialises the plugin to provide Screenplay - /// capabilities to the SpecFlow tests. - /// - /// Runtime plugin events. - /// Runtime plugin parameters. - public void Initialize(RuntimePluginEvents runtimePluginEvents, - RuntimePluginParameters runtimePluginParameters) - { - runtimePluginEvents.ConfigurationDefaults += (sender, e) => { - e.SpecFlowConfiguration.AdditionalStepAssemblies.Add(ThisAssembly.FullName); - }; - } - - Assembly ThisAssembly => Assembly.GetExecutingAssembly(); - } -} diff --git a/CSF.Screenplay.SpecFlow/packages.config b/CSF.Screenplay.SpecFlow/packages.config deleted file mode 100644 index 35ba1979..00000000 --- a/CSF.Screenplay.SpecFlow/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay/Abilities/Ability.cs b/CSF.Screenplay/Abilities/Ability.cs deleted file mode 100644 index 4ec18234..00000000 --- a/CSF.Screenplay/Abilities/Ability.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Abilities -{ - /// - /// Base type for implementations of . - /// - /// - /// - /// Implementors have three mandatory methods to override and implement, as well as one optional (the - /// disposal method). - /// - /// - /// Implementors of are not required to derive from this type, it is offered only as a - /// convenience. - /// - /// - public abstract class Ability : IAbility, IDisposable - { - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. - protected virtual string GetReport(INamed actor) - { - return $"{actor.Name} is able to {GetType().Name}"; - } - - string IReportable.GetReport(INamed actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - return GetReport(actor); - } - - #region IDisposable Support - - bool disposed; - - /// - /// Gets a value indicating whether this is disposed. - /// - /// true if disposed; otherwise, false. - protected bool Disposed => disposed; - - /// - /// Performs disposal of the current instance. - /// - /// If set to true then we are explicitly disposing. - protected virtual void Dispose(bool disposing) - { - if(!disposed) - { - disposed = true; - } - } - - /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. - /// - ~Ability() - { - Dispose(false); - } - - void IDisposable.Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - #endregion - } -} diff --git a/CSF.Screenplay/Abilities/AbilityStore.cs b/CSF.Screenplay/Abilities/AbilityStore.cs deleted file mode 100644 index f7a02feb..00000000 --- a/CSF.Screenplay/Abilities/AbilityStore.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CSF.Screenplay.Abilities -{ - /// - /// Implementation of which uses a generic ISet to hold the abilities. - /// - public class AbilityStore : IAbilityStore - { - readonly ISet abilities; - - /// - /// Determines whether or not the current instance contains an ability or not. - /// - /// true, if the current instance has the ability, false otherwise. - /// The desired ability type. - public virtual bool HasAbility() where TAbility : IAbility - { - return abilities.Any(x => AbilityImplementsType(x, typeof(TAbility))); - } - - /// - /// Gets an ability of the noted type. - /// - /// The ability. - /// The desired ability type. - public virtual TAbility GetAbility() where TAbility : IAbility - { - return (TAbility) abilities.FirstOrDefault(x => AbilityImplementsType(x, typeof(TAbility))); - } - - /// - /// Adds an ability to the current instance. - /// - /// The ability. - public virtual void Add(IAbility ability) - { - if(ability == null) - throw new ArgumentNullException(nameof(ability)); - - abilities.Add(ability); - } - - /// - /// Instantiates an ability of the given type, adds it to the current store instance and returns the created ability. - /// - /// The ability type. - public virtual IAbility Add(Type abilityType) - { - if(!typeof(IAbility).IsAssignableFrom(abilityType)) - throw new ArgumentException($"Ability type must implement `{typeof(IAbility).Name}'.", nameof(abilityType)); - - var ability = (IAbility) Activator.CreateInstance(abilityType); - Add(ability); - return ability; - } - - bool AbilityImplementsType(IAbility ability, Type desiredType) - { - var abilityType = GetAbilityType(ability); - if(abilityType == null) - return false; - - return desiredType.IsAssignableFrom(abilityType); - } - - Type GetAbilityType(IAbility ability) - { - if(ReferenceEquals(ability, null)) - return null; - - return ability.GetType(); - } - - #region IDisposable implementation - - bool disposed; - - /// - /// Gets a value indicating whether this is disposed. - /// - /// true if disposed; otherwise, false. - protected bool Disposed => disposed; - - /// - /// Performs disposal of the current instance. - /// - /// If set to true then we are explicitly disposing. - protected virtual void Dispose(bool disposing) - { - if(!disposed) - { - if(disposing) - { - foreach(var ability in abilities) - { - ability.Dispose(); - } - } - - disposed = true; - } - } - - void IDisposable.Dispose() - { - Dispose(true); - } - - #endregion - - /// - /// Initializes a new instance of the class. - /// - public AbilityStore() - { - abilities = new HashSet(); - } - } -} diff --git a/CSF.Screenplay/Abilities/IAbility.cs b/CSF.Screenplay/Abilities/IAbility.cs deleted file mode 100644 index 0e4103d1..00000000 --- a/CSF.Screenplay/Abilities/IAbility.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Abilities -{ - /// - /// An ability which can be held by an . - /// - public interface IAbility : IDisposable, IReportable - { - } -} \ No newline at end of file diff --git a/CSF.Screenplay/Abilities/IAbilityStore.cs b/CSF.Screenplay/Abilities/IAbilityStore.cs deleted file mode 100644 index ccb2d992..00000000 --- a/CSF.Screenplay/Abilities/IAbilityStore.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -namespace CSF.Screenplay.Abilities -{ - /// - /// Container type responsible for organising the abilities owned by an . - /// - public interface IAbilityStore : IDisposable - { - /// - /// Determines whether or not the current instance contains an ability or not. - /// - /// true, if the current instance has the ability, false otherwise. - /// The desired ability type. - bool HasAbility() where TAbility : IAbility; - - /// - /// Gets an ability of the noted type. - /// - /// The ability. - /// The desired ability type. - TAbility GetAbility() where TAbility : IAbility; - - /// - /// Adds an ability to the current instance. - /// - /// The ability. - void Add(IAbility ability); - - /// - /// Instantiates an ability of the given type, adds it to the current store instance and returns the created ability. - /// - /// The ability type. - IAbility Add(Type abilityType); - } -} diff --git a/CSF.Screenplay/Actors/Actor.cs b/CSF.Screenplay/Actors/Actor.cs deleted file mode 100644 index afafe9ea..00000000 --- a/CSF.Screenplay/Actors/Actor.cs +++ /dev/null @@ -1,488 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Actors -{ - /// - /// The main implementation of . which represents an actor/participant/persona within a test - /// scenario. - /// - /// - /// - /// Actors may be given abilities, which provide the actions which they can take. - /// In order to have them use those abilities to perform actions, you should use the static members of - /// . It is recommended to use these via a using static CSF.Screenplay.StepComposer; - /// statement. This permits usages such as: - /// - /// - /// Given(joe).WasAbleTo(takeOutTheTrash); - /// - /// - public class Actor : IActor - { - #region fields - - readonly IAbilityStore abilityStore; - readonly string name; - readonly Guid scenarioIdentity; - - #endregion - - #region properties - - /// - /// Gets the name of the current actor. - /// - /// The name. - public virtual string Name => name; - - /// - /// Gets the identity of the scenario with which the current actor is associated. - /// - /// The scenario identity. - public virtual Guid ScenarioIdentity => scenarioIdentity; - - #endregion - - #region methods - - /// - /// Adds an ability of the indicated type to the current instance. - /// - /// - /// - /// This overload requires that the ability type has a public parameterless constructor. - /// An instance of the ability type is created/instantiated as part of this operation. - /// - /// - /// The desired ability type. - public virtual void IsAbleTo() where TAbility : IAbility,new() - { - var ability = abilityStore.Add(typeof(TAbility)); - InvokeGainedAbility(ability); - } - - /// - /// Adds an ability of the indicated type to the current instance. - /// - /// - /// - /// This overload requires that the ability type has a public parameterless constructor. - /// An instance of the ability type is created/instantiated as part of this operation. - /// - /// - /// The desired ability type. - public virtual void IsAbleTo(Type abilityType) - { - var ability = abilityStore.Add(abilityType); - InvokeGainedAbility(ability); - } - - /// - /// Adds an ability object to the current instance. - /// - /// The ability. - public virtual void IsAbleTo(IAbility ability) - { - abilityStore.Add(ability); - InvokeGainedAbility(ability); - } - - /// - /// Performs an action or task. - /// - /// The performable item to execute. - protected virtual void Perform(IPerformable performable) - { - if(ReferenceEquals(performable, null)) - throw new ArgumentNullException(nameof(performable)); - - try - { - InvokeBeginPerformance(performable); - performable.PerformAs(this); - InvokeEndPerformance(performable); - } - catch(Exception ex) - { - InvokePerformanceFailed(performable, ex); - throw; - } - } - - /// - /// Performs an action or task which has a public parameterless constructor. - /// - /// The type of the performable item to execute. - protected virtual void Perform() where TPerformable : IPerformable,new() - { - var performable = Activator.CreateInstance(); - Perform(performable); - } - - /// - /// Performs an action, task or asks a question which returns a result value. - /// - /// The result of performing the item - /// The performable item to execute. - /// The result type. - protected virtual TResult Perform(IPerformable performable) - { - if(ReferenceEquals(performable, null)) - throw new ArgumentNullException(nameof(performable)); - - TResult result; - - try - { - InvokeBeginPerformance(performable); - result = performable.PerformAs(this); - InvokePerformanceResult(performable, result); - InvokeEndPerformance(performable); - } - catch(Exception ex) - { - InvokePerformanceFailed(performable, ex); - throw; - } - - return result; - } - - /// - /// Determines whether or not the given performer has an ability or not. - /// - /// true, if the performer has the ability, false otherwise. - /// The desired ability type. - protected virtual bool HasAbility() where TAbility : IAbility - { - return abilityStore.HasAbility(); - } - - /// - /// Gets an ability of the noted type. - /// - /// The ability. - /// The desired ability type. - protected virtual TAbility GetAbility() where TAbility : IAbility - { - var ability = abilityStore.GetAbility(); - - if(ReferenceEquals(ability, null)) - throw new MissingAbilityException($"{Name} does not have the ability {typeof(TAbility).Name}."); - - return ability; - } - - - #endregion - - #region events and invokers - - /// - /// Occurs when the actor begins a performance. - /// - public event EventHandler BeginPerformance; - - /// - /// Occurs when an actor ends a performance. - /// - public event EventHandler EndPerformance; - - /// - /// Occurs when an actor receives a result from a performance. - /// - public event EventHandler PerformanceResult; - - /// - /// Occurs when a performance fails with an exception. - /// - public event EventHandler PerformanceFailed; - - /// - /// Occurs when an actor gains a new ability. - /// - public event EventHandler GainedAbility; - - /// - /// Occurs when the actor begins a 'Given' task, action or question. - /// - public event EventHandler BeginGiven; - - /// - /// Occurs when the actor finishes a 'Given' task, action or question. - /// - public event EventHandler EndGiven; - - /// - /// Occurs when the actor begins a 'When' task, action or question. - /// - public event EventHandler BeginWhen; - - /// - /// Occurs when the actor finishes a 'When' task, action or question. - /// - public event EventHandler EndWhen; - - /// - /// Occurs when the actor begins a 'Then' task, action or question (usually a question). - /// - public event EventHandler BeginThen; - - /// - /// Occurs when the actor finishes a 'Then' task, action or question (usually a question). - /// - public event EventHandler EndThen; - - /// - /// Invokes the begin performance event. - /// - /// Performable. - protected virtual void InvokeBeginPerformance(IPerformable performable) - { - var args = new BeginPerformanceEventArgs(this, performable); - BeginPerformance?.Invoke(this, args); - } - - /// - /// Invokes the end performance event. - /// - /// Performable. - protected virtual void InvokeEndPerformance(IPerformable performable) - { - var args = new EndSuccessfulPerformanceEventArgs(this, performable); - EndPerformance?.Invoke(this, args); - } - - /// - /// Invokes the performance result event. - /// - /// Performable. - /// Result. - protected virtual void InvokePerformanceResult(IPerformable performable, object result) - { - var args = new PerformanceResultEventArgs(this, performable, result); - PerformanceResult?.Invoke(this, args); - } - - /// - /// Invokes the performance failed event. - /// - /// Performable. - /// Exception. - protected virtual void InvokePerformanceFailed(IPerformable performable, Exception exception) - { - var args = new PerformanceFailureEventArgs(this, performable, exception); - PerformanceFailed?.Invoke(this, args); - } - - /// - /// Invokes the gained ability event. - /// - /// Ability. - protected virtual void InvokeGainedAbility(IAbility ability) - { - var args = new GainAbilityEventArgs(this, ability); - GainedAbility?.Invoke(this, args); - } - - /// - /// Invokes the begin-given event. - /// - protected virtual void InvokeBeginGiven() - { - var args = new ActorEventArgs(this); - BeginGiven?.Invoke(this, args); - } - - /// - /// Invokes the end-given event. - /// - protected virtual void InvokeEndGiven() - { - var args = new ActorEventArgs(this); - EndGiven?.Invoke(this, args); - } - - /// - /// Invokes the begin-when event. - /// - protected virtual void InvokeBeginWhen() - { - var args = new ActorEventArgs(this); - BeginWhen?.Invoke(this, args); - } - - /// - /// Invokes the end-when event. - /// - protected virtual void InvokeEndWhen() - { - var args = new ActorEventArgs(this); - EndWhen?.Invoke(this, args); - } - - /// - /// Invokes the begin-then event. - /// - protected virtual void InvokeBeginThen() - { - var args = new ActorEventArgs(this); - BeginThen?.Invoke(this, args); - } - - /// - /// Invokes the end-then event. - /// - protected virtual void InvokeEndThen() - { - var args = new ActorEventArgs(this); - EndThen?.Invoke(this, args); - } - - #endregion - - #region explicit IPerformer and IActor implementations - - void IGivenActor.WasAbleTo(IPerformable performable) - { - InvokeBeginGiven(); - Perform(performable); - InvokeEndGiven(); - } - - void IGivenActor.WasAbleTo() - { - InvokeBeginGiven(); - Perform(); - InvokeEndGiven(); - } - - void IWhenActor.AttemptsTo(IPerformable performable) - { - InvokeBeginWhen(); - Perform(performable); - InvokeEndWhen(); - } - - void IWhenActor.AttemptsTo() - { - InvokeBeginWhen(); - Perform(); - InvokeEndWhen(); - } - - void IThenActor.Should(IPerformable performable) - { - InvokeBeginThen(); - Perform(performable); - InvokeEndThen(); - } - - void IThenActor.Should() - { - InvokeBeginThen(); - Perform(); - InvokeEndThen(); - } - - TResult IGivenActor.WasAbleTo(IPerformable performable) - { - InvokeBeginGiven(); - var result = Perform(performable); - InvokeEndGiven(); - return result; - } - - TResult IWhenActor.AttemptsTo(IPerformable performable) - { - InvokeBeginWhen(); - var result = Perform(performable); - InvokeEndWhen(); - return result; - } - - TResult IThenActor.Should(IPerformable performable) - { - InvokeBeginThen(); - var result = Perform(performable); - InvokeEndThen(); - return result; - } - - TResult IGivenActor.Saw(IQuestion question) - { - InvokeBeginGiven(); - var result = Perform(question); - InvokeEndGiven(); - return result; - } - - TResult IWhenActor.Sees(IQuestion question) - { - InvokeBeginWhen(); - var result = Perform(question); - InvokeEndWhen(); - return result; - } - - TResult IThenActor.ShouldSee(IQuestion question) - { - InvokeBeginThen(); - var result = Perform(question); - InvokeEndThen(); - return result; - } - - bool IPerformer.HasAbility() - { - return HasAbility(); - } - - TAbility IPerformer.GetAbility() - { - return GetAbility(); - } - - void IPerformer.Perform(IPerformable performable) - { - Perform(performable); - } - - void IPerformer.Perform() - { - Perform(); - } - - TResult IPerformer.Perform(IPerformable performable) - { - return Perform(performable); - } - - #endregion - - #region constructor - - /// - /// Initializes a new instance of the class. - /// - /// The actor's name. - /// The screenplay scenario identity. - public Actor(string name, Guid scenarioIdentity) - { - if(name == null) - throw new ArgumentNullException(nameof(name)); - if(scenarioIdentity == Guid.Empty) - throw new ArgumentException("The scenario identity must be populated", nameof(scenarioIdentity)); - - this.name = name; - this.scenarioIdentity = scenarioIdentity; - abilityStore = new AbilityStore(); - } - - #endregion - } -} diff --git a/CSF.Screenplay/Actors/ActorEventArgs.cs b/CSF.Screenplay/Actors/ActorEventArgs.cs deleted file mode 100644 index a448c813..00000000 --- a/CSF.Screenplay/Actors/ActorEventArgs.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// Represents event arguments which include reference to an actor. - /// - public class ActorEventArgs : EventArgs - { - /// - /// Gets the actor. - /// - /// The actor. - public IActor Actor { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// Actor. - public ActorEventArgs(IActor actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - Actor = actor; - } - } -} diff --git a/CSF.Screenplay/Actors/BeginPerformanceEventArgs.cs b/CSF.Screenplay/Actors/BeginPerformanceEventArgs.cs deleted file mode 100644 index 171c8d60..00000000 --- a/CSF.Screenplay/Actors/BeginPerformanceEventArgs.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Event arguments relating to the beginning of the performance of an action, task or question. - /// - public class BeginPerformanceEventArgs : PerformanceEventArgsBase - { - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public BeginPerformanceEventArgs(IActor actor, IPerformable performable) : base(actor, performable) {} - } -} diff --git a/CSF.Screenplay/Actors/Cast.cs b/CSF.Screenplay/Actors/Cast.cs deleted file mode 100644 index 2eb54e73..00000000 --- a/CSF.Screenplay/Actors/Cast.cs +++ /dev/null @@ -1,234 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CSF.Screenplay.Actors -{ - /// - /// A cast is a container for many actors. It may be useful in scenarios in which many actors are involved. - /// - /// - /// - /// There is no need to make use of a instance if there is no need. If you need only use a - /// single actor then it is far easier to stick with just one. For testing scenarios in which multiple actors are - /// involved though, making all of those actor instances available across multiple classes can be difficult. - /// - /// - /// This is where the object becomes useful. - /// - /// - public class Cast : ICast - { - #region fields - - readonly IDictionary actors; - readonly object syncRoot; - - #endregion - - #region properties - - /// - /// Gets a collection of the currently-available actors. - /// - /// The actors. - protected IDictionary Actors => actors; - - #endregion - - #region public API - - /// - /// Gets a collection of all of the actors contained within the current instance. - /// - /// A collection of actors. - public virtual IEnumerable GetAll() => Actors.Values.ToArray(); - - /// - /// Gets a value which indicates whether or not the current instance has an actor of the given name. - /// - /// true, if an actor of the specified name exists in the current cast, false otherwise. - /// The name for which to search. - public virtual bool HasActor(string name) => Actors.ContainsKey(name); - - /// - /// Gets a single actor by their name. - /// - /// The named actor, or a null reference if no such actor is contained in the current instance. - /// The actor name. - public virtual IActor GetExisting(string name) - { - lock(syncRoot) - { - return GetActorLocked(name); - } - } - - /// - /// Gets a single actor by their name, creating them if they do not already exist in the cast. - /// If this operation leads to the creation of a new actor then it will fire both - /// and then . - /// - /// The named actor, which might be a newly-created actor. - /// The actor name. - /// If the actor does not yet exist, then this action will be executed to customise the newly-created actor. - /// The current screenplay scenario. - public virtual IActor Get(string name, - Action createCustomisation, - IScreenplayScenario scenario) - { - if(createCustomisation == null) - throw new ArgumentNullException(nameof(createCustomisation)); - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - - IActor actor; - - lock(syncRoot) - { - actor = GetActorLocked(name); - if(actor != null) - return actor; - - actor = CreateAndAddLocked(name, scenario.Identity); - } - - createCustomisation(actor, scenario); - return actor; - } - - /// - /// Creates a new actor of the given name and adds it to the current cast instance. - /// This operation will fire both and then . - /// - /// The actor name. - /// The identity of the scenario to which the actor belongs. - public virtual void Add(string name, Guid scenarioIdentity) - { - lock(syncRoot) - { - CreateAndAddLocked(name, scenarioIdentity); - } - } - - /// - /// Adds the given actor to the current cast instance. - /// - /// An actor. - public virtual void Add(IActor actor) - { - lock(syncRoot) - { - AddLocked(actor); - } - } - - /// - /// Clears the current cast. - /// - public virtual void Dismiss() - { - lock(syncRoot) - { - Actors.Clear(); - } - } - - /// - /// Creates and returns a new object which implements . - /// - /// The actor. - /// The actor's name. - /// The screenplay scenario identity. - protected virtual IActor CreateActor(string name, Guid scenarioIdentity) - { - var actor = new Actor(name, scenarioIdentity); - OnActorCreated(actor); - return actor; - } - - IActor GetActorLocked(string name) - { - IActor output; - if(Actors.TryGetValue(name, out output)) - { - return output; - } - return null; - } - - IActor CreateAndAddLocked(string name, Guid scenarioIdentity) - { - var actor = CreateActor(name, scenarioIdentity); - AddLocked(actor); - return actor; - } - - void AddLocked(IActor actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - var name = actor.Name; - if(name == null) - throw new ArgumentException("Actors must have a name", nameof(actor)); - - if(Actors.ContainsKey(name)) - throw new DuplicateActorException($"There is already an actor named '{name}' contained within the current {typeof(Cast).Name}. Duplicates are not permitted."); - - Actors.Add(name, actor); - OnActorAdded(actor); - } - - #endregion - - #region events and invokers - - /// - /// An event which is triggered any time a new actor is created by the current cast. - /// Fires before . - /// - public event EventHandler ActorCreated; - - /// - /// Event invoker for the event. - /// - /// Actor. - protected virtual void OnActorCreated(IActor actor) - { - var args = new ActorEventArgs(actor); - ActorCreated?.Invoke(this, args); - } - - /// - /// An event which is triggered any time a new actor is added to the current cast. - /// Where an actor is created then added, this event fires after . - /// - public event EventHandler ActorAdded; - - /// - /// Event invoker for the event. - /// - /// Actor. - protected virtual void OnActorAdded(IActor actor) - { - var args = new ActorEventArgs(actor); - ActorAdded?.Invoke(this, args); - } - - #endregion - - #region constructor - - /// - /// Initializes a new instance of the class. - /// - public Cast() - { - syncRoot = new Object(); - actors = new Dictionary(); - } - - #endregion - } -} diff --git a/CSF.Screenplay/Actors/DuplicateActorException.cs b/CSF.Screenplay/Actors/DuplicateActorException.cs deleted file mode 100644 index 6e26ad74..00000000 --- a/CSF.Screenplay/Actors/DuplicateActorException.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// Exception raised when a duplicate actor is added to a instance. - /// - [System.Serializable] - public class DuplicateActorException : Exception - { - /// - /// Initializes a new instance of the class - /// - public DuplicateActorException() - { - } - - /// - /// Initializes a new instance of the class - /// - /// A that describes the exception. - public DuplicateActorException (string message) : base(message) - { - } - - /// - /// Initializes a new instance of the class - /// - /// A that describes the exception. - /// The exception that is the cause of the current exception. - public DuplicateActorException (string message, Exception inner) : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class - /// - /// The contextual information about the source or destination. - /// The object that holds the serialized object data. - protected DuplicateActorException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) - { - } - } -} diff --git a/CSF.Screenplay/Actors/EndSuccessfulPerformanceEventArgs.cs b/CSF.Screenplay/Actors/EndSuccessfulPerformanceEventArgs.cs deleted file mode 100644 index f9a1f421..00000000 --- a/CSF.Screenplay/Actors/EndSuccessfulPerformanceEventArgs.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Event arguments relating to the successful completion of the performance of an action, task or question. - /// - public class EndSuccessfulPerformanceEventArgs : PerformanceEventArgsBase - { - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public EndSuccessfulPerformanceEventArgs(IActor actor, IPerformable performable) : base(actor, performable) {} - } -} diff --git a/CSF.Screenplay/Actors/GainAbilityEventArgs.cs b/CSF.Screenplay/Actors/GainAbilityEventArgs.cs deleted file mode 100644 index 54bf27cd..00000000 --- a/CSF.Screenplay/Actors/GainAbilityEventArgs.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; - -namespace CSF.Screenplay.Actors -{ - /// - /// Event arguments for an actor gaining an ability. - /// - public class GainAbilityEventArgs : ActorEventArgs - { - /// - /// Gets the ability which was added to the actor. - /// - /// The ability. - public IAbility Ability { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The ability. - public GainAbilityEventArgs(IActor actor, IAbility ability) : base(actor) - { - if(ability == null) - throw new ArgumentNullException(nameof(ability)); - - Ability = ability; - } - } -} diff --git a/CSF.Screenplay/Actors/IActor.cs b/CSF.Screenplay/Actors/IActor.cs deleted file mode 100644 index 62aa2cd4..00000000 --- a/CSF.Screenplay/Actors/IActor.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// An actor is a persona who may participate in a testing scenario. - /// Actors are given abilities. These abilities allow them to make use of - /// items, which may be tasks, actions or questions. - /// - public interface IActor : INamed, IPerformer, IGivenActor, IThenActor, IWhenActor, ICanReceiveAbilities - { - /// - /// Gets the identity of the scenario with which the current actor is associated. - /// - /// The scenario identity. - Guid ScenarioIdentity { get;} - - /// - /// Occurs when the actor begins a performance. - /// - event EventHandler BeginPerformance; - - /// - /// Occurs when an actor ends a performance. - /// - event EventHandler EndPerformance; - - /// - /// Occurs when an actor receives a result from a performance. - /// - event EventHandler PerformanceResult; - - /// - /// Occurs when a performance fails with an exception. - /// - event EventHandler PerformanceFailed; - - /// - /// Occurs when an actor gains a new ability. - /// - event EventHandler GainedAbility; - - /// - /// Occurs when the actor begins a 'Given' task, action or question. - /// - event EventHandler BeginGiven; - - /// - /// Occurs when the actor finishes a 'Given' task, action or question. - /// - event EventHandler EndGiven; - - /// - /// Occurs when the actor begins a 'When' task, action or question. - /// - event EventHandler BeginWhen; - - /// - /// Occurs when the actor finishes a 'When' task, action or question. - /// - event EventHandler EndWhen; - - /// - /// Occurs when the actor begins a 'Then' task, action or question (usually a question). - /// - event EventHandler BeginThen; - - /// - /// Occurs when the actor finishes a 'Then' task, action or question (usually a question). - /// - event EventHandler EndThen; - } -} diff --git a/CSF.Screenplay/Actors/ICanReceiveAbilities.cs b/CSF.Screenplay/Actors/ICanReceiveAbilities.cs deleted file mode 100644 index 2b334653..00000000 --- a/CSF.Screenplay/Actors/ICanReceiveAbilities.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; - -namespace CSF.Screenplay.Actors -{ - /// - /// Represents an actor's ability to receive new instances. - /// - public interface ICanReceiveAbilities - { - /// - /// Adds an ability of the indicated type to the current instance. - /// - /// - /// - /// This overload requires that the ability type has a public parameterless constructor. - /// An instance of the ability type is created/instantiated as part of this operation. - /// - /// - /// The desired ability type. - void IsAbleTo() where TAbility : IAbility,new(); - - /// - /// Adds an ability object to the current instance. - /// - /// The ability. - void IsAbleTo(IAbility ability); - - /// - /// Adds an ability of the indicated type to the current instance. - /// - /// - /// - /// This overload requires that the ability type has a public parameterless constructor. - /// An instance of the ability type is created/instantiated as part of this operation. - /// - /// - /// The desired ability type. - void IsAbleTo(Type abilityType); - } -} \ No newline at end of file diff --git a/CSF.Screenplay/Actors/ICast.cs b/CSF.Screenplay/Actors/ICast.cs deleted file mode 100644 index dca0755c..00000000 --- a/CSF.Screenplay/Actors/ICast.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Actors -{ - /// - /// A cast is a container for many actors. It may be useful in scenarios in which many actors are involved. - /// - /// - /// - /// There is no need to make use of a instance if there is no need. If you need only use a - /// single actor then it is far easier to stick with just one. For testing scenarios in which multiple actors are - /// involved though, making all of those actor instances available across multiple classes can be difficult. - /// - /// - /// This is where the object becomes useful. - /// - /// - public interface ICast - { - /// - /// An event which is triggered any time a new actor is created by the current cast. - /// Fires before . - /// - event EventHandler ActorCreated; - - /// - /// An event which is triggered any time a new actor is added to the current cast. - /// Where an actor is created then added, this event fires after . - /// - event EventHandler ActorAdded; - - /// - /// Gets a collection of all of the actors contained within the current instance. - /// - /// A collection of actors. - IEnumerable GetAll(); - - /// - /// Gets a single actor by their name, but does not create a new actor if they do not already exist. - /// - /// The named actor, or a null reference if no such actor is contained in the current instance. - /// The actor name. - IActor GetExisting(string name); - - /// - /// Gets a value which indicates whether or not the current instance has an actor of the given name. - /// - /// true, if an actor of the specified name exists in the current cast, false otherwise. - /// The name for which to search. - bool HasActor(string name); - - /// - /// Gets a single actor by their name, creating them if they do not already exist in the cast. - /// If this operation leads to the creation of a new actor then it will fire both - /// and then . - /// - /// The named actor, which might be a newly-created actor. - /// The actor name. - /// If the actor does not yet exist, then this action will be executed to customise the newly-created actor. - /// The current screenplay scenario. - IActor Get(string name, Action createCustomisation, IScreenplayScenario scenario); - - /// - /// Creates a new actor of the given name and adds it to the current cast instance. - /// This operation will fire both and then . - /// - /// The actor name. - /// The identity of the scenario to which the actor belongs. - void Add(string name, Guid scenarioIdentity); - - /// - /// Adds the given actor to the current cast instance. - /// This operation will fire but not . - /// - /// An actor. - void Add(IActor actor); - - /// - /// Clears the current cast. - /// - void Dismiss(); - } -} diff --git a/CSF.Screenplay/Actors/IGivenActor.cs b/CSF.Screenplay/Actors/IGivenActor.cs deleted file mode 100644 index 43fc0d59..00000000 --- a/CSF.Screenplay/Actors/IGivenActor.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Represents an actor which is able to perform 'given' steps (preconditions to performing actions). - /// - public interface IGivenActor - { - /// - /// Performs the given action or task. - /// - /// A performable item. - void WasAbleTo(IPerformable performable); - - /// - /// Performs an action or task which has a public parameterless constructor. - /// - /// The type of the performable item to execute. - void WasAbleTo() where TPerformable : IPerformable,new(); - - /// - /// Performs the given action, task or question and gets a result. - /// - /// The result of performing the task. - /// A task. - /// The result type, returned from the task. - TResult WasAbleTo(IPerformable performable); - - /// - /// Asks the given question and gets the answer. - /// - /// The answer returned from the question. - /// A question. - /// The result type, returned from the question. - TResult Saw(IQuestion question); - } -} diff --git a/CSF.Screenplay/Actors/INamed.cs b/CSF.Screenplay/Actors/INamed.cs deleted file mode 100644 index f23d454f..00000000 --- a/CSF.Screenplay/Actors/INamed.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// Represents any actor or performer which can provide information about its name. - /// - public interface INamed - { - /// - /// Gets the name of the actor. - /// - /// The name. - string Name { get; } - } -} diff --git a/CSF.Screenplay/Actors/IPerformer.cs b/CSF.Screenplay/Actors/IPerformer.cs deleted file mode 100644 index ec15117a..00000000 --- a/CSF.Screenplay/Actors/IPerformer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Represents an actor's ability to perform actions. - /// - public interface IPerformer : INamed - { - /// - /// Determines whether or not the given performer has an ability or not. - /// - /// true, if the performer has the ability, false otherwise. - /// The desired ability type. - bool HasAbility() where TAbility : IAbility; - - /// - /// Gets an ability of the noted type. - /// - /// The ability. - /// The desired ability type. - TAbility GetAbility() where TAbility : IAbility; - - /// - /// Performs an action or task. - /// - /// The performable item to execute. - void Perform(IPerformable performable); - - /// - /// Performs an action or task which has a public parameterless constructor. - /// - /// The type of the performable item to execute. - void Perform() where TPerformable : IPerformable,new(); - - /// - /// Performs an action, task or asks a question which returns a result value. - /// - /// The result of performing the item - /// The performable item to execute. - /// The result type. - TResult Perform(IPerformable performable); - } -} diff --git a/CSF.Screenplay/Actors/IStage.cs b/CSF.Screenplay/Actors/IStage.cs deleted file mode 100644 index 8a4d1d7a..00000000 --- a/CSF.Screenplay/Actors/IStage.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// The stage is a concept which enables the use of "passive voice" in tests, such as - /// "Given Joe has money // When he buys eggs". - /// - public interface IStage - { - /// - /// Gets the actor which is currently "in the spotlight" and thus the subject in the context of the test logic. - /// - /// The actor in the spotlight. - IActor GetTheActorInTheSpotlight(); - - /// - /// Shines the spotlight upon an actor, such that they will now be returned by . - /// This essentially marks them the subject of future test logic. - /// - /// Actor. - void ShineTheSpotlightOn(IActor actor); - - /// - /// Removes the spotlight from the current actor and sets such that no actor has the spotlight. - /// - void RemoveTheSpotlight(); - } -} diff --git a/CSF.Screenplay/Actors/IThenActor.cs b/CSF.Screenplay/Actors/IThenActor.cs deleted file mode 100644 index ee4491d9..00000000 --- a/CSF.Screenplay/Actors/IThenActor.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Represents an actor which is able to perform 'then' steps (post-conditions to performing actions, usually - /// assertions). - /// - public interface IThenActor - { - /// - /// Performs the given action or task. - /// - /// A performable item. - void Should(IPerformable performable); - - /// - /// Performs an action or task which has a public parameterless constructor. - /// - /// The type of the performable item to execute. - void Should() where TPerformable : IPerformable,new(); - - /// - /// Performs the given action, task or question and gets a result. - /// - /// The result of performing the task. - /// A task. - /// The result type, returned from the task. - TResult Should(IPerformable performable); - - /// - /// Asks the given question and gets the answer. - /// - /// The answer returned from the question. - /// A question. - /// The result type, returned from the question. - TResult ShouldSee(IQuestion question); - } -} diff --git a/CSF.Screenplay/Actors/IWhenActor.cs b/CSF.Screenplay/Actors/IWhenActor.cs deleted file mode 100644 index c76af924..00000000 --- a/CSF.Screenplay/Actors/IWhenActor.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Represents an actor which is able to perform 'when' steps (performing the actions which are to be tested, usually - /// exercising the application). - /// - public interface IWhenActor - { - /// - /// Performs the given action or task. - /// - /// A performable item. - void AttemptsTo(IPerformable performable); - - /// - /// Performs an action or task which has a public parameterless constructor. - /// - /// The type of the performable item to execute. - void AttemptsTo() where TPerformable : IPerformable,new(); - - /// - /// Performs the given action, task or question and gets a result. - /// - /// The result of performing the task. - /// A task. - /// The result type, returned from the task. - TResult AttemptsTo(IPerformable performable); - - /// - /// Asks the given question and gets the answer. - /// - /// The answer returned from the question. - /// A question. - /// The result type, returned from the question. - TResult Sees(IQuestion question); - } -} diff --git a/CSF.Screenplay/Actors/MissingAbilityException.cs b/CSF.Screenplay/Actors/MissingAbilityException.cs deleted file mode 100644 index 5dd5040d..00000000 --- a/CSF.Screenplay/Actors/MissingAbilityException.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// Exception raised when ability is requested but is not held by the actor. - /// - [System.Serializable] - public class MissingAbilityException : Exception - { - /// - /// Initializes a new instance of the class - /// - public MissingAbilityException() - { - } - - /// - /// Initializes a new instance of the class - /// - /// A that describes the exception. - public MissingAbilityException(string message) : base(message) - { - } - - /// - /// Initializes a new instance of the class - /// - /// A that describes the exception. - /// The exception that is the cause of the current exception. - public MissingAbilityException(string message, Exception inner) : base(message, inner) - { - } - - /// - /// Initializes a new instance of the class - /// - /// The contextual information about the source or destination. - /// The object that holds the serialized object data. - protected MissingAbilityException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) - { - } - } -} diff --git a/CSF.Screenplay/Actors/PerformanceEventArgsBase.cs b/CSF.Screenplay/Actors/PerformanceEventArgsBase.cs deleted file mode 100644 index 796b468c..00000000 --- a/CSF.Screenplay/Actors/PerformanceEventArgsBase.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Base type for event arguments relating to the performance of a task, action or question. - /// - public abstract class PerformanceEventArgsBase : ActorEventArgs - { - /// - /// Gets the performable item to which these event args relate. - /// - /// The performable. - public IPerformable Performable { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - public PerformanceEventArgsBase(IActor actor, IPerformable performable) : base(actor) - { - if(performable == null) - throw new ArgumentNullException(nameof(performable)); - - Performable = performable; - } - } -} diff --git a/CSF.Screenplay/Actors/PerformanceFailureEventArgs.cs b/CSF.Screenplay/Actors/PerformanceFailureEventArgs.cs deleted file mode 100644 index b2f3e4cb..00000000 --- a/CSF.Screenplay/Actors/PerformanceFailureEventArgs.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Event arguments relating to the failure to execute a task, action or question, where an exception was encountered. - /// - public class PerformanceFailureEventArgs : PerformanceEventArgsBase - { - /// - /// Gets an exception encountered whilst attempting to perform the task, action or question. - /// - /// The exception. - public Exception Exception { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - /// The exception. - public PerformanceFailureEventArgs(IActor actor, IPerformable performable, Exception exception) - : base(actor, performable) - { - if(exception == null) - throw new ArgumentNullException(nameof(exception)); - - Exception = exception; - } - } -} diff --git a/CSF.Screenplay/Actors/PerformanceResultEventArgs.cs b/CSF.Screenplay/Actors/PerformanceResultEventArgs.cs deleted file mode 100644 index 30d8d39f..00000000 --- a/CSF.Screenplay/Actors/PerformanceResultEventArgs.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using CSF.Screenplay.Performables; - -namespace CSF.Screenplay.Actors -{ - /// - /// Event arguments relating to retrieving a result value from a task, action or question. - /// - public class PerformanceResultEventArgs : PerformanceEventArgsBase - { - /// - /// Gets an exception encountered whilst attempting to perform the task, action or question. - /// - /// The exception. - public object Result { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The actor. - /// The performable. - /// The result retrieved from the performable. - public PerformanceResultEventArgs(IActor actor, IPerformable performable, object result) - : base(actor, performable) - { - Result = result; - } - } -} diff --git a/CSF.Screenplay/Actors/Stage.cs b/CSF.Screenplay/Actors/Stage.cs deleted file mode 100644 index 0989d471..00000000 --- a/CSF.Screenplay/Actors/Stage.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -namespace CSF.Screenplay.Actors -{ - /// - /// The stage is a concept which enables the use of "passive voice" in tests, such as - /// "Given Joe has money // When he buys eggs". - /// - public class Stage : IStage - { - IActor currentActor; - - /// - /// Gets the actor which is currently "in the spotlight" and thus the subject in the context of the test logic. - /// - /// The actor in the spotlight. - public IActor GetTheActorInTheSpotlight() - { - if(currentActor == null) - throw new InvalidOperationException("There is no actor currently in the spotlight."); - return currentActor; - } - - /// - /// Removes the spotlight from the current actor and sets such that no actor has the spotlight. - /// - public void RemoveTheSpotlight() => ShineTheSpotlightOn(null); - - /// - /// Shines the spotlight upon an actor, such that they will now be returned by . - /// This essentially marks them the subject of future test logic. - /// - /// Actor. - public void ShineTheSpotlightOn(IActor actor) => currentActor = actor; - } -} diff --git a/CSF.Screenplay/CSF.Screenplay.csproj b/CSF.Screenplay/CSF.Screenplay.csproj deleted file mode 100644 index 615c17ad..00000000 --- a/CSF.Screenplay/CSF.Screenplay.csproj +++ /dev/null @@ -1,121 +0,0 @@ - - - - Debug - AnyCPU - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - Library - CSF.Screenplay - CSF.Screenplay - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG;TRACE - prompt - 4 - bin\Debug\CSF.Screenplay.xml - false - - - true - bin\Release - TRACE - prompt - 4 - bin\Release\CSF.Screenplay.xml - false - - - - - ..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll - - - ..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay/CSF.Screenplay.nuspec b/CSF.Screenplay/CSF.Screenplay.nuspec deleted file mode 100644 index f83573aa..00000000 --- a/CSF.Screenplay/CSF.Screenplay.nuspec +++ /dev/null @@ -1,22 +0,0 @@ - - - - CSF.Screenplay - 0.8.0-alpha - CSF.Screenplay - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - An implementation of the Screenplay (formerly known as Journey) pattern for BDD-based testing. Screenplay focusses on actors and the tasks/actions/questions they perform and ask. - Copyright 2017 - - - - - - - - - - \ No newline at end of file diff --git a/CSF.Screenplay/CastIntegrationBuilderExtensions.cs b/CSF.Screenplay/CastIntegrationBuilderExtensions.cs deleted file mode 100644 index 48c5d7fe..00000000 --- a/CSF.Screenplay/CastIntegrationBuilderExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Integration; - -namespace CSF.Screenplay -{ - /// - /// Extension methods related to integrating an with Screenplay. - /// - public static class CastIntegrationBuilderExtensions - { - /// - /// Configures the current integration to make use of an instance. - /// This includes dismissing that cast after each scenario. - /// - /// Helper. - /// Cast. - /// Name. - public static void UseCast(this IIntegrationConfigBuilder helper, ICast cast = null, string name = null) - { - if(helper == null) - throw new ArgumentNullException(nameof(helper)); - - helper.ServiceRegistrations.PerScenario.Add(regBuilder => { - regBuilder - .RegisterFactory(() => cast?? new Cast()) - .As() - .WithName(name); - }); - } - - /// - /// Configures the current integration to make use of an instance. - /// - /// Helper. - /// Stage. - /// Name. - public static void UseStage(this IIntegrationConfigBuilder helper, IStage stage = null, string name = null) - { - if(helper == null) - throw new ArgumentNullException(nameof(helper)); - - helper.ServiceRegistrations.PerScenario.Add(regBuilder => { - regBuilder - .RegisterFactory(() => stage?? new Stage()) - .As() - .WithName(name); - }); - } - } -} diff --git a/CSF.Screenplay/CastResolverExtensions.cs b/CSF.Screenplay/CastResolverExtensions.cs deleted file mode 100644 index f9cb3d6e..00000000 --- a/CSF.Screenplay/CastResolverExtensions.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using CSF.FlexDi; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay -{ - /// - /// Extension methods related to the resolving of an . - /// - public static class CastResolverExtensions - { - /// - /// Gets the cast from the scenario. - /// - /// The cast. - /// Screenplay scenario. - /// An optional identifying name for the cast instance. - public static ICast GetCast(this IScreenplayScenario scenario, string name = null) - { - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - - return scenario.Resolver.GetCast(name); - } - - /// - /// Gets the cast from the service resolver. - /// - /// The cast. - /// Resolver. - /// Name. - public static ICast GetCast(this IResolvesServices resolver, string name = null) - { - if(resolver == null) - throw new ArgumentNullException(nameof(resolver)); - - return resolver.Resolve(name); - } - - /// - /// Gets the stage from the scenario. - /// - /// The stage. - /// Screenplay scenario. - /// An optional identifying name for the stage instance. - public static IStage GetStage(this IScreenplayScenario scenario, string name = null) - { - if(scenario == null) - throw new ArgumentNullException(nameof(scenario)); - - return scenario.Resolver.GetStage(name); - } - - /// - /// Gets the stage from the service resolver. - /// - /// The stage. - /// Resolver. - /// An optional identifying name for the stage instance. - public static IStage GetStage(this IResolvesServices resolver, string name = null) - { - if(resolver == null) - throw new ArgumentNullException(nameof(resolver)); - - return resolver.Resolve(name); - } - } -} diff --git a/CSF.Screenplay/IScreenplayScenario.cs b/CSF.Screenplay/IScreenplayScenario.cs deleted file mode 100644 index 1f3d4845..00000000 --- a/CSF.Screenplay/IScreenplayScenario.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay -{ - /// - /// Represents a single scenario within Screenplay-based test. - /// - public interface IScreenplayScenario : IScenarioName, IDisposable - { - /// - /// Gets a value which indicates whether or not the scenario was a success. - /// - /// The success. - bool? Success { get; set; } - - /// - /// Gets a MicroDi dependency resolver. - /// - /// The resolver. - FlexDi.IResolvesServices Resolver { get; } - - /// - /// Creates a new actor with the given name. - /// - /// The actor. - /// Name. - IActor CreateActor(string name); - - /// - /// Occurs when the scenario begins. - /// - event EventHandler BeginScenario; - - /// - /// Occurs when the scenario ends. - /// - event EventHandler EndScenario; - } -} diff --git a/CSF.Screenplay/Integration/IIntegrationConfig.cs b/CSF.Screenplay/Integration/IIntegrationConfig.cs deleted file mode 100644 index f6b96956..00000000 --- a/CSF.Screenplay/Integration/IIntegrationConfig.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -namespace CSF.Screenplay.Integration -{ - /// - /// In order to integrate Screenplay with your testing framework of choice, you must write a class which - /// implements this interface. Your implementation will provide the integration information in order to make - /// Screenplay work, including all of the extensions you wish to use. - /// - public interface IIntegrationConfig - { - /// - /// Configures Screenplay using a configuration builder type. - /// - /// Builder. - void Configure(IIntegrationConfigBuilder builder); - } -} diff --git a/CSF.Screenplay/Integration/IIntegrationConfigBuilder.cs b/CSF.Screenplay/Integration/IIntegrationConfigBuilder.cs deleted file mode 100644 index 41035b56..00000000 --- a/CSF.Screenplay/Integration/IIntegrationConfigBuilder.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.FlexDi; -using CSF.FlexDi.Builders; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Integration -{ - /// - /// Exposes a number of collections of callbacks, which are used to configure the integration between - /// Screenplay and a testing framework. - /// - public interface IIntegrationConfigBuilder - { - /// - /// Gets the callbacks which are used to register Screenplay-related services. - /// - /// The service registrations. - ServiceRegistrations ServiceRegistrations { get; } - - /// - /// Gets a collection of callbacks which are executed before the first scenario in a test run. - /// - /// The before first scenario. - IList> BeforeFirstScenario { get; } - - /// - /// Gets a collection of callbacks which are executed after the last scenario in a test run. - /// - /// The after last scenario. - IList> AfterLastScenario { get; } - - /// - /// Gets a collection of callbacks which are executed before each scenario. - /// - /// The before scenario. - IList> BeforeScenario { get; } - - /// - /// Gets a collection of callbacks which are executed after each scenario. - /// - /// The after scenario. - IList> AfterScenario { get; } - } -} diff --git a/CSF.Screenplay/Integration/IScreenplayIntegration.cs b/CSF.Screenplay/Integration/IScreenplayIntegration.cs deleted file mode 100644 index 8264a1f2..00000000 --- a/CSF.Screenplay/Integration/IScreenplayIntegration.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Integration -{ - /// - /// This is the API published to testing frameworks, for the purpose of integrating the testing - /// framework with Screenplay. The methods published by this type should be executed at the named points - /// in the test run. - /// - public interface IScreenplayIntegration - { - /// - /// Executed once, before the first scenario in the test run is executed. Note that - /// all services must have already been registered prior to executing this method. - /// - void BeforeExecutingFirstScenario(); - - /// - /// Executed before each scenario in a test run. - /// - /// Scenario. - void BeforeScenario(IScreenplayScenario scenario); - - /// - /// Executed after each scenario in a test run. - /// - /// Scenario. - /// If set to true success. - void AfterScenario(IScreenplayScenario scenario, bool? success); - - /// - /// Executed after the last scenario in a test run. - /// - void AfterExecutedLastScenario(); - - /// - /// Gets the scenario factory. - /// - /// The scenario factory. - IScenarioFactory GetScenarioFactory(); - } -} diff --git a/CSF.Screenplay/Integration/IntegrationConfigurationBuilder.cs b/CSF.Screenplay/Integration/IntegrationConfigurationBuilder.cs deleted file mode 100644 index 2a659630..00000000 --- a/CSF.Screenplay/Integration/IntegrationConfigurationBuilder.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.FlexDi; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Integration -{ - /// - /// Default implementation of the . - /// - public class IntegrationConfigurationBuilder : IIntegrationConfigBuilder - { - /// - /// Gets the callbacks which are used to register Screenplay-related services. - /// - /// The service registrations. - public ServiceRegistrations ServiceRegistrations { get; private set; } - - /// - /// Gets a collection of callbacks which are executed before the first scenario in a test run. - /// - /// The before first scenario. - public IList> BeforeFirstScenario { get; private set; } - - /// - /// Gets a collection of callbacks which are executed after the last scenario in a test run. - /// - /// The after last scenario. - public IList> AfterLastScenario { get; private set; } - - /// - /// Gets a collection of callbacks which are executed before each scenario. - /// - /// The before scenario. - public IList> BeforeScenario { get; private set; } - - /// - /// Gets a collection of callbacks which are executed after each scenario. - /// - /// The after scenario. - public IList> AfterScenario { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - public IntegrationConfigurationBuilder() - { - ServiceRegistrations = new ServiceRegistrations(); - BeforeFirstScenario = new List>(); - AfterLastScenario = new List>(); - BeforeScenario = new List>(); - AfterScenario = new List>(); - } - } -} diff --git a/CSF.Screenplay/Integration/IntegrationFactory.cs b/CSF.Screenplay/Integration/IntegrationFactory.cs deleted file mode 100644 index 36e5990b..00000000 --- a/CSF.Screenplay/Integration/IntegrationFactory.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Integration -{ - /// - /// Factory type for the creation of a sceeenplay integration. - /// - public class IntegrationFactory - { - /// - /// Factory method which creates a new implementation of - /// from a given configuration type. - /// - /// Config type. - public IScreenplayIntegration Create(Type configType) - { - var config = GetConfig(configType); - var builder = GetBuilder(config); - - return new ScreenplayIntegration(builder); - } - - IIntegrationConfig GetConfig(Type configType) - { - if(configType == null) - throw new ArgumentNullException(nameof(configType)); - - if(!typeof(IIntegrationConfig).IsAssignableFrom(configType)) - { - throw new ArgumentException($"Configuration type must implement `{typeof(IIntegrationConfig).Name}'.", - nameof(configType)); - } - - return (IIntegrationConfig) Activator.CreateInstance(configType); - } - - IIntegrationConfigBuilder GetBuilder(IIntegrationConfig config) - { - var output = new IntegrationConfigurationBuilder(); - config.Configure(output); - return output; - } - } -} diff --git a/CSF.Screenplay/Integration/ScreenplayIntegration.cs b/CSF.Screenplay/Integration/ScreenplayIntegration.cs deleted file mode 100644 index fd3cf8b2..00000000 --- a/CSF.Screenplay/Integration/ScreenplayIntegration.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using CSF.FlexDi; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Integration -{ - /// - /// Base type for custom screenplay integrations. This is suitable for subclassing in custom integrations. - /// - public class ScreenplayIntegration : IScreenplayIntegration - { - #region fields - - readonly IIntegrationConfigBuilder builder; - readonly TestRunEvents testRunEvents; - readonly Lazy rootContainer; - - #endregion - - #region protected properties - - /// - /// Gets the root dependency injection container which carries . - /// - /// The root container. - protected IContainer RootContainer => rootContainer.Value; - - #endregion - - #region public API - - /// - /// Executed once, before the first scenario in the test run is executed. Note that - /// all services must have already been registered prior to executing this method. - /// - public void BeforeExecutingFirstScenario() - { - foreach(var callback in builder.BeforeFirstScenario) - callback(testRunEvents, RootContainer); - - testRunEvents.NotifyBeginTestRun(); - } - - /// - /// Executed before each scenario in a test run. - /// - /// Scenario. - public void BeforeScenario(IScreenplayScenario scenario) - { - foreach(var callback in builder.BeforeScenario) - callback(scenario); - - if(scenario is ICanBeginAndEndScenario) - ((ICanBeginAndEndScenario) scenario).Begin(); - } - - /// - /// Executed after each scenario in a test run. - /// - /// Scenario. - /// If set to true success. - public void AfterScenario(IScreenplayScenario scenario, bool? success) - { - scenario.Success = success; - - if(scenario is ICanBeginAndEndScenario) - ((ICanBeginAndEndScenario) scenario).End(success); - - foreach(var callback in builder.AfterScenario) - callback(scenario); - - scenario.Dispose(); - } - - /// - /// Executed after the last scenario in a test run. - /// - public void AfterExecutedLastScenario() - { - testRunEvents.NotifyCompleteTestRun(); - - foreach(var callback in builder.AfterLastScenario) - callback(RootContainer); - - RootContainer.Dispose(); - } - - /// - /// Gets the scenario factory. - /// - /// The scenario factory. - public IScenarioFactory GetScenarioFactory() - => new ScenarioFactory(RootContainer, builder.ServiceRegistrations.PerTestRun); - - #endregion - - #region private methods - - IContainer CreateRootContainer() - { - return Container - .CreateBuilder() - .DoNotMakeAllResolutionOptional() - .DoNotResolveUnregisteredTypes() - .SelfRegisterAResolver() - .DoNotSelfRegisterTheRegistry() - .SupportResolvingLazyInstances() - .DoNotSupportResolvingNamedInstanceDictionaries() - .ThrowOnCircularDependencies() - .UseInstanceCache() - .DoNotUseNonPublicConstructors() - .Build(); - } - - void AddRootContainerRegistrations(IReceivesRegistrations container) - { - container.AddRegistrations(builder.ServiceRegistrations.PerTestRun); - } - - #endregion - - #region constructor - - /// - /// Initializes a new instance of the class. - /// - /// Config builder. - /// The root DI container. - public ScreenplayIntegration(IIntegrationConfigBuilder configBuilder, - IContainer rootContainer = null) - { - if(configBuilder == null) - throw new ArgumentNullException(nameof(configBuilder)); - - builder = configBuilder; - this.rootContainer = new Lazy(() => { - var output = rootContainer ?? CreateRootContainer(); - AddRootContainerRegistrations(output); - return output; - }); - testRunEvents = new TestRunEvents(); - } - - #endregion - } -} diff --git a/CSF.Screenplay/Integration/ServiceRegistrations.cs b/CSF.Screenplay/Integration/ServiceRegistrations.cs deleted file mode 100644 index 2ab9c8a3..00000000 --- a/CSF.Screenplay/Integration/ServiceRegistrations.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.FlexDi.Builders; - -namespace CSF.Screenplay.Integration -{ - /// - /// Container class representing the registrations to be performed upon the container . - /// - public class ServiceRegistrations - { - readonly IList> perTestRun, perScenario; - - /// - /// Service resgirations which last for the complete Screenplay test run. These are registered upon the - /// 'root' container. - /// - /// The per-test-run service registrations. - public IList> PerTestRun => perScenario; - - /// - /// Service resgirations which only have a per-scenario lifetime (they are disposed and recreated - /// with each scenario). These are registered upon the child containers which are created per-scenario. - /// - /// The per-test-run service registrations. - public IList> PerScenario => perScenario; - - /// - /// Initializes a new instance of the class. - /// - public ServiceRegistrations() - { - perTestRun = new List>(); - perScenario = new List>(); - } - } -} diff --git a/CSF.Screenplay/Integration/TestRunEvents.cs b/CSF.Screenplay/Integration/TestRunEvents.cs deleted file mode 100644 index db482983..00000000 --- a/CSF.Screenplay/Integration/TestRunEvents.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Integration -{ - /// - /// Simple type which provides the test run events and notifies subscribers of the beginning/end of the run. - /// - class TestRunEvents : IProvidesTestRunEvents - { - public event EventHandler BeginTestRun; - - public event EventHandler CompleteTestRun; - - internal void NotifyBeginTestRun() - { - BeginTestRun?.Invoke(this, EventArgs.Empty); - } - - internal void NotifyCompleteTestRun() - { - CompleteTestRun?.Invoke(this, EventArgs.Empty); - } - } -} diff --git a/CSF.Screenplay/Performables/IAction.cs b/CSF.Screenplay/Performables/IAction.cs deleted file mode 100644 index b8c162af..00000000 --- a/CSF.Screenplay/Performables/IAction.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CSF.Screenplay.Performables -{ - /// - /// Base interface for an action which may be performed/ - /// - public interface IAction : IPerformable - { - } -} diff --git a/CSF.Screenplay/Performables/IAction`1.cs b/CSF.Screenplay/Performables/IAction`1.cs deleted file mode 100644 index 28a14759..00000000 --- a/CSF.Screenplay/Performables/IAction`1.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CSF.Screenplay.Performables -{ - /// - /// Represents an action which may be performed by an actor. This action returns a response value. - /// - public interface IAction : IPerformable - { - } -} diff --git a/CSF.Screenplay/Performables/IPerformable.cs b/CSF.Screenplay/Performables/IPerformable.cs deleted file mode 100644 index e363c189..00000000 --- a/CSF.Screenplay/Performables/IPerformable.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Performables -{ - /// - /// Represents a performable thing; a task, a question or an action. - /// - public interface IPerformable : IReportable - { - /// - /// Performs this operation, as the given actor. - /// - /// The actor performing this task. - void PerformAs(IPerformer actor); - } -} diff --git a/CSF.Screenplay/Performables/IPerformableWithResult.cs b/CSF.Screenplay/Performables/IPerformableWithResult.cs deleted file mode 100644 index a55de351..00000000 --- a/CSF.Screenplay/Performables/IPerformableWithResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Performables -{ - /// - /// Represents a performable thing; a task, a question or an action. - /// Items of this type return a response/result value. - /// - public interface IPerformableWithResult : IPerformable - { - /// - /// Performs this operation, as the given actor. - /// - /// The response or result. - /// The actor performing this task. - new object PerformAs(IPerformer actor); - } -} diff --git a/CSF.Screenplay/Performables/IPerformable`1.cs b/CSF.Screenplay/Performables/IPerformable`1.cs deleted file mode 100644 index 56607679..00000000 --- a/CSF.Screenplay/Performables/IPerformable`1.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Performables -{ - /// - /// Represents a performable thing; a task, a question or an action. - /// Items of this type return a response/result value. - /// - public interface IPerformable : IPerformableWithResult - { - /// - /// Performs this operation, as the given actor. - /// - /// The response or result. - /// The actor performing this task. - new TResult PerformAs(IPerformer actor); - } -} diff --git a/CSF.Screenplay/Performables/IQuestion`1.cs b/CSF.Screenplay/Performables/IQuestion`1.cs deleted file mode 100644 index 9a415fa2..00000000 --- a/CSF.Screenplay/Performables/IQuestion`1.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace CSF.Screenplay.Performables -{ - /// - /// A question, which has a specific (generic) answer type. - /// - /// - /// - /// Behind this facade, questions are essentially specialisations of performables, which always return an answer value. - /// Additionally, it is good practice to avoid changing the state of the application with questions. - /// - /// - /// Underneath this, questions work much like tasks - they make use of actions to interact with the application. - /// The only real difference is conceptual. - /// - /// - public interface IQuestion : IPerformable - { - } -} diff --git a/CSF.Screenplay/Performables/ITask.cs b/CSF.Screenplay/Performables/ITask.cs deleted file mode 100644 index 93d22f95..00000000 --- a/CSF.Screenplay/Performables/ITask.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; - -namespace CSF.Screenplay.Performables -{ - /// - /// Represents a task, which typically performs one or more actions (or uses sub-tasks) in order to alter the - /// state of the application. - /// - /// - /// - /// Tasks make use of the (actor) passed to them, in order to get actions. Actions - /// are then used to interact with the application and - typically - make changes to its state. - /// Additionally, tasks may make use of other tasks, using composition of low-level tasks in order to create - /// higher-level ones. - /// - /// - public interface ITask : IPerformable - { - } -} \ No newline at end of file diff --git a/CSF.Screenplay/Performables/ITask`1.cs b/CSF.Screenplay/Performables/ITask`1.cs deleted file mode 100644 index cf3e3e45..00000000 --- a/CSF.Screenplay/Performables/ITask`1.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; - -namespace CSF.Screenplay.Performables -{ - /// - /// Represents a task, which typically performs one or more actions (or uses sub-tasks) in order to alter the - /// state of the application. This implementation returns a result value upon completion of the task. - /// - /// - /// - /// Tasks make use of the (actor) passed to them, in order to get actions. Actions - /// are then used to interact with the application and - typically - make changes to its state. - /// Additionally, tasks may make use of other tasks, using composition of low-level tasks in order to create - /// higher-level ones. - /// - /// - public interface ITask : IPerformable - { - } -} diff --git a/CSF.Screenplay/Performables/Performable.cs b/CSF.Screenplay/Performables/Performable.cs deleted file mode 100644 index e52b17de..00000000 --- a/CSF.Screenplay/Performables/Performable.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Performables -{ - /// - /// Base class for performable types. - /// - public abstract class Performable : IPerformable - { - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. - protected virtual string GetReport(INamed actor) - { - return $"{actor.Name} performs {GetType().Name}."; - } - - /// - /// Performs this operation, as the given actor. - /// - /// The actor performing this task. - protected abstract void PerformAs(IPerformer actor); - - string IReportable.GetReport(INamed actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - return GetReport(actor); - } - - void IPerformable.PerformAs(IPerformer actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - PerformAs(actor); - } - } -} diff --git a/CSF.Screenplay/Performables/Performable`1.cs b/CSF.Screenplay/Performables/Performable`1.cs deleted file mode 100644 index 56a885b4..00000000 --- a/CSF.Screenplay/Performables/Performable`1.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Performables -{ - /// - /// Base class for performable types which return a result. - /// - public abstract class Performable : IPerformable - { - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. - protected virtual string GetReport(INamed actor) - { - return $"{actor.Name} performs {GetType().Name}."; - } - - /// - /// Performs this operation, as the given actor. - /// - /// The response or result. - /// The actor performing this task. - protected abstract TResult PerformAs(IPerformer actor); - - void IPerformable.PerformAs(IPerformer actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - PerformAs(actor); - } - - object IPerformableWithResult.PerformAs(IPerformer actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - return PerformAs(actor); - } - - TResult IPerformable.PerformAs(IPerformer actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - return PerformAs(actor); - } - - string IReportable.GetReport(INamed actor) - { - if(actor == null) - throw new ArgumentNullException(nameof(actor)); - - return GetReport(actor); - } - } -} diff --git a/CSF.Screenplay/Performables/Question.cs b/CSF.Screenplay/Performables/Question.cs deleted file mode 100644 index 470481a6..00000000 --- a/CSF.Screenplay/Performables/Question.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting; - -namespace CSF.Screenplay.Performables -{ - /// - /// Base type for implementations of . Note that this type may also be used as an - /// . - /// - /// - /// - /// This base type provides just one abstract method which must be overridden. - /// - /// - /// Implementors of questions are not required to derive from this base type. It is provided only as a convenience - /// where suitable. - /// - /// - /// Behind this facade, questions are essentially specialisations of tasks, which always return an answer value. - /// Additionally, it is good practice to avoid changing the state of the application with questions. - /// - /// - /// Underneath this, questions work much like tasks - they make use of actions to interact with the application. - /// The only real difference is conceptual. - /// - /// - public abstract class Question : Performable, IQuestion - { - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. - protected override string GetReport(INamed actor) - { - return $"{actor.Name} asks {GetType().Name}."; - } - } -} diff --git a/CSF.Screenplay/Properties/AssemblyInfo.cs b/CSF.Screenplay/Properties/AssemblyInfo.cs deleted file mode 100644 index 5e45c7c9..00000000 --- a/CSF.Screenplay/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.Screenplay")] -[assembly: AssemblyDescription("Screenplay core components")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("0.8.0.0")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.Screenplay/Reporting/DefaultObjectFormatter.cs b/CSF.Screenplay/Reporting/DefaultObjectFormatter.cs deleted file mode 100644 index b4355af6..00000000 --- a/CSF.Screenplay/Reporting/DefaultObjectFormatter.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting -{ - /// - /// A default object formatter which uses the object's .ToString() implementation. - /// - public class DefaultObjectFormatter : IObjectFormatter - { - /// - /// Gets a priority for formatting an object. This implementation will always return zero. - /// - /// The formatting priority. - /// Object. - public int GetFormattingPriority(object obj) => 0; - - /// - /// Gets a formatted name for the given input. - /// - /// Object. - public string GetFormattedName(object obj) => obj != null? obj.ToString() : ""; - } -} diff --git a/CSF.Screenplay/Reporting/GenericObjectFormatter.cs b/CSF.Screenplay/Reporting/GenericObjectFormatter.cs deleted file mode 100644 index 83fe5836..00000000 --- a/CSF.Screenplay/Reporting/GenericObjectFormatter.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting -{ - /// - /// Base class for implementations of . - /// - public abstract class GenericObjectFormatter : IObjectFormatter - { - /// - /// Gets a formatted name for the given input. - /// - /// Object. - protected abstract string GetFormattedName(T obj); - - /// - /// Gets a priority for formatting an object which matches the generic type of this class. - /// This should return a value greater than zero. - /// - /// The formatting priority. - /// Object. - protected virtual int GetFormattingPriority(T obj) => 1; - - /// - /// Gets a priority for formatting an object. A formatter which returns a higher priority will be used over one - /// which returns a lower priority. - /// - /// - /// - /// It is advised to return a negative priority (-1 is fine) if the formatter cannot format the given - /// object. Otherwise return a priority of 1 or higher depending upon how likely the formatter is to - /// provide a useful result. - /// - /// - /// Priority zero should be considered reserved for the . - /// - /// - /// The formatting priority. - /// Object. - public virtual int GetFormattingPriority(object obj) - { - if(ReferenceEquals(obj, null)) - return -1; - - var objectType = obj.GetType(); - - if(!typeof(T).IsAssignableFrom(objectType)) - return -2; - - return GetFormattingPriority((T) obj); - } - - string IObjectFormatter.GetFormattedName(object obj) => GetFormattedName((T) obj); - } -} diff --git a/CSF.Screenplay/Reporting/IObjectFormatter.cs b/CSF.Screenplay/Reporting/IObjectFormatter.cs deleted file mode 100644 index 38c6539b..00000000 --- a/CSF.Screenplay/Reporting/IObjectFormatter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting -{ - /// - /// Service which provides a formatted name for an object. - /// - public interface IObjectFormatter - { - /// - /// Gets a priority for formatting an object. A formatter which returns a higher priority will be used over one - /// which returns a lower priority. - /// - /// - /// - /// It is advised to return a negative priority (-1 is fine) if the formatter cannot format the given - /// object. Otherwise return a priority of 1 or higher depending upon how likely the formatter is to - /// provide a useful result. - /// - /// - /// Priority zero should be considered reserved for the . - /// - /// - /// The formatting priority. - /// Object. - int GetFormattingPriority(object obj); - - /// - /// Gets a formatted name for the given input. - /// - /// Object. - string GetFormattedName(object obj); - } -} diff --git a/CSF.Screenplay/Reporting/IReportable.cs b/CSF.Screenplay/Reporting/IReportable.cs deleted file mode 100644 index 60d0f949..00000000 --- a/CSF.Screenplay/Reporting/IReportable.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting -{ - /// - /// Indicates a type which can provide a human-readable report text indicating its nature. - /// - public interface IReportable - { - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. - string GetReport(INamed actor); - } -} diff --git a/CSF.Screenplay/Reporting/StringArrayFormatter.cs b/CSF.Screenplay/Reporting/StringArrayFormatter.cs deleted file mode 100644 index 7f1a6cd4..00000000 --- a/CSF.Screenplay/Reporting/StringArrayFormatter.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -namespace CSF.Screenplay.Reporting -{ - /// - /// Formatter for string arrays. - /// - public class StringArrayFormatter : GenericObjectFormatter - { - /// - /// Gets a formatted name for the given input. - /// - /// Object. - protected override string GetFormattedName(string[] obj) => String.Join(", ", obj); - } -} diff --git a/CSF.Screenplay/Scenarios/BeginScenarioEventArgs.cs b/CSF.Screenplay/Scenarios/BeginScenarioEventArgs.cs deleted file mode 100644 index 451c199c..00000000 --- a/CSF.Screenplay/Scenarios/BeginScenarioEventArgs.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// Begin-scenario event arguments. - /// - public class BeginScenarioEventArgs : EventArgs - { - /// - /// Gets or sets the scenario identity. - /// - /// The scenario identity. - public Guid ScenarioIdentity { get; set; } - - /// - /// Gets or sets the feature identifier. - /// - /// The feature identifier. - public IdAndName FeatureId { get; set; } - - /// - /// Gets or sets the scenario identifier. - /// - /// The scenario identifier. - public IdAndName ScenarioId { get; set; } - } -} diff --git a/CSF.Screenplay/Scenarios/ContainerExtensions.cs b/CSF.Screenplay/Scenarios/ContainerExtensions.cs deleted file mode 100644 index e9c0a57b..00000000 --- a/CSF.Screenplay/Scenarios/ContainerExtensions.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.FlexDi; -using CSF.FlexDi.Builders; - -namespace CSF.Screenplay.Scenarios -{ - /// - /// Extension methods for a container. - /// - public static class ContainerExtensions - { - /// - /// Adds a collection of registrations to the container. - /// - /// Container. - /// Registrations. - public static void AddRegistrations(this IReceivesRegistrations container, - IEnumerable> registrations) - { - if(container == null) - throw new ArgumentNullException(nameof(container)); - var registrationsToAdd = registrations?? Enumerable.Empty>(); - - container.AddRegistrations(helper => { - foreach(var registrationAction in registrationsToAdd) - registrationAction(helper); - }); - } - } -} diff --git a/CSF.Screenplay/Scenarios/EndScenarioEventArgs.cs b/CSF.Screenplay/Scenarios/EndScenarioEventArgs.cs deleted file mode 100644 index e542a235..00000000 --- a/CSF.Screenplay/Scenarios/EndScenarioEventArgs.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// End-scenario event arguments. - /// - public class EndScenarioEventArgs : EventArgs - { - /// - /// Gets or sets the scenario identity. - /// - /// The scenario identity. - public Guid ScenarioIdentity { get; set; } - - /// - /// Gets or sets the feature identifier. - /// - /// The feature identifier. - public IdAndName FeatureId { get; set; } - - /// - /// Gets or sets the scenario identifier. - /// - /// The scenario identifier. - public IdAndName ScenarioId { get; set; } - - /// - /// Gets or sets a value indicating whether the scenario was a success. - /// - /// true if the scenario was a success; otherwise, false. - public bool? ScenarioOutcome { get; set; } - } -} diff --git a/CSF.Screenplay/Scenarios/ICanBeginAndEndScenario.cs b/CSF.Screenplay/Scenarios/ICanBeginAndEndScenario.cs deleted file mode 100644 index e1f8a36d..00000000 --- a/CSF.Screenplay/Scenarios/ICanBeginAndEndScenario.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// A type which can begin and end a screenplay scenario. - /// - public interface ICanBeginAndEndScenario : IScreenplayScenario - { - /// - /// Marks the scenario as having begun (which may trigger event listeners). - /// - void Begin(); - - /// - /// Marks the scenario as having ended (which may trigger event listeners). - /// - void End(bool? success); - } -} diff --git a/CSF.Screenplay/Scenarios/IProvidesTestRunEvents.cs b/CSF.Screenplay/Scenarios/IProvidesTestRunEvents.cs deleted file mode 100644 index 75251f91..00000000 --- a/CSF.Screenplay/Scenarios/IProvidesTestRunEvents.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// Indicates that the current instance provides the events which indicate the beginning/end of a test run. - /// - public interface IProvidesTestRunEvents - { - /// - /// Occurs when a test run begins. - /// - event EventHandler BeginTestRun; - - /// - /// Occurs when a test run is completed. - /// - event EventHandler CompleteTestRun; - } -} diff --git a/CSF.Screenplay/Scenarios/IScenarioFactory.cs b/CSF.Screenplay/Scenarios/IScenarioFactory.cs deleted file mode 100644 index f3ea7283..00000000 --- a/CSF.Screenplay/Scenarios/IScenarioFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// Factory service which creates instances of . - /// - public interface IScenarioFactory - { - /// - /// Gets the scenario. - /// - /// The scenario. - /// Feature identifier. - /// Scenario identifier. - IScreenplayScenario GetScenario(IdAndName featureId, IdAndName scenarioId); - } -} diff --git a/CSF.Screenplay/Scenarios/IScenarioName.cs b/CSF.Screenplay/Scenarios/IScenarioName.cs deleted file mode 100644 index c1aeec1a..00000000 --- a/CSF.Screenplay/Scenarios/IScenarioName.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// A service which provides identification information about a Screenplay feature and scenario. - /// - public interface IScenarioName - { - /// - /// Gets a unique identity for the the current scenario instance. - /// - /// The scenario identity. - Guid Identity { get; } - - /// - /// Gets identifying information about the current feature under test. - /// - /// The feature identifier. - IdAndName FeatureId { get; } - - /// - /// Gets identifying information about the current scenario which is being tested. - /// - /// The scenario identifier. - IdAndName ScenarioId { get; } - } -} diff --git a/CSF.Screenplay/Scenarios/IdAndName.cs b/CSF.Screenplay/Scenarios/IdAndName.cs deleted file mode 100644 index bf008f26..00000000 --- a/CSF.Screenplay/Scenarios/IdAndName.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -namespace CSF.Screenplay.Scenarios -{ - /// - /// Represents an unique identifier and a corresponding human-readable name. - /// - public class IdAndName : IEquatable - { - /// - /// Gets the unique identifier. - /// - /// The identity. - public string Identity { get; private set; } - - /// - /// Gets the human-readable name. - /// - /// The name. - public string Name { get; private set; } - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current - /// ; otherwise, false. - public override bool Equals(object obj) - { - return Equals(obj as IdAndName); - } - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current - /// ; otherwise, false. - public bool Equals(IdAndName other) - { - if(ReferenceEquals(other, null)) - return false; - if(ReferenceEquals(other, this)) - return true; - - return other.Identity == Identity && other.Name == Name; - } - - /// - /// Serves as a hash function for a object. - /// - /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table. - public override int GetHashCode() - { - var nameHash = (Name != null)? Name.GetHashCode() : 0; - return Identity.GetHashCode() ^ nameHash; - } - - /// - /// Initializes a new instance of the class. - /// - /// Identity. - /// Name. - public IdAndName(string identity, string name = null) - { - if(identity == null) - throw new ArgumentNullException(nameof(identity)); - - Identity = identity; - Name = name; - } - } -} diff --git a/CSF.Screenplay/Scenarios/ScenarioFactory.cs b/CSF.Screenplay/Scenarios/ScenarioFactory.cs deleted file mode 100644 index 01e1e828..00000000 --- a/CSF.Screenplay/Scenarios/ScenarioFactory.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.FlexDi; -using CSF.FlexDi.Builders; - -namespace CSF.Screenplay.Scenarios -{ - /// - /// Concrete implementation of . - /// - public class ScenarioFactory : IScenarioFactory - { - readonly IContainer rootContainer; - readonly IEnumerable> perScenarioRegistrations; - - /// - /// Gets the scenario. - /// - /// The scenario. - /// Feature identifier. - /// Scenario identifier. - public IScreenplayScenario GetScenario(IdAndName featureId, IdAndName scenarioId) - { - var scenarioContainer = CreateScenarioContainer(); - return new ScreenplayScenario(featureId, scenarioId, scenarioContainer); - } - - IContainer CreateScenarioContainer() - { - var output = rootContainer.CreateChildContainer(); - output.AddRegistrations(perScenarioRegistrations); - return output; - } - - /// - /// Initializes a new instance of the class. - /// - public ScenarioFactory(IContainer rootContainer, - IEnumerable> perScenarioRegistrations) - { - if(rootContainer == null) - throw new ArgumentNullException(nameof(rootContainer)); - - this.perScenarioRegistrations = perScenarioRegistrations ?? Enumerable.Empty>(); - this.rootContainer = rootContainer; - } - } -} diff --git a/CSF.Screenplay/Scenarios/ScreenplayScenario.cs b/CSF.Screenplay/Scenarios/ScreenplayScenario.cs deleted file mode 100644 index 6b7a7deb..00000000 --- a/CSF.Screenplay/Scenarios/ScreenplayScenario.cs +++ /dev/null @@ -1,236 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Scenarios -{ - /// - /// Represents a single scenario within Screenplay-based test. - /// - public class ScreenplayScenario : IScreenplayScenario, IEquatable, ICanBeginAndEndScenario - { - #region fields - - readonly Guid identity; - readonly FlexDi.IContainer container; - - #endregion - - #region IScreenplayScenario implementation - - /// - /// Gets a value which indicates whether or not the scenario was a success. - /// - /// The success. - public bool? Success { get; set; } - - /// - /// Gets a MicroDi dependency resolver. - /// - /// The resolver. - public FlexDi.IResolvesServices Resolver => container; - - /// - /// Gets a unique identity for the the current scenario instance. - /// - /// The scenario identity. - public Guid Identity => identity; - - /// - /// Gets identifying information about the current feature under test. - /// - /// The feature identifier. - public IdAndName FeatureId { get; private set; } - - /// - /// Gets identifying information about the current scenario which is being tested. - /// - /// The scenario identifier. - public IdAndName ScenarioId { get; private set; } - - /// - /// Occurs when the scenario begins. - /// - public event EventHandler BeginScenario; - - /// - /// Occurs when the scenario ends. - /// - public event EventHandler EndScenario; - - /// - /// Creates a new actor with the given name. - /// - /// The actor. - /// Name. - public virtual IActor CreateActor(string name) => new Actor(name, Identity); - - #endregion - - #region ICanBeginAndEndScenario implementation - - /// - /// Notifies subscribers that the scenario has begun. - /// - public void Begin() - { - OnBeginScenario(); - } - - /// - /// Notifies subscribers that the scenario has ended. - /// - /// If set to true then the scenario is a success. - public void End(bool? outcome) - { - OnEndScenario(outcome); - } - - #endregion - - #region public API - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current - /// ; otherwise, false. - public bool Equals(ScreenplayScenario other) - { - if(ReferenceEquals(other, null)) - return false; - if(ReferenceEquals(other, this)) - return true; - - return identity == other.identity; - } - - /// - /// Determines whether the specified is equal to the current . - /// - /// The to compare with the current . - /// true if the specified is equal to the current - /// ; otherwise, false. - public override bool Equals(object obj) - { - return Equals(obj as ScreenplayScenario); - } - - /// - /// Serves as a hash function for a object. - /// - /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table. - public override int GetHashCode() - { - return identity.GetHashCode(); - } - - /// - /// Returns a that represents the current . - /// - /// A that represents the current . - public override string ToString() => $"[Screenplay scenario:{identity.ToString()}]"; - - #endregion - - #region event invokers - - /// - /// Event invoker for . - /// - protected virtual void OnBeginScenario() - { - var args = new BeginScenarioEventArgs { - FeatureId = FeatureId, - ScenarioId = ScenarioId, - ScenarioIdentity = Identity, - }; - BeginScenario?.Invoke(this, args); - } - - /// - /// Event invoker for . - /// - protected virtual void OnEndScenario(bool? outcome) - { - var args = new EndScenarioEventArgs { - FeatureId = FeatureId, - ScenarioId = ScenarioId, - ScenarioOutcome = outcome, - ScenarioIdentity = Identity, - }; - EndScenario?.Invoke(this, args); - } - - #endregion - - #region IDisposable Support - - bool disposedValue; - - /// - /// Disposes the current instance. - /// - /// If set to true disposing. - protected virtual void Dispose(bool disposing) - { - if(!disposedValue) - { - if(disposing) - { - container.Dispose(); - } - - disposedValue = true; - } - } - - /// - /// Releases all resource used by the object. - /// - /// Call when you are finished using the - /// . The method leaves the - /// in an unusable state. After calling - /// , you must release all references to the - /// so the garbage collector can reclaim the memory that - /// the was occupying. - public void Dispose() - { - Dispose(true); - } - - #endregion - - #region constructor - - /// - /// Initializes a new instance of the class. - /// - /// Feature identifier. - /// Scenario identifier. - /// A MicroDi container instance. - public ScreenplayScenario(IdAndName featureId, - IdAndName scenarioId, - FlexDi.IContainer container) - { - if(container == null) - throw new ArgumentNullException(nameof(container)); - if(featureId == null) - throw new ArgumentNullException(nameof(featureId)); - if(scenarioId == null) - throw new ArgumentNullException(nameof(scenarioId)); - - identity = Guid.NewGuid(); - - FeatureId = featureId; - ScenarioId = scenarioId; - this.container = container; - - this.container.AddRegistrations(h => { - h.RegisterInstance(this).As(); - }); - } - - #endregion - } -} diff --git a/CSF.Screenplay/StepComposer.cs b/CSF.Screenplay/StepComposer.cs deleted file mode 100644 index c41ef5ad..00000000 --- a/CSF.Screenplay/StepComposer.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay -{ - /// - /// A convenience type (for readability of tests) which helps 'phrase' the test method in a meaningful manner. - /// - /// - /// - /// It is recommended to use the functionality of this type via a using static CSF.Screenplay.StepComposer; - /// declaration at the top of your test steps source file. Typical usage looks like the following: - /// - /// - /// Given(joe).WasAbleTo(takeOutTheTrash); - /// - /// - /// The Given method does nothing more than down-cast the instance to an - /// , but whilst it performs little functional benefit, it makes the test more readable by - /// making it clear that this is a "given" (precondition) testing step. - /// - /// - public static class StepComposer - { - /// - /// Returns the actor instance, as an , in order to perform precondition actions. - /// - /// The actor. - public static IGivenActor Given(IActor actor) => actor; - - /// - /// Returns the actor instance, as an , in order to perform actions which exercise the - /// application. - /// - /// The actor. - public static IWhenActor When(IActor actor) => actor; - - /// - /// Returns the actor instance, as an , in order to perform actions which asserts that - /// the desired outcome has come about. - /// - /// The actor. - public static IThenActor Then(IActor actor) => actor; - } -} diff --git a/CSF.Screenplay/packages.config b/CSF.Screenplay/packages.config deleted file mode 100644 index aea13d1a..00000000 --- a/CSF.Screenplay/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/CSF.WebDriverFactory/CSF.WebDriverFactory.csproj b/CSF.WebDriverFactory/CSF.WebDriverFactory.csproj deleted file mode 100644 index 74945420..00000000 --- a/CSF.WebDriverFactory/CSF.WebDriverFactory.csproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - Debug - AnyCPU - {C99466AD-CA21-4C12-9E05-6730CDC3C031} - Library - CSF.WebDriverFactory - CSF.WebDriverFactory - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG;TRACE - prompt - 4 - bin\Debug\CSF.WebDriverFactory.xml - false - - - true - bin\Release - TRACE - prompt - 4 - bin\Release\CSF.WebDriverFactory.xml - false - - - - - ..\packages\Selenium.WebDriver.3.4.0\lib\net40\WebDriver.dll - - - - ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CSF.WebDriverFactory/CSF.WebDriverFactory.nuspec b/CSF.WebDriverFactory/CSF.WebDriverFactory.nuspec deleted file mode 100644 index 67f56cc4..00000000 --- a/CSF.WebDriverFactory/CSF.WebDriverFactory.nuspec +++ /dev/null @@ -1,22 +0,0 @@ - - - - CSF.WebDriverFactory - 0.8.0-alpha - CSF.WebDriverFactory - CSF Software Ltd - https://opensource.org/licenses/MIT - https://github.com/csf-dev/CSF.Screenplay - false - A configuration or environment-variable-based factory for Selenium WebDriver instances - Copyright 2017 - - - - - - - - - - \ No newline at end of file diff --git a/CSF.WebDriverFactory/Config/FactoryPropertyElementCollection.cs b/CSF.WebDriverFactory/Config/FactoryPropertyElementCollection.cs deleted file mode 100644 index d43db40d..00000000 --- a/CSF.WebDriverFactory/Config/FactoryPropertyElementCollection.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Configuration; - -namespace CSF.WebDriverFactory.Config -{ - /// - /// Represents a collection of within a configuration file. - /// - public class FactoryPropertyElementCollection : ConfigurationElementCollection - { - internal const string PropertyName = "Property"; - - /// - /// Gets the configuration collection type. - /// - /// The type of the collection. - public override ConfigurationElementCollectionType CollectionType - { - get - { - return ConfigurationElementCollectionType.BasicMapAlternate; - } - } - - /// - /// Gets the name of the element. - /// - /// The name of the element. - protected override string ElementName - { - get - { - return PropertyName; - } - } - - /// - /// Determines whether the given string matches the . - /// - /// true if the string matches the element name; otherwise, false. - /// Element name. - protected override bool IsElementName(string elementName) - { - return elementName.Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase); - } - - /// - /// Determines whether this instance is read only. - /// - /// true if this instance is read only; otherwise, false. - public override bool IsReadOnly() - { - return false; - } - - /// - /// Creates the new element. - /// - /// The new element. - protected override ConfigurationElement CreateNewElement() - { - return new FactoryProperty(); - } - - /// - /// Gets the element key. - /// - /// The element key. - /// Element. - protected override object GetElementKey(ConfigurationElement element) - { - return ((FactoryProperty)(element)).Name; - } - - /// - /// Gets the with the specified index. - /// - /// Index. - public FactoryProperty this[int idx] - { - get - { - return (FactoryProperty)BaseGet(idx); - } - } - } - - /// - /// A single factory property, exposing a name/value pair, indicating a public settable property on the factory - /// type and the value to be set into it. - /// - public class FactoryProperty : ConfigurationElement - { - const string NameConfigName = @"Name", ValueConfigName = @"Value"; - - /// - /// Gets or sets the name. - /// - /// The name. - [ConfigurationProperty(NameConfigName, IsRequired = true)] - public virtual string Name - { - get { return (string) this[NameConfigName]; } - set { this[NameConfigName] = value; } - } - - /// - /// Gets or sets the value. - /// - /// The value. - [ConfigurationProperty(ValueConfigName, IsRequired = true)] - public virtual string Value - { - get { return (string) this[ValueConfigName]; } - set { this[ValueConfigName] = value; } - } - } -} diff --git a/CSF.WebDriverFactory/Config/IWebDriverFactoryConfiguration.cs b/CSF.WebDriverFactory/Config/IWebDriverFactoryConfiguration.cs deleted file mode 100644 index 5c2a3c12..00000000 --- a/CSF.WebDriverFactory/Config/IWebDriverFactoryConfiguration.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace CSF.WebDriverFactory.Config -{ - /// - /// Represents configuration information which will enable calling code to get a . - /// - public interface IWebDriverFactoryConfiguration - { - /// - /// Gets the System.Type of web driver factory desired. - /// - /// The factory type. - Type GetFactoryType(); - - /// - /// Gets a collection of name/value pairs which indicate public settable properties on the factory instance - /// and values to set into them. - /// - /// The factory properties. - IDictionary GetFactoryProperties(); - } -} diff --git a/CSF.WebDriverFactory/Config/WebDriverConfigurationSection.cs b/CSF.WebDriverFactory/Config/WebDriverConfigurationSection.cs deleted file mode 100644 index 3297a084..00000000 --- a/CSF.WebDriverFactory/Config/WebDriverConfigurationSection.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; -using CSF.Configuration; - -namespace CSF.WebDriverFactory.Config -{ - /// - /// Implementation of which makes use of a ConfigurationSection - /// to store the information. - /// - [ConfigurationPath("WebDriverFactory")] - public class WebDriverConfigurationSection : ConfigurationSection, IWebDriverFactoryConfiguration - { - const string - FactoryTypeConfigName = @"FactoryType", - FactoryPropertiesConfigName = @"FactoryProperties"; - - /// - /// Gets or sets the assembly-qualified type name of the factory implementation to use. - /// - /// The factory type. - [ConfigurationProperty(FactoryTypeConfigName, IsRequired = true)] - public virtual string FactoryType - { - get { return (string) this[FactoryTypeConfigName]; } - set { this[FactoryTypeConfigName] = value; } - } - - /// - /// Gets or sets a collection of the instances which should be applied to the - /// factory. - /// - /// The factory properties. - [ConfigurationProperty(FactoryPropertiesConfigName, IsRequired = false)] - public virtual FactoryPropertyElementCollection FactoryProperties - { - get { return (FactoryPropertyElementCollection) this[FactoryPropertiesConfigName]; } - set { this[FactoryPropertiesConfigName] = value; } - } - - /// - /// Gets the System.Type of web driver factory desired. - /// - /// The factory type. - public Type GetFactoryType() - { - if(FactoryType == null) - return null; - - return Type.GetType(FactoryType); - } - - /// - /// Gets a collection of name/value pairs which indicate public settable properties on the factory instance - /// and values to set into them. - /// - /// The factory properties. - public IDictionary GetFactoryProperties() - { - if(FactoryProperties == null) - return new Dictionary(); - - return FactoryProperties - .Cast() - .ToDictionary(k => k.Name, v => v.Value); - } - } -} diff --git a/CSF.WebDriverFactory/ConfigurationWebDriverFactoryProvider.cs b/CSF.WebDriverFactory/ConfigurationWebDriverFactoryProvider.cs deleted file mode 100644 index 1aaf7c2d..00000000 --- a/CSF.WebDriverFactory/ConfigurationWebDriverFactoryProvider.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Reflection; -using CSF.Configuration; -using CSF.WebDriverFactory.Config; - -namespace CSF.WebDriverFactory -{ - /// - /// Implementation of which reads information from a configuration source - /// and creates a web driver factory according to the information within. - /// - public class ConfigurationWebDriverFactoryProvider : IWebDriverFactoryProvider - { - const BindingFlags - PropertySettingBindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase; - static readonly Type BaseFactoryType = typeof(IWebDriverFactory); - - readonly IWebDriverFactoryConfiguration injectedConfig; - - /// - /// Gets the web driver factory instance, using the configuration data. - /// - /// The factory. - public virtual IWebDriverFactory GetFactory() - { - var config = GetConfiguration(); - var factory = GetFactory(config); - ConfigureFactory(factory, config); - return factory; - } - - /// - /// Gets the configuration information. - /// - /// The configuration. - protected virtual IWebDriverFactoryConfiguration GetConfiguration() - { - if(injectedConfig != null) - return injectedConfig; - - var reader = new ConfigurationReader(); - var config = reader.ReadSection(); - - if(config == null) - throw new InvalidOperationException("The configuration must not be null; please check your configuration file."); - - return config; - } - - /// - /// Creates and returns the web driver factory instance. - /// - /// The factory. - /// Configuration. - protected virtual IWebDriverFactory GetFactory(IWebDriverFactoryConfiguration config) - { - if(config == null) - throw new ArgumentNullException(nameof(config)); - - var factoryType = config.GetFactoryType(); - if(factoryType == null) - throw new ArgumentException($"The configuration must return a non-null factory type; check that the configured type exists.", - nameof(config)); - if(!BaseFactoryType.IsAssignableFrom(factoryType)) - throw new ArgumentException($"A factory type must implement `{BaseFactoryType.Name}', but `{factoryType.FullName}' does not.", - nameof(config)); - - return (IWebDriverFactory) Activator.CreateInstance(factoryType); - } - - /// - /// Configures the factory by setting property values according to information from the configuration. - /// - /// Factory. - /// Config. - protected virtual void ConfigureFactory(IWebDriverFactory factory, IWebDriverFactoryConfiguration config) - { - if(factory == null) - throw new ArgumentNullException(nameof(factory)); - if(config == null) - throw new ArgumentNullException(nameof(config)); - - var factoryType = factory.GetType(); - var propertiesToSet = config.GetFactoryProperties(); - - foreach(var propertyName in propertiesToSet.Keys) - { - var propertyValue = propertiesToSet[propertyName]; - SetFactoryPropertyValue(factoryType, factory, propertyName, propertyValue); - } - } - - /// - /// Sets a single property value on the given factory instance. - /// - /// Type. - /// Instance. - /// Property name. - /// Property value. - protected virtual void SetFactoryPropertyValue(Type type, object instance, string propertyName, string propertyValue) - { - var property = type.GetProperty(propertyName, PropertySettingBindingFlags); - if(property == null) - throw new ArgumentException($"There must be a public instance property on `{type.FullName}' named '{propertyName}'.", - propertyName); - - if(!property.CanWrite) - throw new ArgumentException($"The property {type.Name}.{property.Name} must be settable.", nameof(propertyName)); - - var convertedValue = Convert.ChangeType(propertyValue, property.PropertyType); - property.SetValue(instance, convertedValue); - } - - /// - /// Initializes a new instance of the class. - /// - public ConfigurationWebDriverFactoryProvider() : this(null) {} - - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// Generally, callers do not need to use this overload of the constructor, as the default behaviour is to read the - /// configuration information from the XML configuration. - /// - /// - /// Only use this constructor if you need to inject the configuration from an alternative source. - /// - /// - /// An instance of to inject into the factory. - public ConfigurationWebDriverFactoryProvider(IWebDriverFactoryConfiguration injectedConfig) - { - this.injectedConfig = injectedConfig; - } - } -} diff --git a/CSF.WebDriverFactory/IMarksWebDriverWithOutcome.cs b/CSF.WebDriverFactory/IMarksWebDriverWithOutcome.cs deleted file mode 100644 index 6e1f433f..00000000 --- a/CSF.WebDriverFactory/IMarksWebDriverWithOutcome.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using OpenQA.Selenium; - -namespace CSF.WebDriverFactory -{ - /// - /// Indicates a type which is capable of marking a web driver with outcome-related information. - /// - public interface IMarksWebDriverWithOutcome - { - /// - /// Marks the web driver as having passed the current test scenario. - /// - /// Driver. - void MarkAsSuccess(IWebDriver driver); - - /// - /// Marks the web driver as having failed the current test scenario. - /// - /// Driver. - void MarkAsFailure(IWebDriver driver); - } -} diff --git a/CSF.WebDriverFactory/IWebDriverFactory.cs b/CSF.WebDriverFactory/IWebDriverFactory.cs deleted file mode 100644 index 66159c9f..00000000 --- a/CSF.WebDriverFactory/IWebDriverFactory.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using OpenQA.Selenium; - -namespace CSF.WebDriverFactory -{ - /// - /// The main interface all factory implementations must implement. Provides the functionality to get a fully-configured - /// web driver. - /// - public interface IWebDriverFactory - { - /// - /// Gets the name of the web browser that this factory will create. - /// - /// The browser name. - string GetBrowserName(); - - /// - /// Gets the version of the web browser that this factory will create. - /// - /// The browser version. - string GetBrowserVersion(); - - /// - /// Gets the web driver. - /// - /// The web driver. - IWebDriver GetWebDriver(); - - /// - /// Gets the web driver. - /// - /// The web driver. - IWebDriver GetWebDriver(IDictionary capabilities); - } -} diff --git a/CSF.WebDriverFactory/IWebDriverFactoryProvider.cs b/CSF.WebDriverFactory/IWebDriverFactoryProvider.cs deleted file mode 100644 index 88f0466a..00000000 --- a/CSF.WebDriverFactory/IWebDriverFactoryProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -namespace CSF.WebDriverFactory -{ - /// - /// Provides an entry point to this API, creating and returning an instance of . - /// - public interface IWebDriverFactoryProvider - { - /// - /// Gets the web driver factory. - /// - /// The factory. - IWebDriverFactory GetFactory(); - } -} diff --git a/CSF.WebDriverFactory/Impl/ChromeWebDriverFactory.cs b/CSF.WebDriverFactory/Impl/ChromeWebDriverFactory.cs deleted file mode 100644 index 405e0e67..00000000 --- a/CSF.WebDriverFactory/Impl/ChromeWebDriverFactory.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Collections.Generic; -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; - -namespace CSF.WebDriverFactory.Impl -{ - /// - /// Implementation of which gets a Google Chrome web driver. - /// - public class ChromeWebDriverFactory : IWebDriverFactory - { - /// - /// Gets or sets the timeout (in seconds) between issuing a command to the web driver and receiving a response. - /// - /// The command timeout seconds. - public int CommandTimeoutSeconds { get; set; } - - /// - /// Gets or sets the TCP port on which the web driver process will listen. - /// - /// The chrome driver port. - public int? DriverPort { get; set; } - - /// - /// Gets or sets the filesystem path to the web-driver executable (chromedriver). - /// - /// The chrome driver path. - public string DriverPath { get; set; } - - /// - /// Gets or sets the filesystem path to the Google Chrome web browser executable. - /// - /// The chrome executable path. - public string BrowserExecutablePath { get; set; } - - /// - /// Gets the name of the web browser that this factory will create. - /// - /// The browser name. - public string GetBrowserName() => "Chrome"; - - /// - /// Gets the version of the web browser that this factory will create. - /// - /// The browser version. - public string GetBrowserVersion() => null; - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver() - { - return GetWebDriver(null); - } - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver(IDictionary capabilities) - { - var driverService = GetDriverService(); - var options = GetChromeOptions(); - - if(capabilities != null) - { - foreach(var cap in capabilities) - { - options.AddAdditionalCapability(cap.Key, cap.Value); - } - } - - var timeout = GetTimeout(); - return new ChromeDriver(driverService, options, timeout); - } - - TimeSpan GetTimeout() - { - return TimeSpan.FromSeconds(CommandTimeoutSeconds); - } - - ChromeDriverService GetDriverService() - { - ChromeDriverService output; - - if(String.IsNullOrEmpty(DriverPath)) - output = ChromeDriverService.CreateDefaultService(); - else - output = ChromeDriverService.CreateDefaultService(DriverPath); - - output.HideCommandPromptWindow = true; - output.SuppressInitialDiagnosticInformation = true; - - if(DriverPort.HasValue) - output.Port = DriverPort.Value; - - return output; - } - - ChromeOptions GetChromeOptions() - { - var output = new ChromeOptions(); - - if(!String.IsNullOrEmpty(BrowserExecutablePath)) - output.BinaryLocation = BrowserExecutablePath; - - return output; - } - - /// - /// Initializes a new instance of the class. - /// - public ChromeWebDriverFactory() - { - CommandTimeoutSeconds = 60; - } - } -} diff --git a/CSF.WebDriverFactory/Impl/FirefoxGeckoDriverWebDriverFactory.cs b/CSF.WebDriverFactory/Impl/FirefoxGeckoDriverWebDriverFactory.cs deleted file mode 100644 index 5af80fde..00000000 --- a/CSF.WebDriverFactory/Impl/FirefoxGeckoDriverWebDriverFactory.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; -using OpenQA.Selenium; -using OpenQA.Selenium.Firefox; - -namespace CSF.WebDriverFactory.Impl -{ - /// - /// Implementation of which is suitable for Firefox versions 47+, using the - /// geckodriver executable. - /// - public class FirefoxGeckoDriverWebDriverFactory : IWebDriverFactory - { - /// - /// Gets or sets the timeout (in seconds) between issuing a command to the web driver and receiving a response. - /// - /// The command timeout seconds. - public int CommandTimeoutSeconds { get; set; } - - /// - /// Gets or sets the TCP port on which the web driver process will listen. - /// - /// The gecko driver port. - public int? DriverPort { get; set; } - - /// - /// Gets or sets the filesystem path to the web-driver executable (chromedriver). - /// - /// The gecko driver path. - public string DriverPath { get; set; } - - /// - /// Gets or sets the filesystem path to the Mozilla Firefox web browser executable. - /// - /// The firefox executable path. - public string BrowserExecutablePath { get; set; } - - /// - /// Gets the name of the web browser that this factory will create. - /// - /// The browser name. - public string GetBrowserName() => "Firefox"; - - /// - /// Gets the version of the web browser that this factory will create. - /// - /// The browser version. - public string GetBrowserVersion() => null; - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver() - { - return GetWebDriver(null); - } - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver(IDictionary capabilities) - { - var driverService = GetDriverService(); - var options = GetFirefoxOptions(); - - if(capabilities != null) - { - foreach(var cap in capabilities) - { - options.AddAdditionalCapability(cap.Key, cap.Value); - } - } - - var timeout = GetTimeout(); - return new FirefoxDriver(driverService, options, timeout); - } - - TimeSpan GetTimeout() - { - return TimeSpan.FromSeconds(CommandTimeoutSeconds); - } - - FirefoxDriverService GetDriverService() - { - FirefoxDriverService output; - - if(String.IsNullOrEmpty(DriverPath)) - output = FirefoxDriverService.CreateDefaultService(); - else - output = FirefoxDriverService.CreateDefaultService(DriverPath); - - output.HideCommandPromptWindow = true; - output.SuppressInitialDiagnosticInformation = true; - - if(DriverPort.HasValue) - output.Port = DriverPort.Value; - - if(!String.IsNullOrEmpty(BrowserExecutablePath)) - output.FirefoxBinaryPath = BrowserExecutablePath; - - return output; - } - - FirefoxOptions GetFirefoxOptions() - { - var output = new FirefoxOptions(); - - if(!String.IsNullOrEmpty(BrowserExecutablePath)) - output.BrowserExecutableLocation = BrowserExecutablePath; - - return output; - } - } -} diff --git a/CSF.WebDriverFactory/Impl/InternetExplorerWebDriverFactory.cs b/CSF.WebDriverFactory/Impl/InternetExplorerWebDriverFactory.cs deleted file mode 100644 index b5a71281..00000000 --- a/CSF.WebDriverFactory/Impl/InternetExplorerWebDriverFactory.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; -using OpenQA.Selenium; -using OpenQA.Selenium.IE; - -namespace CSF.WebDriverFactory.Impl -{ - /// - /// Implementation of which gets an Internet Explorer web driver. - /// - public class InternetExplorerWebDriverFactory : IWebDriverFactory - { - /// - /// Gets or sets the timeout (in seconds) between issuing a command to the web driver and receiving a response. - /// - /// The command timeout seconds. - public int CommandTimeoutSeconds { get; set; } - - /// - /// Gets or sets the TCP port on which the web driver process will listen. - /// - /// The IE driver port. - public int? DriverPort { get; set; } - - /// - /// Gets or sets the filesystem path to the web-driver executable (chromedriver). - /// - /// The IE driver path. - public string DriverPath { get; set; } - - /// - /// Gets the name of the web browser that this factory will create. - /// - /// The browser name. - public string GetBrowserName() => "Internet explorer"; - - /// - /// Gets the version of the web browser that this factory will create. - /// - /// The browser version. - public string GetBrowserVersion() => null; - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver() - { - return GetWebDriver(null); - } - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver(IDictionary capabilities) - { - var driverService = GetDriverService(); - var options = GetIEOptions(); - - if(capabilities != null) - { - foreach(var cap in capabilities) - { - options.AddAdditionalCapability(cap.Key, cap.Value); - } - } - - var timeout = GetTimeout(); - return new InternetExplorerDriver(driverService, options, timeout); - } - - TimeSpan GetTimeout() - { - return TimeSpan.FromSeconds(CommandTimeoutSeconds); - } - - InternetExplorerDriverService GetDriverService() - { - InternetExplorerDriverService output; - - if(String.IsNullOrEmpty(DriverPath)) - output = InternetExplorerDriverService.CreateDefaultService(); - else - output = InternetExplorerDriverService.CreateDefaultService(DriverPath); - - output.HideCommandPromptWindow = true; - output.SuppressInitialDiagnosticInformation = true; - - if(DriverPort.HasValue) - output.Port = DriverPort.Value; - - return output; - } - - InternetExplorerOptions GetIEOptions() - { - var output = new InternetExplorerOptions(); - - return output; - } - } -} diff --git a/CSF.WebDriverFactory/Impl/RemoteWebDriverFactory.cs b/CSF.WebDriverFactory/Impl/RemoteWebDriverFactory.cs deleted file mode 100644 index ddceb75f..00000000 --- a/CSF.WebDriverFactory/Impl/RemoteWebDriverFactory.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using OpenQA.Selenium; -using OpenQA.Selenium.Remote; - -namespace CSF.WebDriverFactory.Impl -{ - /// - /// Implementation of which gets a web driver for a remote web browser. - /// - public class RemoteWebDriverFactory : IWebDriverFactory - { - /// - /// Gets or sets the desired browser name. - /// - /// The name of the browser. - public string BrowserName { get; set; } - - /// - /// Gets or sets the desired browser version. - /// - /// The browser version. - public string BrowserVersion { get; set; } - - /// - /// Gets or sets the desired platform. - /// - /// The platform. - public string Platform { get; set; } - - /// - /// Gets or sets the endpoint address for the remote web browser driver. - /// - /// The remote address. - public string RemoteAddress { get; set; } - - /// - /// Gets or sets the timeout (in seconds) between issuing a command to the web driver and receiving a response. - /// - /// The command timeout seconds. - public int CommandTimeoutSeconds { get; set; } - - /// - /// Gets the name of the web browser that this factory will create. - /// - /// The browser name. - public virtual string GetBrowserName() => BrowserName; - - /// - /// Gets the version of the web browser that this factory will create. - /// - /// The browser version. - public virtual string GetBrowserVersion() => BrowserVersion; - - /// - /// Gets the web driver. - /// - /// The web driver. - public virtual IWebDriver GetWebDriver() - { - return GetWebDriver(null); - } - - /// - /// Gets the web driver. - /// - /// The web driver. - public IWebDriver GetWebDriver(IDictionary capabilities) - { - var baseCapabilities = GetCapabilities(); - var uri = GetRemoteUri(); - - if(capabilities != null) - { - foreach(var cap in capabilities) - { - baseCapabilities.SetCapability(cap.Key, cap.Value); - } - } - - var timeout = GetTimeout(); - return new RemoteWebDriver(uri, baseCapabilities, timeout); - } - - /// - /// Gets a set of ICapabilities from the current state of this instance. - /// - /// The capabilities. - protected virtual DesiredCapabilities GetCapabilities() - { - var caps = new DesiredCapabilities(); - ConfigureCapabilities(caps); - return caps; - } - - /// - /// Configures the capabilities desired for the current instance. - /// - /// Caps. - protected virtual void ConfigureCapabilities(DesiredCapabilities caps) - { - caps.SetCapability(CapabilityType.BrowserName, BrowserName); - - SetCapabilityIfNotNull(caps, CapabilityType.Version, BrowserVersion); - SetCapabilityIfNotNull(caps, CapabilityType.Platform, Platform); - } - - /// - /// Gets the timeout. - /// - /// The timeout. - protected virtual TimeSpan GetTimeout() - { - return TimeSpan.FromSeconds(CommandTimeoutSeconds); - } - - /// - /// Sets a desired capability key/value pair into the given capabilities instance, but only if the capability - /// value is not null. - /// - /// The capabilities instance to modify. - /// The capability name. - /// The capability value. - protected virtual void SetCapabilityIfNotNull(DesiredCapabilities caps, string name, string value) - { - if(value == null) - return; - - caps.SetCapability(name, value); - } - - /// - /// Gets the URI to the remote web driver. - /// - /// The remote URI. - protected virtual Uri GetRemoteUri() - { - return new Uri(RemoteAddress); - } - - /// - /// Initializes a new instance of the class. - /// - public RemoteWebDriverFactory() - { - BrowserName = "Chrome"; - RemoteAddress = "http://127.0.0.1:4444/wd/hub"; - CommandTimeoutSeconds = 60; - } - } -} diff --git a/CSF.WebDriverFactory/Impl/RemoteWebDriverFromEnvironmentFactory.cs b/CSF.WebDriverFactory/Impl/RemoteWebDriverFromEnvironmentFactory.cs deleted file mode 100644 index 31202755..00000000 --- a/CSF.WebDriverFactory/Impl/RemoteWebDriverFromEnvironmentFactory.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using OpenQA.Selenium; -using OpenQA.Selenium.Remote; - -namespace CSF.WebDriverFactory.Impl -{ - /// - /// Implementation of which gets a web driver for a remote web browser, but also - /// is capable of configuring that remote web driver instance via environment variables. - /// - /// - /// - /// This factory type is intended for usage with CI build systems, in which they may perform multiple builds, - /// with differing environment variables between each build. This may be used with this factory to trigger different - /// builds to use different web browsers (for example). - /// - /// - public class RemoteWebDriverFromEnvironmentFactory : RemoteWebDriverFactory - { - /// - /// Gets or sets the name of the environment variable used to override the configured browser. - /// - /// The browser name variable. - public string BrowserNameVar { get; set; } - - /// - /// Gets or sets the name of the environment variable used to override the configured browser version. - /// - /// The browser version variable. - public string BrowserVersionVar { get; set; } - - /// - /// Gets or sets the name of the environment variable used to override the configured platform. - /// - /// The platform variable. - public string PlatformVar { get; set; } - - /// - /// Gets or sets the name of the environment variable used to override the configured remote web driver address. - /// - /// The remote address variable. - public string RemoteAddressVar { get; set; } - - /// - /// Gets or sets the name of the environment variable used to override the configured command timeout. - /// - /// The command timeout seconds variable. - public string CommandTimeoutSecondsVar { get; set; } - - /// - /// Gets the name of the web browser that this factory will create. - /// - /// The browser name. - public override string GetBrowserName() => GetFromEnvironmentOrSetting(BrowserNameVar, BrowserName); - - /// - /// Gets the version of the web browser that this factory will create. - /// - /// The browser version. - public override string GetBrowserVersion() => GetFromEnvironmentOrSetting(BrowserVersionVar, BrowserVersion); - - /// - /// Gets the resolved platform name. - /// - /// The resolved platform. - public virtual string GetPlatform() - { - return GetFromEnvironmentOrSetting(PlatformVar, Platform); - } - - /// - /// Gets the URI to the remote web driver. - /// - /// The remote URI. - protected override Uri GetRemoteUri() - { - if(String.IsNullOrEmpty(RemoteAddressVar)) - { - return base.GetRemoteUri(); - } - - var uri = GetEnv(RemoteAddressVar); - return new Uri(uri); - } - - /// - /// Gets the timeout. - /// - /// The timeout. - protected override TimeSpan GetTimeout() - { - if(String.IsNullOrEmpty(CommandTimeoutSecondsVar)) - { - return base.GetTimeout(); - } - - int seconds; - var val = GetEnv(CommandTimeoutSecondsVar); - if(Int32.TryParse(val, out seconds)) - { - return TimeSpan.FromSeconds(seconds); - } - - return base.GetTimeout(); - } - - /// - /// Configures the capabilities desired for the current instance. - /// - /// Caps. - protected override void ConfigureCapabilities(DesiredCapabilities caps) - { - SetCapabilityToEnvOrSetting(caps, CapabilityType.BrowserName, BrowserNameVar, BrowserName); - SetCapabilityToEnvOrSetting(caps, CapabilityType.Version, BrowserVersionVar, BrowserVersion); - SetCapabilityToEnvOrSetting(caps, CapabilityType.Platform, PlatformVar, Platform); - } - - /// - /// Sets the value of a single capability into a capabilities instance, using either the given environment - /// variable name (if provided) or the functionality from - /// if not. - /// - /// The capabilities instance to modify. - /// The capability name. - /// The capability value. - /// The name of an environment variable from which to get a value. - protected virtual void SetCapabilityToEnvOrSetting(DesiredCapabilities caps, string name, string envName, string value) - { - var resolvedValue = GetFromEnvironmentOrSetting(envName, value); - base.SetCapabilityIfNotNull(caps, name, resolvedValue); - } - - /// - /// Gets a value from either the environment variable or a provided setting. - /// - /// The resolved value. - /// Environment variable name. - /// The provided setting. - protected virtual string GetFromEnvironmentOrSetting(string envName, string value) - { - if(String.IsNullOrEmpty(envName)) - return value; - - return GetEnv(envName); - } - - string GetEnv(string name) - { - return Environment.GetEnvironmentVariable(name); - } - } -} diff --git a/CSF.WebDriverFactory/Impl/SauceConnectWebDriverFactory.cs b/CSF.WebDriverFactory/Impl/SauceConnectWebDriverFactory.cs deleted file mode 100644 index bd26acda..00000000 --- a/CSF.WebDriverFactory/Impl/SauceConnectWebDriverFactory.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using OpenQA.Selenium; - -namespace CSF.WebDriverFactory.Impl -{ - /// - /// Web driver factory base type designed for integration with Sauce Connect by Sauce Labs: - /// https://saucelabs.com/ - /// - public abstract class SauceConnectWebDriverFactory : RemoteWebDriverFromEnvironmentFactory, IMarksWebDriverWithOutcome - { - const string - TunnelIdCapability = "tunnel-identifier", - UsernameCapability = "username", - ApiKeyCapability = "accessKey", - TestNameCapabilityName = "name", - BuildNameCapability = "build", - PassedScriptTemplate = "sauce:job-result={0}"; - - /// - /// Gets the name of the capability which provides the test name. - /// - /// The test name capability. - public static string TestNameCapability => TestNameCapabilityName; - - /// - /// Configures the capabilities desired for the current instance. - /// - /// Caps. - protected override void ConfigureCapabilities(OpenQA.Selenium.Remote.DesiredCapabilities caps) - { - base.ConfigureCapabilities(caps); - ConfigureSauceConnectCapabilities(caps); - } - - /// - /// Configures capabilities specific to Sauce Connect. - /// - /// Caps. - protected virtual void ConfigureSauceConnectCapabilities(OpenQA.Selenium.Remote.DesiredCapabilities caps) - { - caps.SetCapability(TunnelIdCapability, GetSauceTunnelId()); - caps.SetCapability(UsernameCapability, GetSauceUsername()); - caps.SetCapability(ApiKeyCapability, GetSauceAccessKey()); - caps.SetCapability(BuildNameCapability, GetSauceBuildName()); - } - - /// - /// Gets the tunnel identifier. - /// - /// The tunnel identifier. - protected abstract string GetSauceTunnelId(); - - /// - /// Gets the Sauce Connect username. - /// - /// The sauce username. - protected abstract string GetSauceUsername(); - - /// - /// Gets the Sauce Connect access key. - /// - /// The sauce access key. - protected abstract string GetSauceAccessKey(); - - /// - /// Gets the Sauce Labs 'build name' (a name for the current test run). - /// - /// The sauce build name. - protected abstract string GetSauceBuildName(); - - /// - /// Marks the web driver as having passed the current test scenario. - /// - /// Driver. - public void MarkAsSuccess(IWebDriver driver) - { - MarkWithOutcome(driver, true); - } - - /// - /// Marks the web driver as having failed the current test scenario. - /// - /// Driver. - public void MarkAsFailure(IWebDriver driver) - { - MarkWithOutcome(driver, false); - } - - void MarkWithOutcome(IWebDriver driver, bool passed) - { - if(driver == null) - throw new ArgumentNullException(nameof(driver)); - - var javascriptExecutor = driver as IJavaScriptExecutor; - if(javascriptExecutor == null) - return; - - var outcome = passed.ToString().ToLowerInvariant(); - javascriptExecutor.ExecuteScript(String.Format(PassedScriptTemplate, outcome)); - } - } -} diff --git a/CSF.WebDriverFactory/Properties/AssemblyInfo.cs b/CSF.WebDriverFactory/Properties/AssemblyInfo.cs deleted file mode 100644 index a1f6d0be..00000000 --- a/CSF.WebDriverFactory/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("CSF.WebDriverFactory")] -[assembly: AssemblyDescription("Selenium WebDriver factory")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CSF Software Limited")] -[assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Craig Fowler")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("0.8.0.0")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/CSF.WebDriverFactory/WebDriverFactoryExtensions.cs b/CSF.WebDriverFactory/WebDriverFactoryExtensions.cs deleted file mode 100644 index 4d391d00..00000000 --- a/CSF.WebDriverFactory/WebDriverFactoryExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using OpenQA.Selenium; - -namespace CSF.WebDriverFactory -{ - /// - /// Extension methods to web driver factory types. - /// - public static class WebDriverFactoryExtensions - { - /// - /// Marks the web driver as having passed the current test. - /// - /// Factory. - /// Driver. - public static void MarkTestAsPassed(this IWebDriverFactory factory, IWebDriver driver) - { - if(factory == null) - throw new ArgumentNullException(nameof(factory)); - if(driver == null) - throw new ArgumentNullException(nameof(driver)); - - var outcomeFactory = factory as IMarksWebDriverWithOutcome; - if(outcomeFactory == null) - return; - - outcomeFactory.MarkAsSuccess(driver); - } - - /// - /// Marks the web driver as having failed the current test. - /// - /// Factory. - /// Driver. - public static void MarkTestAsFailed(this IWebDriverFactory factory, IWebDriver driver) - { - if(factory == null) - throw new ArgumentNullException(nameof(factory)); - if(driver == null) - throw new ArgumentNullException(nameof(driver)); - - var outcomeFactory = factory as IMarksWebDriverWithOutcome; - if(outcomeFactory == null) - return; - - outcomeFactory.MarkAsFailure(driver); - } - } -} diff --git a/CSF.WebDriverFactory/packages.config b/CSF.WebDriverFactory/packages.config deleted file mode 100644 index 19871e96..00000000 --- a/CSF.WebDriverFactory/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Get.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Get.cs deleted file mode 100644 index c217afaa..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Get.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using CSF.Screenplay.JsonApis.Tests.Services; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Builders -{ - public static class Get - { - public static JsonServiceDescription TheNumber() => new GetNumberService(); - public static JsonServiceDescription TheSampleDataFor(string name) => new GetDataService(name); - public static JsonServiceDescription TheSampleDataSlowlyFor(string name) => new SlowlyGetDataService(name); - public static JsonServiceDescription TheSampleDataSlowlyFor(string name, TimeSpan timeout) - => new SlowlyGetDataService(name, timeout); - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Set.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Set.cs deleted file mode 100644 index 7906614c..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Set.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using CSF.Screenplay.JsonApis.Tests.Services; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Builders -{ - public static class Set - { - public static JsonServiceDescription TheNumberTo(int number) - => new SetNumberService(new SampleApiData { NewNumber = number }); - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Validate.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Validate.cs deleted file mode 100644 index 8b588c21..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Builders/Validate.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using CSF.Screenplay.JsonApis.Tests.Services; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Builders -{ - public static class Validate - { - public static JsonServiceDescription TheData(SampleApiData data) => new CheckDataService(data); - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/CSF.Screenplay.JsonApis.Tests.csproj b/Tests/CSF.Screenplay.JsonApis.Tests/CSF.Screenplay.JsonApis.Tests.csproj deleted file mode 100644 index a0bb1882..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/CSF.Screenplay.JsonApis.Tests.csproj +++ /dev/null @@ -1,81 +0,0 @@ - - - - Debug - AnyCPU - {AD2EA460-8F07-4068-90DF-0EB373836D86} - Library - CSF.Screenplay.JsonApis.Tests - CSF.Screenplay.JsonApis.Tests - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - - ..\..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - {9AA1246E-B5BC-499E-B0D9-EFA5F62F2E2C} - CSF.Screenplay.JsonApis - - - {7E16FEE8-2CEA-4581-B559-A399EF5A86A9} - CSF.Screenplay.WebTestWebsite - - - {18010B4E-22A7-4462-B057-7199B3386D48} - CSF.Screenplay.Reporting - - - {78571AD2-4C55-4459-A4D9-2CD63A9AACC7} - CSF.Screenplay.NUnit - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/ExecuteAJsonApiTests.cs b/Tests/CSF.Screenplay.JsonApis.Tests/ExecuteAJsonApiTests.cs deleted file mode 100644 index 901202f6..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/ExecuteAJsonApiTests.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using CSF.Screenplay.JsonApis.Builders; -using CSF.Screenplay.JsonApis.Tests.Builders; -using CSF.Screenplay.JsonApis.Tests.Services; -using CSF.Screenplay.NUnit; -using CSF.Screenplay.WebTestWebsite.ApiControllers; -using CSF.Screenplay.WebTestWebsite.Models; -using NUnit.Framework; -using static CSF.Screenplay.StepComposer; - -namespace CSF.Screenplay.JsonApis.Tests -{ - [TestFixture] - public class ExecuteAJsonApiTests - { - [Test,Screenplay] - public void Using_SetTheNumber_does_not_raise_exception(IScreenplayScenario scenario) - { - // Arrange - var joe = scenario.GetJoe(); - - // Act & assert - Assert.That(() => When(joe).AttemptsTo(Execute.AJsonApi(Set.TheNumberTo(5))), Throws.Nothing); - } - - [Test,Screenplay] - public void Using_SetTheNumber_then_GetTheNumber_returns_the_correct_number(IScreenplayScenario scenario) - { - // Arrange - var theNumber = 42; - var joe = scenario.GetJoe(); - Given(joe).WasAbleTo(Execute.AJsonApi(Set.TheNumberTo(theNumber))); - - // Act - var result = When(joe).AttemptsTo(Execute.AJsonApiAndGetTheResult(Get.TheNumber())); - - // Assert - Assert.That(result, Is.EqualTo(theNumber)); - } - - [Test,Screenplay] - public void Using_CheckData_does_not_raise_exception_for_valid_data(IScreenplayScenario scenario) - { - // Arrange - var joe = scenario.GetJoe(); - var theData = new SampleApiData { Name = ExecutionController.ValidName, DateAndTime = DateTime.Today }; - - // Act & assert - Assert.That(() => When(joe).AttemptsTo(Execute.AJsonApi(Validate.TheData(theData))), Throws.Nothing); - } - - [Test,Screenplay] - public void Using_CheckData_raises_exception_for_invalid_data(IScreenplayScenario scenario) - { - // Arrange - var joe = scenario.GetJoe(); - var theData = new SampleApiData { Name = "Invalid, crash expected", DateAndTime = DateTime.Today }; - - // Act & assert - Assert.That(() => When(joe).AttemptsTo(Execute.AJsonApi(Validate.TheData(theData))), - Throws.InstanceOf()); - } - - [Test,Screenplay] - public void Using_GetData_returns_expected_result(IScreenplayScenario scenario) - { - // Arrange - var joe = scenario.GetJoe(); - - // Act - var result = When(joe).AttemptsTo(Execute.AJsonApiAndGetTheResult(Get.TheSampleDataFor(joe.Name))); - - // Assert - Assert.That(result, Is.Not.Null, "Result should not be null"); - Assert.That(result.Name, Is.EqualTo(joe.Name), "Result name should be as expected"); - Assert.That(result.DateAndTime, Is.EqualTo(DataController.SampleDateTime), "Result date should be as expected"); - } - - [Test,Screenplay] - public void Using_GetDataSlowly_does_not_raise_exception_if_timeout_is_30_seconds(IScreenplayScenario scenario) - { - // Arrange - var joe = scenario.GetJoe(); - var timeout = TimeSpan.FromSeconds(30); - - // Act & assert - Assert.That(() => When(joe).AttemptsTo(Execute.AJsonApiAndGetTheResult(Get.TheSampleDataSlowlyFor(joe.Name, timeout))), - Throws.Nothing); - } - - [Test,Screenplay] - public void Using_GetDataSlowly_raises_exception_if_timeout_is_1_second(IScreenplayScenario scenario) - { - // Arrange - var joe = scenario.GetJoe(); - var timeout = TimeSpan.FromSeconds(1); - - // Act & assert - Assert.That(() => When(joe).AttemptsTo(Execute.AJsonApiAndGetTheResult(Get.TheSampleDataSlowlyFor(joe.Name, timeout))), - Throws.InstanceOf()); - } - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/ScenarioExtensions.cs b/Tests/CSF.Screenplay.JsonApis.Tests/ScenarioExtensions.cs deleted file mode 100644 index 1718edd3..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/ScenarioExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.JsonApis.Abilities; - -namespace CSF.Screenplay.JsonApis.Tests -{ - public static class ScenarioExtensions - { - public static IActor GetJoe(this IScreenplayScenario scenario) - { - var cast = scenario.GetCast(); - return cast.Get("Joe", (actor, s) => { - var consumeWebServices = new ConsumeJsonWebServices("http://localhost:8080/api/"); - actor.IsAbleTo(consumeWebServices); - }, scenario); - } - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/ScreenplayConfig.cs b/Tests/CSF.Screenplay.JsonApis.Tests/ScreenplayConfig.cs deleted file mode 100644 index 63272ea5..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/ScreenplayConfig.cs +++ /dev/null @@ -1,29 +0,0 @@ -using CSF.Screenplay.Integration; -using CSF.Screenplay.JsonApis.Tests; -using CSF.Screenplay.NUnit; -using CSF.Screenplay.Reporting; -using CSF.Screenplay.Reporting.Models; - -[assembly: ScreenplayAssembly(typeof(ScreenplayConfig))] - -namespace CSF.Screenplay.JsonApis.Tests -{ - public class ScreenplayConfig : IIntegrationConfig - { - public void Configure(IIntegrationConfigBuilder builder) - { - builder.UseCast(); - builder.UseReporting(config => { - config - .SubscribeToActorsCreatedInCast() - .WriteReport(WriteReport); - }); - } - - void WriteReport(IObjectFormattingService formatter, Report report) - { - var path = "JsonApis.report.txt"; - TextReportWriter.WriteToFile(report, path, formatter); - } - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Services/CheckDataService.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Services/CheckDataService.cs deleted file mode 100644 index 22e274e9..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Services/CheckDataService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Net.Http; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Services -{ - public class CheckDataService : JsonServiceDescription - { - protected override string GetUriString() => "Execution/CheckData"; - - public CheckDataService(SampleApiData data) : base(requestPayload: data) {} - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Services/GetDataService.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Services/GetDataService.cs deleted file mode 100644 index 2e2de1a4..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Services/GetDataService.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Net.Http; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Services -{ - public class GetDataService : JsonServiceDescription - { - readonly string name; - - protected override HttpMethod GetHttpMethod() => HttpMethod.Get; - - protected override string GetUriString() => $"Data/sample-data/{name}"; - - public GetDataService(string name) : base() - { - if(name == null) - throw new ArgumentNullException(nameof(name)); - - this.name = name; - } - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Services/GetNumberService.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Services/GetNumberService.cs deleted file mode 100644 index 35565894..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Services/GetNumberService.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Net.Http; - -namespace CSF.Screenplay.JsonApis.Tests.Services -{ - public class GetNumberService : JsonServiceDescription - { - protected override HttpMethod GetHttpMethod() => HttpMethod.Get; - - protected override string GetUriString() => $"Execution/GetMyNumber"; - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Services/SetNumberService.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Services/SetNumberService.cs deleted file mode 100644 index 8cb790eb..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Services/SetNumberService.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Services -{ - public class SetNumberService : JsonServiceDescription - { - protected override string GetUriString() => $"Execution/SetMyNumber"; - - public SetNumberService(SampleApiData data) : base(requestPayload: data) {} - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/Services/SlowlyGetDataService.cs b/Tests/CSF.Screenplay.JsonApis.Tests/Services/SlowlyGetDataService.cs deleted file mode 100644 index 973622a5..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/Services/SlowlyGetDataService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using CSF.Screenplay.WebTestWebsite.Models; - -namespace CSF.Screenplay.JsonApis.Tests.Services -{ - public class SlowlyGetDataService : JsonServiceDescription - { - readonly string name; - - protected override string GetUriString() => $"Data/slow-sample-data/{name}"; - - public SlowlyGetDataService(string name, TimeSpan? timeout = null) : base(timeout: timeout) - { - if(name == null) - throw new ArgumentNullException(nameof(name)); - - this.name = name; - } - } -} diff --git a/Tests/CSF.Screenplay.JsonApis.Tests/packages.config b/Tests/CSF.Screenplay.JsonApis.Tests/packages.config deleted file mode 100644 index 8b674639..00000000 --- a/Tests/CSF.Screenplay.JsonApis.Tests/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/AutoMoqDataAttribute.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/AutoMoqDataAttribute.cs deleted file mode 100644 index ae875b47..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/AutoMoqDataAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.AutoMoq; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.Screenplay.Reporting.Html.Tests -{ - public class AutoMoqDataAttribute : AutoDataAttribute - { - public AutoMoqDataAttribute() : base(new Fixture().Customize(new AutoMoqCustomization())) - { - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/AbilityCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/AbilityCustomisation.cs deleted file mode 100644 index e054b807..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/AbilityCustomisation.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using Moq; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class AbilityCustomisation : ICustomization - { - static readonly string[] Names = { - "fly", - "swim", - "run", - "walk", - "sing", - "dance", - "hop", - "skip", - "jump", - "climb" - }; - - public void Customize(IFixture fixture) - { - fixture.Customize(builder => builder.FromFactory(CreateAbility)); - } - - IAbility CreateAbility() - { - var abilityName = Names[ScenarioCustomisation.Randomiser.Next(0, Names.Length)]; - - var ability = new Mock(); - ability - .Setup(x => x.GetReport(It.IsAny())) - .Returns((INamed a) => $"{a.Name} is able to {abilityName}"); - - return ability.Object; - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/FeatureCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/FeatureCustomisation.cs deleted file mode 100644 index 09a5baef..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/FeatureCustomisation.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class FeatureCustomisation : ICustomization - { - public void Customize(IFixture fixture) - { - new ScenarioCustomisation().Customize(fixture); - fixture.Customize(builder => builder.FromFactory>(CreateFeature)); - } - - Feature CreateFeature(string id, string name, IList scenarios) - => new Feature($"FeatureId {id}", $"Feature {name}", scenarios.ToArray()); - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/GainAbilityCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/GainAbilityCustomisation.cs deleted file mode 100644 index dd081dee..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/GainAbilityCustomisation.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Reporting.Models; -using Moq; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class GainAbilityCustomisation : ICustomization - { - public void Customize(IFixture fixture) - { - fixture.Customize(builder => builder.FromFactory(CreateGainAbility)); - } - - GainAbility CreateGainAbility(PerformanceOutcome outcome, - INamed actor, - IAbility ability) - { - return new GainAbility(actor, outcome, ability, PerformanceType.Given); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/NamedCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/NamedCustomisation.cs deleted file mode 100644 index 4a260008..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/NamedCustomisation.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using Moq; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class NamedCustomisation : ICustomization - { - static readonly string[] Names = { - "Joe", - "Bob", - "Jane", - "Anne", - "Siobahn", - "Youssef", - "Wong", - "Nancy", - "Jasmine", - "Julian" - }; - - public void Customize(IFixture fixture) - { - fixture.Customize(builder => builder.FromFactory(CreateNamed)); - } - - INamed CreateNamed() - { - var name = Names[ScenarioCustomisation.Randomiser.Next(0, Names.Length)]; - return Mock.Of(x => x.Name == name); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformableCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformableCustomisation.cs deleted file mode 100644 index d5f83734..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformableCustomisation.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using CSF.Screenplay.Performables; -using Ploeh.AutoFixture; -using Moq; -using CSF.Screenplay.Actors; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class PerformableCustomisation : ICustomization - { - public void Customize(IFixture fixture) - { - fixture.Customize(builder => builder.FromFactory(CreatePerformable)); - } - - IPerformable CreatePerformable(string id) - { - var output = new Mock(); - output - .Setup(x => x.GetReport(It.IsAny())) - .Returns((INamed actor) => $"{actor.Name} executes performable {id}"); - return output.Object; - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceCustomisation.cs deleted file mode 100644 index 89fbefda..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceCustomisation.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.Kernel; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class PerformanceCustomisation : ICustomization - { - readonly ISpecimenBuilder performanceBuilder; - - public void Customize(IFixture fixture) - { - fixture.Customize(builder => builder.FromFactory(performanceBuilder)); - } - - public PerformanceCustomisation() - { - performanceBuilder = new PerformanceSpecimenBuilder(); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceSpecimenBuilder.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceSpecimenBuilder.cs deleted file mode 100644 index d203c0c8..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/PerformanceSpecimenBuilder.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture.Kernel; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class PerformanceSpecimenBuilder : ISpecimenBuilder - { - public object Create(object request, ISpecimenContext context) - { - var type = request as Type; - if(type == null) return new NoSpecimen(); - if(!typeof(Performance).IsAssignableFrom(type)) return new NoSpecimen(); - - return CreatePerformance(context); - } - - Performance CreatePerformance(ISpecimenContext context) - { - var category = SelectPerformanceCategory(); - switch(category) - { - case PerformanceCategory.FailureWithException: - return CreateFailurePerformance(context); - - case PerformanceCategory.SuccessWithResult: - return CreateSuccessPerformanceWithResult(context); - - case PerformanceCategory.SuccessWithChildren: - return CreateSuccessPerformanceWithChildren(context); - - default: - return CreateSuccessPerformance(context); - } - } - - Performance CreateSuccessPerformance(ISpecimenContext context) - { - return CreatePerformance(context, - PerformanceOutcome.Success); - } - - Performance CreateSuccessPerformanceWithChildren(ISpecimenContext context) - { - var howManyChildren = ScenarioCustomisation.Randomiser.Next(1, 5); - var children = Enumerable.Range(0, howManyChildren) - .Select(x => context.Resolve(typeof(Performance))) - .Cast() - .ToArray(); - return CreatePerformance(context, - PerformanceOutcome.Success, - children: children); - } - - Performance CreateSuccessPerformanceWithResult(ISpecimenContext context) - { - return CreatePerformance(context, - PerformanceOutcome.SuccessWithResult, - context.Resolve(typeof(Guid))); - } - - Performance CreateFailurePerformance(ISpecimenContext context) - { - return CreatePerformance(context, - PerformanceOutcome.FailureWithException, - exception: (Exception) context.Resolve(typeof(Exception))); - } - - Performance CreatePerformance(ISpecimenContext context, - PerformanceOutcome outcome, - object result = null, - Exception exception = null, - IList children = null) - { - var actor = (INamed) context.Resolve(typeof(INamed)); - var performable = (IPerformable) context.Resolve(typeof(IPerformable)); - var performanceType = SelectPerformanceType(); - - return new Performance(actor, outcome, performable, performanceType, result, exception, children); - } - - PerformanceType SelectPerformanceType() - { - var randomNumber = ScenarioCustomisation.Randomiser.Next(0, 3); - if(randomNumber == 0) return PerformanceType.Given; - if(randomNumber == 1) return PerformanceType.When; - return PerformanceType.Then; - } - - PerformanceCategory SelectPerformanceCategory() - { - var randomNumber = ScenarioCustomisation.Randomiser.Next(0, 10); - - if(randomNumber < 5) return PerformanceCategory.Success; - if(randomNumber < 7) return PerformanceCategory.SuccessWithResult; - if(randomNumber < 9) return PerformanceCategory.SuccessWithChildren; - return PerformanceCategory.FailureWithException; - } - - enum PerformanceCategory - { - Success, - SuccessWithChildren, - SuccessWithResult, - FailureWithException - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/RandomReportAttribute.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/RandomReportAttribute.cs deleted file mode 100644 index b9ce83e4..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/RandomReportAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Reflection; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class RandomReportAttribute : CustomizeAttribute - { - public override ICustomization GetCustomization(ParameterInfo parameter) - { - if(parameter.ParameterType != typeof(Report)) - { - throw new InvalidOperationException($"`{nameof(RandomReportAttribute)}' is only valid for `{nameof(Report)}' parameters."); - } - - return new ReportCustomisation(); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ReportCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ReportCustomisation.cs deleted file mode 100644 index c94149e7..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ReportCustomisation.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class ReportCustomisation : ICustomization - { - public void Customize(IFixture fixture) - { - fixture.Behaviors.OfType() - .ToList() - .ForEach(x => fixture.Behaviors.Remove(x)); - - new FeatureCustomisation().Customize(fixture); - fixture.Customize(builder => builder.FromFactory>(CreateReport)); - } - - Report CreateReport(IList features) => new Report(features.ToArray()); - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ScenarioCustomisation.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ScenarioCustomisation.cs deleted file mode 100644 index c0d8f049..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/ScenarioCustomisation.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class ScenarioCustomisation : ICustomization - { - static readonly Random randomiser; - - public static Random Randomiser => randomiser; - - public void Customize(IFixture fixture) - { - new NamedCustomisation().Customize(fixture); - new AbilityCustomisation().Customize(fixture); - new PerformableCustomisation().Customize(fixture); - new GainAbilityCustomisation().Customize(fixture); - new PerformanceCustomisation().Customize(fixture); - - fixture.Customize(builder => { - return builder - .FromFactory(CreateScenario) - .Do(s => { - ConfigureRandomOutcome(s); - AddSomeReportables(s, fixture); - }); - }); - } - - Scenario CreateScenario(string id, string name) - => new Scenario($"ScenarioId {id}", $"Scenario {name}"); - - void ConfigureRandomOutcome(Scenario scenario) - { - var random = Randomiser.Next(1, 4); - - switch(random) - { - case 1: - scenario.Outcome = true; - break; - - case 2: - scenario.Outcome = false; - break; - - default: - scenario.Outcome = null; - break; - } - } - - void AddSomeReportables(Scenario scenario, IFixture fixture) - { - int - howManyAbilities = Randomiser.Next(0, 4), - howManyPerformances = Randomiser.Next(1, 6); - - var abilities = fixture.CreateMany(howManyAbilities); - var performances = fixture.CreateMany(howManyPerformances); - - foreach(var ability in abilities) - scenario.Reportables.Add(ability); - - foreach(var performance in performances) - scenario.Reportables.Add(performance); - } - - static ScenarioCustomisation() - { - randomiser = new Random(); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/StringFormatAttribute.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/StringFormatAttribute.cs deleted file mode 100644 index 8b57a475..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/Autofixture/StringFormatAttribute.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Reflection; -using Moq; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.Screenplay.Reporting.Html.Tests.Autofixture -{ - public class StringFormatAttribute : CustomizeAttribute - { - public override ICustomization GetCustomization(ParameterInfo parameter) - { - if(parameter.ParameterType != typeof(IObjectFormattingService)) - { - throw new InvalidOperationException($"`{nameof(StringFormatAttribute)}' is only valid for `{nameof(IObjectFormattingService)}' parameters."); - } - - return new StringFormatCustomisation(); - } - - public class StringFormatCustomisation : ICustomization - { - public void Customize(IFixture fixture) - { - fixture.Customize(builder => { - return builder - .FromFactory(() => Mock.Of()) - .Do(service => { - Mock.Get(service) - .Setup(x => x.Format(It.IsAny())) - .Returns((object obj) => obj?.ToString()); - }); - }); - } - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/CSF.Screenplay.Reporting.Html.Tests.csproj b/Tests/CSF.Screenplay.Reporting.Html.Tests/CSF.Screenplay.Reporting.Html.Tests.csproj deleted file mode 100644 index 703457c0..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/CSF.Screenplay.Reporting.Html.Tests.csproj +++ /dev/null @@ -1,136 +0,0 @@ - - - - Debug - AnyCPU - {C3A68C7D-848E-434C-8004-9BC3B99CF2B8} - Library - CSF.Screenplay.Reporting.Html.Tests - CSF.Screenplay.Reporting.Html.Tests - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\AutoFixture.3.50.3\lib\net40\Ploeh.AutoFixture.dll - - - ..\..\packages\AutoFixture.NUnit3.3.50.3\lib\net40\Ploeh.AutoFixture.NUnit3.dll - - - ..\..\packages\AutoFixture.AutoMoq.3.50.3\lib\net40\Ploeh.AutoFixture.AutoMoq.dll - - - ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - - ..\..\packages\Moq.4.7.25\lib\net45\Moq.dll - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - ..\..\packages\CSF.Caches.1.0.0\lib\net45\CSF.Caches.dll - - - ..\..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll - - - ..\..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll - - - ..\..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll - - - - - - - - ..\..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll - - - ..\..\packages\CSF.Zpt.Abstractions.1.0.3\lib\net45\CSF.Zpt.Abstractions.dll - - - ..\..\packages\CSF.Zpt.1.0.3\lib\net45\CSF.Zpt.dll - - - ..\..\packages\CSF.Zpt.ExpressionEvaluators.PathExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.PathExpressions.dll - - - ..\..\packages\CSF.Zpt.ExpressionEvaluators.LoadExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.LoadExpressions.dll - - - ..\..\packages\CSF.Zpt.DocumentProviders.HtmlHAP.1.0.3\lib\net45\CSF.Zpt.DocumentProviders.HtmlHAP.dll - - - ..\..\packages\CSF.Zpt.DocumentProviders.XmlLinq.1.0.3\lib\net45\CSF.Zpt.DocumentProviders.XmlLinq.dll - - - ..\..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.dll - - - ..\..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpFramework.dll - - - ..\..\packages\CSF.Zpt.ExpressionEvaluators.NotExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.NotExpressions.dll - - - ..\..\packages\CSF.Zpt.ExpressionEvaluators.StringExpressions.1.0.3\lib\net45\CSF.Zpt.ExpressionEvaluators.StringExpressions.dll - - - - - - - - - - - - - - - - - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - {18010B4E-22A7-4462-B057-7199B3386D48} - CSF.Screenplay.Reporting - - - {29AA4CCD-A7B7-414E-A57F-FDE74A04A19F} - CSF.Screenplay.Reporting.Html - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/HtmlReportWriterTests.cs b/Tests/CSF.Screenplay.Reporting.Html.Tests/HtmlReportWriterTests.cs deleted file mode 100644 index 704eaf0b..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/HtmlReportWriterTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using NUnit.Framework; -using CSF.Screenplay.Reporting.Models; -using CSF.Screenplay.Reporting.Html.Tests.Autofixture; -using System.Text; -using System.IO; - -namespace CSF.Screenplay.Reporting.Html.Tests -{ - [TestFixture] - public class HtmlReportWriterTests - { - [Test,AutoMoqData] - public void Write_can_create_a_document_without_crashing([RandomReport] Report report, - [StringFormat] IObjectFormattingService formatService) - { - // Arrange - var sb = new StringBuilder(); - using(var writer = new StringWriter(sb)) - { - var sut = new HtmlReportWriter(writer, formatService); - - // Act & assert - Assert.DoesNotThrow(() => sut.Write(report)); - } - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/app.config b/Tests/CSF.Screenplay.Reporting.Html.Tests/app.config deleted file mode 100644 index 84dbd2ac..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/app.config +++ /dev/null @@ -1,64 +0,0 @@ - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tests/CSF.Screenplay.Reporting.Html.Tests/packages.config b/Tests/CSF.Screenplay.Reporting.Html.Tests/packages.config deleted file mode 100644 index 3d414b48..00000000 --- a/Tests/CSF.Screenplay.Reporting.Html.Tests/packages.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Reporting.Tests/App.config b/Tests/CSF.Screenplay.Reporting.Tests/App.config deleted file mode 100644 index aef5c239..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/App.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/Tests/CSF.Screenplay.Reporting.Tests/AutoMoqDataAttribute.cs b/Tests/CSF.Screenplay.Reporting.Tests/AutoMoqDataAttribute.cs deleted file mode 100644 index 8e5b6139..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/AutoMoqDataAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.AutoMoq; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.Screenplay.Reporting.Tests -{ - public class AutoMoqDataAttribute : AutoDataAttribute - { - public AutoMoqDataAttribute() : base(new Fixture().Customize(new AutoMoqCustomization())) - { - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioAttribute.cs b/Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioAttribute.cs deleted file mode 100644 index aeb7c15e..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Reflection; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.Screenplay.Reporting.Tests.Autofixture -{ - public class ScenarioAttribute : CustomizeAttribute - { - public string FeatureId { get; set; } - - public string ScenarioId { get; set; } - - public string FeatureName { get; set; } - - public string ScenarioName { get; set; } - - public override ICustomization GetCustomization(ParameterInfo parameter) - { - if(parameter.ParameterType != typeof(Scenario)) - { - throw new InvalidOperationException($"`{nameof(ScenarioAttribute)}' is only valid for `{nameof(Scenario)}' parameters."); - } - - return new ScenarioCustomization(FeatureId, ScenarioId, FeatureName, ScenarioName); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioCustomization.cs b/Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioCustomization.cs deleted file mode 100644 index 2bc6cb00..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/Autofixture/ScenarioCustomization.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using CSF.Screenplay.Reporting.Models; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Tests.Autofixture -{ - public class ScenarioCustomization : ICustomization - { - readonly string featureId, scenarioId, featureName, scenarioName; - - public void Customize(IFixture fixture) - { - fixture.Customize(builder => { - return builder.FromFactory((string sId, string sName, string fId, string fName) => { - return new Scenario(scenarioId?? sId, - scenarioName?? sName, - featureName?? fName, - featureId?? fId); - }); - }); - } - - public ScenarioCustomization(string featureId, string scenarioId, string featureName, string scenarioName) - { - this.scenarioName = scenarioName; - this.featureName = featureName; - this.scenarioId = scenarioId; - this.featureId = featureId; - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Tests/CSF.Screenplay.Reporting.Tests.csproj b/Tests/CSF.Screenplay.Reporting.Tests/CSF.Screenplay.Reporting.Tests.csproj deleted file mode 100644 index 25855006..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/CSF.Screenplay.Reporting.Tests.csproj +++ /dev/null @@ -1,75 +0,0 @@ - - - - Debug - AnyCPU - {404C337E-3CC0-4168-86BA-3309515FB558} - Library - CSF.Screenplay.Reporting.Tests - CSF.Screenplay.Reporting.Tests - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - - ..\..\packages\Moq.4.7.25\lib\net45\Moq.dll - - - ..\..\packages\AutoFixture.3.50.3\lib\net40\Ploeh.AutoFixture.dll - - - ..\..\packages\AutoFixture.NUnit3.3.50.3\lib\net40\Ploeh.AutoFixture.NUnit3.dll - - - ..\..\packages\AutoFixture.AutoMoq.3.50.3\lib\net40\Ploeh.AutoFixture.AutoMoq.dll - - - - - - - - - - - - - - - - - {18010B4E-22A7-4462-B057-7199B3386D48} - CSF.Screenplay.Reporting - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Reporting.Tests/ReportBuilderTests.cs b/Tests/CSF.Screenplay.Reporting.Tests/ReportBuilderTests.cs deleted file mode 100644 index 0432b46a..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/ReportBuilderTests.cs +++ /dev/null @@ -1,276 +0,0 @@ -using NUnit.Framework; -using System; -using CSF.Screenplay.Reporting.Builders; -using System.Linq; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.Reporting.Models; -using Moq; -using System.Collections.Generic; - -namespace CSF.Screenplay.Reporting.Tests -{ - [TestFixture,Parallelizable] - public class ReportBuilderTests - { - [Test,AutoMoqData] - public void BeginNewScenario_creates_single_scenario(string id, - string name, - string feature, - ReportBuilder sut, - Guid scenarioIdentity) - { - // Act - sut.BeginNewScenario(id, name, feature, null, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - Assert.That(report.Scenarios, Is.Not.Null, "Scenarios is not null"); - Assert.That(report.Scenarios.Count, Is.EqualTo(1), "One scenario present"); - var scenario = report.Scenarios.Single(); - Assert.That(scenario.Id, Is.EqualTo(id), "Scenario ID is correct"); - Assert.That(scenario.FriendlyName, Is.EqualTo(name), "Scenario name is correct"); - Assert.That(scenario.FeatureName, Is.EqualTo(feature), "Scenario feature name is correct"); - } - - [Test,AutoMoqData] - public void BeginNewScenario_passes_feature_name(string id, - string featureId, - ReportBuilder sut, - Guid scenarioIdentity) - { - // Act - sut.BeginNewScenario(id, null, null, featureId, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - var scenario = report.Scenarios.Single(); - Assert.That(scenario.FeatureId, Is.EqualTo(featureId)); - } - - [Test,AutoMoqData] - public void EndScenario_raises_exception_when_called_before_BeginScenario(ReportBuilder sut, - bool success, - Guid scenarioIdentity) - { - // Act & assert - Assert.That(() => sut.EndScenario(success, scenarioIdentity), Throws.TypeOf()); - } - - [Test,AutoMoqData] - public void EndScenario_closes_the_current_scenario(ReportBuilder sut, - bool success, - string idOne, - string idTwo, - Guid scenarioIdentity, - Guid otherIdentity) - { - // Arrange - sut.BeginNewScenario(idOne, null, null, null, scenarioIdentity); - - // Act - sut.EndScenario(success, scenarioIdentity); - sut.BeginNewScenario(idTwo, null, null, null, otherIdentity); - - // Assert - var report = sut.GetReport(); - var scenarioNames = report.Scenarios.Select(x => x.Id).ToArray(); - Assert.That(scenarioNames, Is.EquivalentTo(new [] { idOne, idTwo })); - } - - [Test,AutoMoqData] - public void BeginScenario_with_the_same_identity_twice_raises_an_exception(ReportBuilder sut, - bool success, - string idOne, - string idTwo, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(idOne, null, null, null, scenarioIdentity); - - // Act & assert - Assert.That(() => sut.BeginNewScenario(idTwo, null, null, null, scenarioIdentity), Throws.InvalidOperationException); - } - - [Test,AutoMoqData] - public void BeginPerformance_raises_exception_when_called_before_BeginScenario(INamed actor, - IPerformable performable, - ReportBuilder sut, - Guid scenarioIdentity) - { - // Act & assert - Assert.That(() => sut.BeginPerformance(actor, performable, scenarioIdentity), Throws.TypeOf()); - } - - [Test,AutoMoqData] - public void BeginPerformance_raises_exception_when_called_after_EndScenario(INamed actor, - IPerformable performable, - string id, - bool success, - ReportBuilder sut, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - sut.EndScenario(success, scenarioIdentity); - - // Act & assert - Assert.That(() => sut.BeginPerformance(actor, performable, scenarioIdentity), Throws.TypeOf()); - } - - [Test,AutoMoqData] - public void BeginPerformanceType_raises_exception_when_called_before_BeginScenario(PerformanceType type, - ReportBuilder sut, - Guid scenarioIdentity) - { - // Act & assert - Assert.That(() => sut.BeginPerformanceType(type, scenarioIdentity), Throws.TypeOf()); - } - - [Test,AutoMoqData] - public void BeginPerformanceType_raises_exception_when_called_after_EndScenario(PerformanceType type, - string id, - bool success, - ReportBuilder sut, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - sut.EndScenario(success, scenarioIdentity); - - // Act & assert - Assert.That(() => sut.BeginPerformanceType(type, scenarioIdentity), Throws.TypeOf()); - } - - [Test,AutoMoqData] - public void BeginPerformanceType_marks_a_performance_with_the_appropriate_type(ReportBuilder sut, - string id, - INamed actor, - IPerformable performable, - Guid scenarioIdentity) - { - // Arrange - var type = PerformanceType.Then; - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - - // Act - sut.BeginPerformanceType(type, scenarioIdentity); - sut.BeginPerformance(actor, performable, scenarioIdentity); - sut.RecordSuccess(performable, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - Assert.That(report.Scenarios.Single().Reportables.Single().PerformanceType, Is.EqualTo(type)); - } - - [Test,AutoMoqData] - public void BeginPerformance_records_the_actor(ReportBuilder sut, - string id, - INamed actor, - IPerformable performable, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - - // Act - sut.BeginPerformance(actor, performable, scenarioIdentity); - sut.RecordSuccess(performable, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - Assert.That(report.Scenarios.Single().Reportables.Single().Actor, Is.SameAs(actor)); - } - - [Test,AutoMoqData] - public void BeginPerformance_creates_a_performance_report(ReportBuilder sut, - string id, - INamed actor, - IPerformable performable, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - - // Act - sut.BeginPerformance(actor, performable, scenarioIdentity); - sut.RecordSuccess(performable, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - var performance = report.Scenarios.Single().Reportables.Single() as Performance; - Assert.That(performable, Is.Not.Null); - } - - [Test,AutoMoqData] - public void BeginPerformance_records_the_performable(ReportBuilder sut, - string id, - INamed actor, - IPerformable performable, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - - // Act - sut.BeginPerformance(actor, performable, scenarioIdentity); - sut.RecordSuccess(performable, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - var performance = report.Scenarios.Single().Reportables.Single() as Performance; - Assert.That(performance.Performable, Is.SameAs(performable)); - } - - [Test,AutoMoqData] - public void BeginPerformance_can_create_nested_reportables(ReportBuilder sut, - string id, - INamed actor, - IPerformable performable, - IPerformable differentPerformable, - Guid scenarioIdentity) - { - // Arrange - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - sut.BeginPerformance(actor, performable, scenarioIdentity); - - // Act - sut.BeginPerformance(actor, differentPerformable, scenarioIdentity); - sut.RecordSuccess(differentPerformable, scenarioIdentity); - sut.RecordSuccess(performable, scenarioIdentity); - - // Assert - var report = sut.GetReport(); - var performance = report.Scenarios.Single().Reportables.Single() as Performance; - var childPerformance = performance.Reportables.Single() as Performance; - Assert.That(childPerformance.Performable, Is.SameAs(differentPerformable)); - } - - [Test,AutoMoqData] - public void GetReport_uses_report_factory(IReportFactory factory, - string id, - INamed actor, - IPerformable performable, - Guid scenarioIdentity, - Report report) - { - // Arrange - var sut = new ReportBuilder(factory); - sut.BeginNewScenario(id, null, null, null, scenarioIdentity); - sut.BeginPerformance(actor, performable, scenarioIdentity); - sut.RecordSuccess(performable, scenarioIdentity); - - Mock.Get(factory) - .Setup(x => x.GetReport(It.IsAny>())) - .Returns(report); - - // Act - var result = sut.GetReport(); - - // Assert - Assert.AreSame(report, result, "Result is same instance returned by factory"); - Mock.Get(factory) - .Verify(x => x.GetReport(It.IsAny>()), Times.Once()); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Tests/ReportFactoryTests.cs b/Tests/CSF.Screenplay.Reporting.Tests/ReportFactoryTests.cs deleted file mode 100755 index 3ae3783c..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/ReportFactoryTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Linq; -using CSF.Screenplay.Reporting.Models; -using CSF.Screenplay.Reporting.Tests.Autofixture; -using NUnit.Framework; -using Ploeh.AutoFixture; - -namespace CSF.Screenplay.Reporting.Tests -{ - [TestFixture] - public class ReportFactoryTests - { - [Test,AutoMoqData] - public void GetReport_returns_all_scenarios(ReportFactory sut, - [Scenario] Scenario scenarioOne, - [Scenario] Scenario scenarioTwo, - [Scenario] Scenario scenarioThree) - { - // Arrange - var allScenarios = new [] { scenarioOne, scenarioTwo, scenarioThree }; - - // Act - var result = sut.GetReport(allScenarios); - - // Assert - CollectionAssert.AreEquivalent(allScenarios, result.Scenarios); - } - - [Test,AutoMoqData] - public void GetReport_does_not_create_duplicate_features_when_multiple_scenarios_use_the_same_feature( - ReportFactory sut, - [Scenario(FeatureId = "TestFeature")] Scenario scenarioOne, - [Scenario(FeatureId = "TestFeature")] Scenario scenarioTwo, - [Scenario(FeatureId = "TestFeature")] Scenario scenarioThree) - { - // Arrange - var allScenarios = new [] { scenarioOne, scenarioTwo, scenarioThree }; - - // Act - var result = sut.GetReport(allScenarios); - - // Assert - Assert.AreEqual(1, result.Features.Count, "Only one feature created"); - Assert.AreEqual("TestFeature", result.Features.First().Id); - } - - [Test,AutoMoqData] - public void GetReport_places_all_scenarios_in_the_correct_feature( - ReportFactory sut, - [Scenario(FeatureId = "TestFeature1")] Scenario scenarioOne, - [Scenario(FeatureId = "TestFeature2")] Scenario scenarioTwo, - [Scenario(FeatureId = "TestFeature1")] Scenario scenarioThree) - { - // Arrange - var allScenarios = new [] { scenarioOne, scenarioTwo, scenarioThree }; - var expectedScenariosInFeature1 = new [] { scenarioOne, scenarioThree }; - var expectedScenariosInFeature2 = new [] { scenarioTwo }; - - // Act - var result = sut.GetReport(allScenarios); - - // Assert - Assert.AreEqual(2, result.Features.Count, "Two features created"); - var actualScenariosInFeature1 = result.Features.Single(x => x.Id == "TestFeature1").Scenarios; - var actualScenariosInFeature2 = result.Features.Single(x => x.Id == "TestFeature2").Scenarios; - - CollectionAssert.AreEquivalent(expectedScenariosInFeature1, actualScenariosInFeature1, "Scenarios in feature 1"); - CollectionAssert.AreEquivalent(expectedScenariosInFeature2, actualScenariosInFeature2, "Scenarios in feature 2"); - } - - [Test,AutoMoqData] - public void GetReport_orders_features_alphabetically_by_name( - ReportFactory sut, - [Scenario(FeatureId = "C feature", FeatureName = "CC this is the third feature")] Scenario scenarioOne, - [Scenario(FeatureId = "A feature", FeatureName = "AA this is the first feature")] Scenario scenarioTwo, - [Scenario(FeatureId = "B feature", FeatureName = "BB this is the second feature")] Scenario scenarioThree) - { - // Arrange - var allScenarios = new [] { scenarioOne, scenarioTwo, scenarioThree }; - var expectedFeatureOrder = new [] { "A feature", "B feature", "C feature" }; - - // Act - var result = sut.GetReport(allScenarios); - - // Assert - var orderedFeatures = result.Features.Select(x => x.Id).ToArray(); - CollectionAssert.AreEqual(expectedFeatureOrder, orderedFeatures); - } - - [Test,AutoMoqData] - public void GetReport_orders_scenarios_alphabetically_by_name_within_features( - ReportFactory sut, - [Scenario(FeatureId = "TestFeature", ScenarioId = "S3", ScenarioName = "C third")] Scenario scenarioOne, - [Scenario(FeatureId = "TestFeature", ScenarioId = "S1", ScenarioName = "A first")] Scenario scenarioTwo, - [Scenario(FeatureId = "TestFeature", ScenarioId = "S2", ScenarioName = "B second")] Scenario scenarioThree) - { - // Arrange - var allScenarios = new [] { scenarioOne, scenarioTwo, scenarioThree }; - var expectedScenarioOrder = new [] { "S1", "S2", "S3" }; - - // Act - var result = sut.GetReport(allScenarios); - - // Assert - var feature = result.Features.Single(); - var actualScenarioOrder = feature.Scenarios.Select(x => x.Id).ToArray(); - CollectionAssert.AreEqual(expectedScenarioOrder, actualScenarioOrder); - } - } -} \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Reporting.Tests/TextReportWriterTests.cs b/Tests/CSF.Screenplay.Reporting.Tests/TextReportWriterTests.cs deleted file mode 100644 index 15b29e82..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/TextReportWriterTests.cs +++ /dev/null @@ -1,342 +0,0 @@ -using System; -using NUnit.Framework; -using CSF.Screenplay.Reporting; -using System.Text; -using System.IO; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using Moq; -using CSF.Screenplay.Reporting.Models; - -namespace CSF.Screenplay.Reporting.Tests -{ - [TestFixture] - public class TextReportWriterTests - { - string ExerciseSut(Report report) - { - var builder = new StringBuilder(); - - using(var writer = new StringWriter(builder)) - { - var sut = new TextReportWriter(writer); - sut.Write(report); - } - - return builder.ToString(); - } - - [Test,AutoMoqData] - public void Can_create_report_with_one_performance(string id, - string name, - string feature, - IActor actor, - IPerformable performable) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Success **** -Given Joe does a thing -"; - - Mock.Get(performable) - .Setup(x => x.GetReport(actor)) - .Returns("Joe does a thing"); - - var scenario = new Models.Scenario(id, name, feature) { Outcome = true }; - scenario.Reportables.Add(new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given)); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Can_create_report_with_scenario_failure(IActor actor, - IPerformable performable, - string id, - string name, - string feature) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Failure **** -Given Joe does a thing -"; - - Mock.Get(performable) - .Setup(x => x.GetReport(actor)) - .Returns("Joe does a thing"); - - var scenario = new Models.Scenario(id, name, feature) { Outcome = false }; - scenario.Reportables.Add(new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given)); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Can_create_report_with_inconclusive_outcome(IActor actor, - IPerformable performable, - string id, - string name, - string feature) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Inconclusive **** -Given Joe does a thing -"; - - Mock.Get(performable) - .Setup(x => x.GetReport(actor)) - .Returns("Joe does a thing"); - - var scenario = new Models.Scenario(id, name, feature); - scenario.Reportables.Add(new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given)); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Reported_exceptions_should_not_be_duplicated_up_the_reporting_chain(IActor actor, - IPerformable performable, - IPerformable childPerformable, - string id, - string name, - string feature, - Exception error) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Success **** -Given Joe does a thing - Joe does a different thing - FAILED with an exception: -{error.ToString()} -"; - - Mock.Get(performable).Setup(x => x.GetReport(actor)).Returns("Joe does a thing"); - Mock.Get(childPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does a different thing"); - - var scenario = new Models.Scenario(id, name, feature) { Outcome = true }; - var parentPerformance = new Performance(actor, - PerformanceOutcome.FailureWithException, - performable, - PerformanceType.Given, - exception: error); - var childPerformance = new Performance(actor, - PerformanceOutcome.FailureWithException, - childPerformable, - PerformanceType.Given, - exception: error); - parentPerformance.Reportables.Add(childPerformance); - scenario.Reportables.Add(parentPerformance); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Feature_name_is_omitted_if_not_provided(IActor actor, - IPerformable performable, - string id, - string name) - { - // Arrange - var expected = $@" -Scenario: {name} -**** Success **** -Given Joe does a thing -"; - - Mock.Get(performable) - .Setup(x => x.GetReport(actor)) - .Returns("Joe does a thing"); - - var scenario = new Models.Scenario(id, name, null) { Outcome = true }; - scenario.Reportables.Add(new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given)); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Scenario_id_is_used_if_name_if_omitted(IActor actor, - IPerformable performable, - string id, - string feature) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {id} -**** Success **** -Given Joe does a thing -"; - - Mock.Get(performable) - .Setup(x => x.GetReport(actor)) - .Returns("Joe does a thing"); - - var scenario = new Models.Scenario(id, null, feature) { Outcome = true }; - scenario.Reportables.Add(new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given)); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Can_create_report_with_two_nested_performances(IActor actor, - IPerformable performable, - IPerformable childPerformable, - string id, - string name, - string feature) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Success **** -Given Joe does a thing - Joe does a different thing -"; - - Mock.Get(performable).Setup(x => x.GetReport(actor)).Returns("Joe does a thing"); - Mock.Get(childPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does a different thing"); - - var scenario = new Models.Scenario(id, name, feature) { Outcome = true }; - var parentPerformance = new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given); - parentPerformance.Reportables.Add(new Performance(actor, PerformanceOutcome.Success, childPerformable, PerformanceType.Given)); - scenario.Reportables.Add(parentPerformance); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Can_create_report_with_three_nested_performances(IActor actor, - IPerformable performable, - IPerformable childPerformable, - IPerformable grandChildPerformable, - string id, - string name, - string feature) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Success **** -Given Joe does a thing - Joe does a different thing - Joe does a totally different thing -"; - - Mock.Get(performable).Setup(x => x.GetReport(actor)).Returns("Joe does a thing"); - Mock.Get(childPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does a different thing"); - Mock.Get(grandChildPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does a totally different thing"); - - var scenario = new Models.Scenario(id, name, feature) { Outcome = true }; - var parentPerformance = new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given); - var childPerformance = new Performance(actor, PerformanceOutcome.Success, childPerformable, PerformanceType.Given); - var grandchildPerformance = new Performance(actor, PerformanceOutcome.Success, grandChildPerformable, PerformanceType.Given); - parentPerformance.Reportables.Add(childPerformance); - childPerformance.Reportables.Add(grandchildPerformance); - scenario.Reportables.Add(parentPerformance); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - - [Test,AutoMoqData] - public void Can_create_report_with_complex_nested_performances(IActor actor, - IPerformable performable, - IPerformable childPerformable, - IPerformable grandChildPerformable, - IPerformable siblingPerformable, - IPerformable secondPerformable, - string id, - string name, - string feature) - { - // Arrange - var expected = $@" -Feature: {feature} -Scenario: {name} -**** Success **** -Given Joe does a thing - Joe does a different thing - Joe does a totally different thing - Joe does an unrelated thing - When Joe takes some kind of action -"; - - Mock.Get(performable).Setup(x => x.GetReport(actor)).Returns("Joe does a thing"); - Mock.Get(childPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does a different thing"); - Mock.Get(grandChildPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does a totally different thing"); - Mock.Get(siblingPerformable).Setup(x => x.GetReport(actor)).Returns("Joe does an unrelated thing"); - Mock.Get(secondPerformable).Setup(x => x.GetReport(actor)).Returns("Joe takes some kind of action"); - - var scenario = new Models.Scenario(id, name, feature) { Outcome = true }; - var parentPerformance = new Performance(actor, PerformanceOutcome.Success, performable, PerformanceType.Given); - var childPerformance = new Performance(actor, PerformanceOutcome.Success, childPerformable, PerformanceType.Given); - var grandchildPerformance = new Performance(actor, PerformanceOutcome.Success, grandChildPerformable, PerformanceType.Given); - var siblingPerformance = new Performance(actor, PerformanceOutcome.Success, siblingPerformable, PerformanceType.Given); - var secondPerformance = new Performance(actor, PerformanceOutcome.Success, secondPerformable, PerformanceType.When); - parentPerformance.Reportables.Add(childPerformance); - parentPerformance.Reportables.Add(siblingPerformance); - childPerformance.Reportables.Add(grandchildPerformance); - scenario.Reportables.Add(parentPerformance); - scenario.Reportables.Add(secondPerformance); - var report = new Report(new [] { scenario }); - - // Act - var result = ExerciseSut(report); - - // Assert - Assert.That(result, Is.EqualTo(expected)); - } - } -} diff --git a/Tests/CSF.Screenplay.Reporting.Tests/packages.config b/Tests/CSF.Screenplay.Reporting.Tests/packages.config deleted file mode 100644 index 74426c78..00000000 --- a/Tests/CSF.Screenplay.Reporting.Tests/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Abilities/AddNumbers.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/Abilities/AddNumbers.cs deleted file mode 100644 index 8224cff0..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Abilities/AddNumbers.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using CSF.Screenplay.Abilities; - -namespace CSF.Screenplay.SpecFlow.Tests.Abilities -{ - public class AddNumbers : Ability - { - int current = 0; - - protected override string GetReport(Actors.INamed actor) => $"{actor.Name} is able to add numbers together"; - - public void Add(int number) - { - current += number; - } - - public void Set(int number) - { - current = number; - } - - public int GetTotal() => current; - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/AddTheNumber.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/AddTheNumber.cs deleted file mode 100644 index 736274bc..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/AddTheNumber.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.SpecFlow.Tests.Abilities; - -namespace CSF.Screenplay.SpecFlow.Tests.Actions -{ - public class AddTheNumber : Performable - { - int number; - - public AddTheNumber(int number) - { - this.number = number; - } - - protected override void PerformAs(IPerformer actor) - { - var ability = actor.GetAbility(); - ability.Add(number); - } - - protected override string GetReport(INamed actor) => $"{actor.Name} adds {number}"; - } - - public class Add - { - public static IPerformable TheNumber(int number) - { - return new AddTheNumber(number); - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/GetTheNumber.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/GetTheNumber.cs deleted file mode 100644 index 79cfbc34..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/GetTheNumber.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.SpecFlow.Tests.Abilities; - -namespace CSF.Screenplay.SpecFlow.Tests.Actions -{ - public class GetTheNumber : Question - { - protected override int PerformAs(IPerformer actor) - { - var ability = actor.GetAbility(); - return ability.GetTotal(); - } - - protected override string GetReport(INamed actor) => $"{actor.Name} reads the current number"; - } - - public class Get - { - public static IQuestion TheNumber() - { - return new GetTheNumber(); - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/StartWithTheNumber.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/StartWithTheNumber.cs deleted file mode 100644 index 066fb0e6..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Actions/StartWithTheNumber.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.SpecFlow.Tests.Abilities; - -namespace CSF.Screenplay.SpecFlow.Tests.Actions -{ - public class HasTheNumber : Performable - { - int number; - - public HasTheNumber(int number) - { - this.number = number; - } - - protected override void PerformAs(IPerformer actor) - { - var ability = actor.GetAbility(); - ability.Set(number); - } - - protected override string GetReport(INamed actor) => $"{actor.Name} has the number {number}"; - } - - public class StartWith - { - public static IPerformable TheNumber(int number) - { - return new HasTheNumber(number); - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/App.config b/Tests/CSF.Screenplay.SpecFlow.Tests/App.config deleted file mode 100644 index f1b35ea4..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/App.config +++ /dev/null @@ -1,12 +0,0 @@ - - - -
- - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/CSF.Screenplay.SpecFlow.Tests.csproj b/Tests/CSF.Screenplay.SpecFlow.Tests/CSF.Screenplay.SpecFlow.Tests.csproj deleted file mode 100644 index ed6d71e7..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/CSF.Screenplay.SpecFlow.Tests.csproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - Debug - AnyCPU - {7D3FE30F-56FD-4A79-B05B-CE0251159D3A} - Library - CSF.Screenplay.SpecFlow.Tests - CSF.Screenplay.SpecFlow.Tests - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - ..\..\packages\SpecFlow.2.2.0\lib\net45\TechTalk.SpecFlow.dll - - - ..\..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - - - SpecFlowSingleFileGenerator - Test.feature.cs - - - - - SpecFlowSingleFileGenerator - Stage.feature.cs - - - - - Test.feature - - - - - - - - - - Stage.feature - - - - - - {5FC41182-AE52-4324-BA3B-456DA91FE30C} - CSF.Screenplay.SpecFlow - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - {18010B4E-22A7-4462-B057-7199B3386D48} - CSF.Screenplay.Reporting - - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/ScenarioExtensions.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/ScenarioExtensions.cs deleted file mode 100644 index b7fae95f..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/ScenarioExtensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Scenarios; -using CSF.Screenplay.SpecFlow.Tests.Abilities; - -namespace CSF.Screenplay.SpecFlow.Tests -{ - public static class ScenarioExtensions - { - public static IActor GetMathsWhiz(this IScreenplayScenario context, string name) - { - var cast = context.Resolver.GetCast(); - if(cast == null) - { - var actor = new Actor(name, context.Identity); - CustomiseActor(actor, context); - return actor; - } - - return cast.Get(name, CustomiseActor, context); - } - - static void CustomiseActor(IActor actor, IScreenplayScenario context) - { - actor.IsAbleTo(); - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/ScreenplayConfig.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/ScreenplayConfig.cs deleted file mode 100644 index 00f9a887..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/ScreenplayConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using CSF.Screenplay.Integration; -using CSF.Screenplay.Reporting; -using CSF.Screenplay.SpecFlow; - -[assembly: ScreenplayAssembly(typeof(CSF.Screenplay.SpecFlow.Tests.ScreenplayConfig))] - -namespace CSF.Screenplay.SpecFlow.Tests -{ - public class ScreenplayConfig : IIntegrationConfig - { - public void Configure(IIntegrationConfigBuilder builder) - { - builder.UseCast(); - builder.UseStage(); - builder.UseReporting(config => { - config - .SubscribeToActorsCreatedInCast() - .WriteReport(report => { - var path = "SpecFlow.report.txt"; - TextReportWriter.WriteToFile(report, path); - }); - }); - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature b/Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature deleted file mode 100644 index d8ebb5c7..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature +++ /dev/null @@ -1,10 +0,0 @@ -Feature: The stage - In order to be able to use the passive voice within test - bindings, I want to be able to refer to actors by names such - as 'he' or 'she'. This requires a contextual storage of - an actor. - -Scenario: Store an actor in the stage - Given Joe is an actor in the spotlight - When I get the actor in the spotlight - Then that actor should be the same as Joe diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature.cs deleted file mode 100644 index dcdf0fff..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Stage.feature.cs +++ /dev/null @@ -1,85 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:1.9.0.77 -// SpecFlow Generator Version:2.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -namespace CSF.Screenplay.SpecFlow.Tests -{ - using TechTalk.SpecFlow; - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.0.0.0")] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [NUnit.Framework.TestFixtureAttribute()] - [NUnit.Framework.DescriptionAttribute("The stage")] - public partial class TheStageFeature - { - - private TechTalk.SpecFlow.ITestRunner testRunner; - -#line 1 "Stage.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"), "The stage", " In order to be able to use the passive voice within test\n bindings, I want to be able to refer to actors by names such\n as 'he' or 'she'. This requires a contextual storage of\n an actor.", ProgrammingLanguage.CSharp, ((string[])(null))); - testRunner.OnFeatureStart(featureInfo); - } - - [NUnit.Framework.TestFixtureTearDownAttribute()] - public virtual void FeatureTearDown() - { - testRunner.OnFeatureEnd(); - testRunner = null; - } - - [NUnit.Framework.SetUpAttribute()] - public virtual void TestInitialize() - { - } - - [NUnit.Framework.TearDownAttribute()] - public virtual void ScenarioTearDown() - { - testRunner.OnScenarioEnd(); - } - - public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) - { - testRunner.OnScenarioStart(scenarioInfo); - } - - public virtual void ScenarioCleanup() - { - testRunner.CollectScenarioErrors(); - } - - [NUnit.Framework.TestAttribute()] - [NUnit.Framework.DescriptionAttribute("Store an actor in the stage")] - public virtual void StoreAnActorInTheStage() - { - TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Store an actor in the stage", ((string[])(null))); -#line 7 -this.ScenarioSetup(scenarioInfo); -#line 8 - testRunner.Given("Joe is an actor in the spotlight", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); -#line 9 - testRunner.When("I get the actor in the spotlight", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); -#line 10 - testRunner.Then("that actor should be the same as Joe", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); -#line hidden - this.ScenarioCleanup(); - } - } -} -#pragma warning restore -#endregion diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/StageSteps.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/StageSteps.cs deleted file mode 100644 index 723fbcbb..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/StageSteps.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using CSF.Screenplay.Actors; -using NUnit.Framework; -using TechTalk.SpecFlow; - -namespace CSF.Screenplay.SpecFlow.Tests -{ - [Binding] - public class StageSteps - { - readonly IScreenplayScenario ctx; - IActor retrievedActor; - - [Given("Joe is an actor in the spotlight")] - public void GivenJoeIsAnActorInTheSpotlight() - { - var joe = ctx.CreateActor("Joe"); - var cast = ctx.GetCast(); - cast.Add(joe); - - var stage = ctx.GetStage(); - stage.ShineTheSpotlightOn(joe); - } - - [When("I get the actor in the spotlight")] - public void WhenIGetTheActorInTheSpotlight() - { - var stage = ctx.GetStage(); - retrievedActor = stage.GetTheActorInTheSpotlight(); - } - - [Then("that actor should be the same as Joe")] - public void ThenThatActorShouldBeJoe() - { - var joe = ctx.GetCast().GetExisting("Joe"); - Assert.That(retrievedActor, Is.SameAs(joe)); - } - - public StageSteps(IScreenplayScenario ctx) - { - if(ctx == null) - throw new ArgumentNullException(nameof(ctx)); - - this.ctx = ctx; - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature b/Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature deleted file mode 100644 index 5bee48c7..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature +++ /dev/null @@ -1,15 +0,0 @@ -Feature: Addition - In order to avoid silly mistakes - As a math idiot - I want to keep a running count of numbers - -Scenario: Add two numbers - Given Joe has the number 50 - When Joe adds 70 - Then Joe should see the total 120 - -Scenario: Add three numbers - Given Joe has the number 50 - And Joe adds 20 - When Joe adds 70 - Then Joe should see the total 140 diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature.cs deleted file mode 100644 index f758a444..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/Test.feature.cs +++ /dev/null @@ -1,104 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:1.9.0.77 -// SpecFlow Generator Version:2.0.0.0 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ -#region Designer generated code -#pragma warning disable -namespace CSF.Screenplay.SpecFlow.Tests -{ - using TechTalk.SpecFlow; - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.0.0.0")] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [NUnit.Framework.TestFixtureAttribute()] - [NUnit.Framework.DescriptionAttribute("Addition")] - public partial class AdditionFeature - { - - private TechTalk.SpecFlow.ITestRunner testRunner; - -#line 1 "Test.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 avoid silly mistakes\n As a math idiot\n I want to keep a running count of numbers", ProgrammingLanguage.CSharp, ((string[])(null))); - testRunner.OnFeatureStart(featureInfo); - } - - [NUnit.Framework.TestFixtureTearDownAttribute()] - public virtual void FeatureTearDown() - { - testRunner.OnFeatureEnd(); - testRunner = null; - } - - [NUnit.Framework.SetUpAttribute()] - public virtual void TestInitialize() - { - } - - [NUnit.Framework.TearDownAttribute()] - public virtual void ScenarioTearDown() - { - testRunner.OnScenarioEnd(); - } - - public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) - { - testRunner.OnScenarioStart(scenarioInfo); - } - - public virtual void ScenarioCleanup() - { - testRunner.CollectScenarioErrors(); - } - - [NUnit.Framework.TestAttribute()] - [NUnit.Framework.DescriptionAttribute("Add two numbers")] - public virtual void AddTwoNumbers() - { - TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Add two numbers", ((string[])(null))); -#line 6 -this.ScenarioSetup(scenarioInfo); -#line 7 - testRunner.Given("Joe has the number 50", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); -#line 8 - testRunner.When("Joe adds 70", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); -#line 9 - testRunner.Then("Joe should see the total 120", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); -#line hidden - this.ScenarioCleanup(); - } - - [NUnit.Framework.TestAttribute()] - [NUnit.Framework.DescriptionAttribute("Add three numbers")] - public virtual void AddThreeNumbers() - { - TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Add three numbers", ((string[])(null))); -#line 11 -this.ScenarioSetup(scenarioInfo); -#line 12 - testRunner.Given("Joe has the number 50", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); -#line 13 - testRunner.And("Joe adds 20", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); -#line 14 - testRunner.When("Joe adds 70", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); -#line 15 - testRunner.Then("Joe should see the total 140", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); -#line hidden - this.ScenarioCleanup(); - } - } -} -#pragma warning restore -#endregion diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/TestSteps.cs b/Tests/CSF.Screenplay.SpecFlow.Tests/TestSteps.cs deleted file mode 100644 index 4ac191da..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/TestSteps.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using static CSF.Screenplay.StepComposer; - -using TechTalk.SpecFlow; -using CSF.Screenplay.SpecFlow.Tests.Actions; -using NUnit.Framework; - -namespace CSF.Screenplay.SpecFlow.Tests -{ - [Binding] - public class TestSteps - { - readonly IScreenplayScenario ctx; - - [Given(@"([^ ]+) has the number (-?\d+)")] - public void GivenJoeStartsWithTheNumber(string actorName, int number) - { - var joe = ctx.GetMathsWhiz(actorName); - - Given(joe).WasAbleTo(StartWith.TheNumber(number)); - } - - [Given(@"([^ ]+) adds (-?\d+)")] - public void GivenJoeAdded(string actorName, int number) - { - var joe = ctx.GetMathsWhiz(actorName); - - Given(joe).WasAbleTo(Add.TheNumber(number)); - } - - [When(@"([^ ]+) adds (-?\d+)")] - public void WhenJoeAdds(string actorName, int number) - { - var joe = ctx.GetMathsWhiz(actorName); - - When(joe).AttemptsTo(Add.TheNumber(number)); - } - - [Then(@"([^ ]+) should see the total (-?\d+)")] - public void ThenJoeShouldSeeTheResult(string actorName, int number) - { - var joe = ctx.GetMathsWhiz(actorName); - - var result = Then(joe).ShouldSee(Get.TheNumber()); - Assert.That(result, Is.EqualTo(number)); - } - - public TestSteps(IScreenplayScenario context) - { - if(context == null) - throw new ArgumentNullException(nameof(context)); - - ctx = context; - } - } -} diff --git a/Tests/CSF.Screenplay.SpecFlow.Tests/packages.config b/Tests/CSF.Screenplay.SpecFlow.Tests/packages.config deleted file mode 100644 index 4e7df851..00000000 --- a/Tests/CSF.Screenplay.SpecFlow.Tests/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Tests/Abilities/AbilityStoreTests.cs b/Tests/CSF.Screenplay.Tests/Abilities/AbilityStoreTests.cs deleted file mode 100644 index ac6f9d6f..00000000 --- a/Tests/CSF.Screenplay.Tests/Abilities/AbilityStoreTests.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using NUnit.Framework; -using CSF.Screenplay.Abilities; - -namespace CSF.Screenplay.Tests.Abilities -{ - [TestFixture,Parallelizable(ParallelScope.All)] - public class AbilityStoreTests - { - [Test] - public void Add_ability_by_type_successfully_adds_an_ability() - { - // Arrange - var sut = GetSut(); - - // Act - sut.Add(typeof(SampleAbility)); - - // Assert - Assert.That(() => sut.HasAbility()); - } - - [Test] - public void Add_ability_by_type_which_is_not_an_ability_raises_an_exception() - { - // Arrange - var sut = GetSut(); - - // Act & assert - Assert.That(() => sut.Add(typeof(NotAnAbility)), Throws.ArgumentException); - } - - [Test] - public void Add_ability_by_instance_successfully_adds_an_ability() - { - // Arrange - var sut = GetSut(); - - // Act - sut.Add(new SampleAbility()); - - // Assert - Assert.That(() => sut.HasAbility()); - } - - [Test] - public void GetAbility_can_get_ability_added_by_type() - { - // Arrange - var sut = GetSut(); - sut.Add(typeof(SampleAbility)); - - // Act - var result = sut.GetAbility(); - - // Assert - Assert.That(result, Is.Not.Null, "Result is not null"); - Assert.That(result, Is.InstanceOf(), "Result is an instance of sample ability"); - } - - [Test] - public void GetAbility_can_get_ability_added_by_instance() - { - // Arrange - var sut = GetSut(); - var ability = new SampleAbility(); - sut.Add(ability); - - // Act - var result = sut.GetAbility(); - - // Assert - Assert.That(result, Is.SameAs(ability)); - } - - [Test] - public void GetAbility_returns_null_for_an_ability_which_was_not_added() - { - // Arrange - var sut = GetSut(); - - // Act - var result = sut.GetAbility(); - - // Assert - Assert.That(result, Is.Null); - } - - IAbilityStore GetSut() => new AbilityStore(); - - class SampleAbility : Ability {} - - class NotAnAbility {} - } -} diff --git a/Tests/CSF.Screenplay.Tests/Actors/ActorTests.cs b/Tests/CSF.Screenplay.Tests/Actors/ActorTests.cs deleted file mode 100644 index 03c835f1..00000000 --- a/Tests/CSF.Screenplay.Tests/Actors/ActorTests.cs +++ /dev/null @@ -1,287 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using CSF.Screenplay.Abilities; -using CSF.Screenplay.Actors; -using CSF.Screenplay.Performables; -using CSF.Screenplay.Reporting; -using Moq; -using NUnit.Framework; - -namespace CSF.Screenplay.Tests.Actors -{ - [TestFixture,Parallelizable(ParallelScope.All)] - public class ActorTests - { - [Test] - public void Perform_executes_void_action() - { - // Arrange - var performer = CreateActor(); - var action = Mock.Of(); - - // Act - performer.Perform(action); - - // Assert - Mock.Get(action).Verify(x => x.PerformAs(performer), Times.Once()); - } - - [Test] - public void Perform_executes_non_void_action() - { - // Arrange - var performer = CreateActor(); - var action = Mock.Of>(); - - // Act - performer.Perform(action); - - // Assert - Mock.Get(action).Verify(x => x.PerformAs(performer), Times.Once()); - } - - [Test] - public void Perform_void_action_reports_beginning() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.BeginPerformance += (sender, e) => triggered = true; - var action = Mock.Of(); - - // Act - performer.Perform(action); - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void Perform_void_action_reports_success_when_action_is_ok() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.EndPerformance += (sender, e) => triggered = true; - var action = Mock.Of(); - - // Act - performer.Perform(action); - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void Perform_void_action_reports_failure_when_action_raises_exception() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.PerformanceFailed += (sender, e) => triggered = true; - var action = Mock.Of(); - Mock.Get(action) - .Setup(x => x.PerformAs(performer)) - .Throws(); - - // Act - try - { - performer.Perform(action); - } - catch(InvalidOperationException) { } - - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void Perform_non_void_action_reports_beginning() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.BeginPerformance += (sender, e) => triggered = true; - var action = Mock.Of>(); - - // Act - performer.Perform(action); - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void Perform_non_void_action_reports_success_when_action_is_ok() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.EndPerformance += (sender, e) => triggered = true; - var action = Mock.Of>(); - - // Act - performer.Perform(action); - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void Perform_non_void_action_reports_result_when_action_is_ok() - { - // Arrange - var triggered = false; - object result = null; - var performer = CreateActor(); - performer.PerformanceResult += (sender, e) => { - triggered = true; - result = e.Result; - }; - var action = Mock.Of>(x => x.PerformAs(performer) == "foo"); - - // Act - performer.Perform(action); - - // Assert - Assert.IsTrue(triggered); - Assert.AreEqual("foo", result); - } - - [Test] - public void Perform_non_void_action_reports_failure_when_action_raises_exception() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.PerformanceFailed += (sender, e) => triggered = true; - var action = Mock.Of>(); - Mock.Get(action) - .Setup(x => x.PerformAs(performer)) - .Throws(); - - // Act - try - { - performer.Perform(action); - } - catch(InvalidOperationException) { } - - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void HasAbility_returns_true_when_the_ability_is_possessed() - { - // Arrange - var ability = Mock.Of(); - var performer = CreateActor(ability); - - // Act - var result = performer.HasAbility(); - - // Assert - Assert.IsTrue(result); - } - - [Test] - public void GainedAbility_reports_gaining_an_ability() - { - // Arrange - var triggered = false; - var performer = CreateActor(); - performer.GainedAbility += (sender, e) => triggered = true; - - // Act - performer.IsAbleTo(Mock.Of()); - - // Assert - Assert.IsTrue(triggered); - } - - [Test] - public void SupportsAction_returns_false_when_the_ability_is_not_possessed() - { - // Arrange - var performer = CreateActor(); - - // Act - var result = performer.HasAbility(); - - // Assert - Assert.IsFalse(result); - } - - [Test] - public void GetAbility_returns_instance_when_the_ability_is_possessed() - { - // Arrange - var ability = Mock.Of(); - var performer = CreateActor(ability); - - // Act - var result = performer.GetAbility(); - - // Assert - Assert.AreSame(ability, result); - } - - [Test] - public void GetAbility_throws_exception_when_the_ability_is_not_possessed() - { - // Arrange - var performer = CreateActor(); - - // Act & assert - Assert.Throws(() => performer.GetAbility()); - } - - [Test] - public void Perform_may_be_used_generically() - { - // Arrange - var actor = CreateActor(); - var performed = false; - - actor.BeginPerformance += (sender, e) => performed = true; - - // Act - actor.Perform(); - - // Assert - Assert.That(performed, Is.True); - } - - IActor CreateActor(IAbility ability, string name = null) - { - return CreateActor(new [] { ability }, name); - } - - IActor CreateActor(IEnumerable abilities = null, string name = null) - { - abilities = abilities?? Enumerable.Empty(); - name = name?? "Joe"; - - var performer = new Actor(name, Guid.NewGuid()); - foreach(var ability in abilities) - { - performer.IsAbleTo(ability); - } - return performer; - } - - public class SampleAbility : Ability {} - - public class SampleAction : Performable - { - protected override void PerformAs(IPerformer actor) - { - // Intentional no-op - } - } - } -} diff --git a/Tests/CSF.Screenplay.Tests/Actors/CastTests.cs b/Tests/CSF.Screenplay.Tests/Actors/CastTests.cs deleted file mode 100644 index 70b26d0e..00000000 --- a/Tests/CSF.Screenplay.Tests/Actors/CastTests.cs +++ /dev/null @@ -1,266 +0,0 @@ -using System; -using NUnit.Framework; -using CSF.Screenplay.Actors; -using Moq; -using CSF.Screenplay.Scenarios; - -namespace CSF.Screenplay.Tests.Actors -{ - [TestFixture,Parallelizable(ParallelScope.All)] - public class CastTests - { - [Test] - public void Add_using_name_sets_actors_name() - { - // Arrange - var cast = GetSut(); - var name = "joe"; - - // Act - cast.Add(name, Guid.NewGuid()); - var joe = cast.GetExisting(name); - - // Assert - Assert.AreEqual(name, joe.Name); - } - - [Test] - public void Add_using_guid_sets_scenario_identity() - { - // Arrange - var cast = GetSut(); - var name = "joe"; - var identity = Guid.NewGuid(); - - // Act - cast.Add(name, identity); - var joe = cast.GetExisting(name); - - // Assert - Assert.AreEqual(identity, joe.ScenarioIdentity); - } - - [Test] - public void Add_using_name_raises_exception_if_used_twice_with_same_name() - { - // Arrange - var cast = GetSut(); - var name = "joe"; - - // Act - cast.Add(name, Guid.NewGuid()); - - // Act and assert - Assert.Throws(() => cast.Add(name, Guid.NewGuid())); - } - - [Test] - public void Add_using_name_does_not_raise_exception_if_used_twice_with_different_names() - { - // Arrange - var cast = GetSut(); - - // Act - cast.Add("joe", Guid.NewGuid()); - cast.Add("davina", Guid.NewGuid()); - - // Act and assert - Assert.Pass(); - } - - [Test] - public void GetExisting_returns_null_for_nonexistent_actors() - { - // Arrange - var cast = GetSut(); - - // Act - var joe = cast.GetExisting("joe"); - - // Assert - Assert.IsNull(joe); - } - - [Test] - public void GetExisting_returns_instance_for_created_actor() - { - // Arrange - var cast = GetSut(); - var name = "joe"; - cast.Add(name, Guid.NewGuid()); - - // Act - var joe = cast.GetExisting(name); - - // Assert - Assert.NotNull(joe); - } - - [Test] - public void Get_creates_new_actor_if_they_do_not_exist() - { - // Arrange - var cast = GetSut(); - - // Act - var joe = cast.Get("joe", (actor, scenario) => {}, Mock.Of(x => x.Identity == Guid.NewGuid())); - - // Assert - Assert.That(joe, Is.Not.Null); - } - - [Test] - public void Get_assigns_scenario_identity_to_created_actor() - { - // Arrange - var cast = GetSut(); - var identity = Guid.NewGuid(); - var scenario = Mock.Of(x => x.Identity == identity); - - // Act - var joe = cast.Get("joe", (a, s) => {}, scenario); - - // Assert - Assert.That(joe.ScenarioIdentity, Is.EqualTo(identity)); - } - - [Test] - public void Get_returns_same_actor_if_called_twice() - { - // Arrange - var cast = GetSut(); - - // Act - var joe = cast.Get("joe", (actor, scenario) => {}, Mock.Of(x => x.Identity == Guid.NewGuid())); - var joeAgain = cast.Get("joe", (actor, scenario) => {}, Mock.Of(x => x.Identity == Guid.NewGuid())); - - // Assert - Assert.That(joe, Is.SameAs(joeAgain)); - } - - [Test] - public void Get_returns_existing_actor_if_they_already_exist() - { - // Arrange - var cast = GetSut(); - cast.Add("joe", Guid.NewGuid()); - var joe = cast.GetExisting("joe"); - - // Act - var joeAgain = cast.Get("joe", (actor, scenario) => {}, Mock.Of()); - - // Assert - Assert.That(joeAgain, Is.SameAs(joe)); - } - - [Test] - public void Get_applies_scenario_customisation_if_creating_a_new_actor() - { - // Arrange - var cast = GetSut(); - var customisationCallCount = 0; - - // Act - cast.Get("joe", (a, s) => customisationCallCount++, Mock.Of(x => x.Identity == Guid.NewGuid())); - - // Assert - Assert.That(customisationCallCount, Is.EqualTo(1)); - } - - [Test] - public void Get_does_not_apply_scenario_customisation_if_actor_already_exists() - { - // Arrange - var cast = GetSut(); - cast.Add("joe", Guid.NewGuid()); - var customisationCallCount = 0; - - // Act - cast.Get("joe", (a, s) => customisationCallCount++, Mock.Of()); - - // Assert - Assert.That(customisationCallCount, Is.EqualTo(0)); - } - - [Test] - public void GetAll_returns_all_created_actors() - { - // Arrange - var cast = GetSut(); - cast.Add("joe", Guid.NewGuid()); - cast.Add("davina", Guid.NewGuid()); - - var joe = cast.GetExisting("joe"); - var davina = cast.GetExisting("davina"); - - // Act - var all = cast.GetAll(); - - // Assert - Assert.That(all, Is.EquivalentTo(new [] { joe, davina })); - } - - [Test] - public void Dismiss_removes_all_actors() - { - // Arrange - var cast = GetSut(); - cast.Add("joe", Guid.NewGuid()); - cast.Add("davina", Guid.NewGuid()); - - // Act - cast.Dismiss(); - - // Assert - var all = cast.GetAll(); - Assert.That(all, Is.Empty); - } - - [Test] - public void Add_adds_the_actor() - { - // Arrange - var cast = GetSut(); - var name = "joe"; - var joe = new Actor(name, Guid.NewGuid()); - - // Act - cast.Add(joe); - var joeClone = cast.GetExisting(name); - - // Assert - Assert.NotNull(joeClone); - Assert.AreSame(joe, joeClone); - } - - [Test] - public void Add_raises_exception_if_used_twice_with_same_name() - { - // Arrange - var cast = GetSut(); - var name = "joe"; - var joe = new Actor(name, Guid.NewGuid()); - - // Act - cast.Add(joe); - - // Act and assert - Assert.Throws(() => cast.Add(joe)); - } - - [Test] - public void Add_does_not_raise_exception_if_used_twice_with_different_names() - { - // Arrange - var cast = GetSut(); - var joe = new Actor("joe", Guid.NewGuid()); - var davina = new Actor("davina", Guid.NewGuid()); - - // Act - cast.Add(joe); - Assert.That(() => cast.Add(davina), Throws.Nothing); - } - - ICast GetSut() => new Cast(); - } -} diff --git a/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj b/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj deleted file mode 100644 index d60b652c..00000000 --- a/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj +++ /dev/null @@ -1,64 +0,0 @@ - - - - Debug - AnyCPU - {B6273A66-8B2A-47C0-A982-F94E6BEA79F8} - Library - CSF.Screenplay.Tests - CSF.Screenplay.Tests - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - - ..\..\packages\Moq.4.7.25\lib\net45\Moq.dll - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - ..\..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - - - - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Tests/Integration/ScreenplayIntegrationTests.cs b/Tests/CSF.Screenplay.Tests/Integration/ScreenplayIntegrationTests.cs deleted file mode 100644 index b96366af..00000000 --- a/Tests/CSF.Screenplay.Tests/Integration/ScreenplayIntegrationTests.cs +++ /dev/null @@ -1,238 +0,0 @@ -using NUnit.Framework; -using System; -using CSF.Screenplay.Integration; -using Moq; -using CSF.Screenplay.Scenarios; -using System.Collections.Generic; -using System.Linq; -using CSF.FlexDi; - -namespace CSF.Screenplay.Tests.Integration -{ - [TestFixture,Parallelizable(ParallelScope.All)] - public class ScreenplayIntegrationTests - { - [Test] - public void BeforeExecutingFirstScenario_executes_before_callbacks() - { - // Arrange - var called = false; - Action callback = (arg1, arg2) => called = true; - - var builder = GetBuilder(); - Mock.Get(builder) - .SetupGet(x => x.BeforeFirstScenario) - .Returns(new [] {callback}); - var sut = GetSut(builder: builder); - - // Act - sut.BeforeExecutingFirstScenario(); - - // Assert - Assert.That(called, Is.True, "Callback should have been invoked"); - } - - [Test] - public void BeforeExecutingFirstScenario_raises_begin_test_run_event() - { - var eventReceived = false; - Action callback = (arg1, arg2) => { - arg1.BeginTestRun += (sender, e) => eventReceived = true; - }; - - var builder = GetBuilder(); - Mock.Get(builder) - .SetupGet(x => x.BeforeFirstScenario) - .Returns(new [] {callback}); - var sut = GetSut(builder: builder); - - // Act - sut.BeforeExecutingFirstScenario(); - - // Assert - Assert.That(eventReceived, Is.True, "Event should have been raised"); - } - - [Test] - public void BeforeScenario_executes_before_callbacks() - { - // Arrange - var called = false; - Action callback = (arg1) => called = true; - - var builder = GetBuilder(); - Mock.Get(builder) - .SetupGet(x => x.BeforeScenario) - .Returns(new [] {callback}); - var sut = GetSut(builder: builder); - var scenario = GetScenario(); - - // Act - sut.BeforeScenario(scenario); - - // Assert - Assert.That(called, Is.True, "Callback should have been invoked"); - } - - [Test] - public void BeforeScenario_executes_begin_scenario_method() - { - // Arrange - var sut = GetSut(); - var scenario = GetScenario(); - - // Act - sut.BeforeScenario(scenario); - - // Assert - Mock.Get(scenario) - .As() - .Verify(x => x.Begin(), Times.Once()); - } - - [Test] - public void AfterScenario_executes_after_callbacks() - { - // Arrange - var called = false; - Action callback = (arg1) => called = true; - - var builder = GetBuilder(); - Mock.Get(builder) - .SetupGet(x => x.AfterScenario) - .Returns(new [] {callback}); - var sut = GetSut(builder: builder); - var scenario = GetScenario(); - - // Act - sut.AfterScenario(scenario, true); - - // Assert - Assert.That(called, Is.True, "Callback should have been invoked"); - } - - [Test] - public void AfterScenario_disposes_the_scenario() - { - // Arrange - var sut = GetSut(); - var scenario = GetScenario(); - - // Act - sut.AfterScenario(scenario, true); - - // Assert - Mock.Get(scenario).Verify(x => x.Dispose(), Times.Once()); - } - - [Theory] - public void AfterScenario_executes_end_scenario_method_with_success(bool success) - { - // Arrange - var sut = GetSut(); - var scenario = GetScenario(); - - // Act - sut.AfterScenario(scenario, success); - - // Assert - Mock.Get(scenario) - .As() - .Verify(x => x.End(success), Times.Once()); - } - - [Test] - public void AfterExecutedLastScenario_executes_after_callbacks() - { - // Arrange - var called = false; - Action callback = (arg1) => called = true; - - var builder = GetBuilder(); - Mock.Get(builder) - .SetupGet(x => x.AfterLastScenario) - .Returns(new [] {callback}); - var sut = GetSut(builder: builder); - - // Act - sut.AfterExecutedLastScenario(); - - // Assert - Assert.That(called, Is.True, "Callback should have been invoked"); - } - - [Test] - public void AfterExecutedLastScenario_raises_end_test_run_event() - { - var eventReceived = false; - Action callback = (arg1, arg2) => { - arg1.CompleteTestRun += (sender, e) => eventReceived = true; - }; - - var builder = GetBuilder(); - Mock.Get(builder) - .SetupGet(x => x.BeforeFirstScenario) - .Returns(new [] {callback}); - var sut = GetSut(builder: builder); - sut.BeforeExecutingFirstScenario(); - - // Act - sut.AfterExecutedLastScenario(); - - // Assert - Assert.That(eventReceived, Is.True, "Event should have been raised"); - } - - [Test] - public void AfterExecutedLastScenario_releases_singleton_services() - { - // Arrange - var container = Mock.Of(); - var sut = GetSut(container: container); - - // Act - sut.AfterExecutedLastScenario(); - - // Assert - Mock.Get(container).Verify(x => x.Dispose(), Times.Once()); - } - - IScreenplayIntegration GetSut(IIntegrationConfigBuilder builder = null, IContainer container = null) - => new ScreenplayIntegration(builder ?? GetBuilder(), container); - - IIntegrationConfigBuilder GetBuilder() - { - var builder = new Mock(); - - builder - .SetupGet(x => x.BeforeFirstScenario) - .Returns(Enumerable.Empty>().ToArray()); - - builder - .SetupGet(x => x.BeforeScenario) - .Returns(Enumerable.Empty>().ToArray()); - - builder - .SetupGet(x => x.AfterLastScenario) - .Returns(Enumerable.Empty>().ToArray()); - - builder - .SetupGet(x => x.AfterScenario) - .Returns(Enumerable.Empty>().ToArray()); - - var registrations = new ServiceRegistrations(); - builder - .SetupGet(x => x.ServiceRegistrations) - .Returns(registrations); - - return builder.Object; - } - - IScreenplayScenario GetScenario() - { - var scenario = new Mock(); - scenario.As(); - return scenario.Object; - } - } -} diff --git a/Tests/CSF.Screenplay.Tests/packages.config b/Tests/CSF.Screenplay.Tests/packages.config deleted file mode 100644 index 461a36aa..00000000 --- a/Tests/CSF.Screenplay.Tests/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Tests/CSF.WebDriverFactory.Tests/App.config b/Tests/CSF.WebDriverFactory.Tests/App.config deleted file mode 100644 index 14671ec3..00000000 --- a/Tests/CSF.WebDriverFactory.Tests/App.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/Tests/CSF.WebDriverFactory.Tests/AutoMoqDataAttribute.cs b/Tests/CSF.WebDriverFactory.Tests/AutoMoqDataAttribute.cs deleted file mode 100644 index dd249a07..00000000 --- a/Tests/CSF.WebDriverFactory.Tests/AutoMoqDataAttribute.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.AutoMoq; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.WebDriverFactory.Tests -{ - public class AutoMoqDataAttribute : AutoDataAttribute - { - public AutoMoqDataAttribute() : base(new Fixture().Customize(new AutoMoqCustomization())) - { - } - } -} diff --git a/Tests/CSF.WebDriverFactory.Tests/CSF.WebDriverFactory.Tests.csproj b/Tests/CSF.WebDriverFactory.Tests/CSF.WebDriverFactory.Tests.csproj deleted file mode 100644 index 7e46ad99..00000000 --- a/Tests/CSF.WebDriverFactory.Tests/CSF.WebDriverFactory.Tests.csproj +++ /dev/null @@ -1,64 +0,0 @@ - - - - Debug - AnyCPU - {9A92340A-F3AA-445B-955D-DCF68B3580AC} - Library - CSF.WebDriverFactory.Tests - CSF.WebDriverFactory.Tests - v4.5 - 0.8.0-alpha - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - - - true - bin\Release - prompt - 4 - - - - - ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - - ..\..\packages\Moq.4.7.25\lib\net45\Moq.dll - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll - - - ..\..\packages\AutoFixture.3.50.3\lib\net40\Ploeh.AutoFixture.dll - - - ..\..\packages\AutoFixture.AutoMoq.3.50.3\lib\net40\Ploeh.AutoFixture.AutoMoq.dll - - - ..\..\packages\AutoFixture.NUnit3.3.50.3\lib\net40\Ploeh.AutoFixture.NUnit3.dll - - - - - - - - - - - - - {C99466AD-CA21-4C12-9E05-6730CDC3C031} - CSF.WebDriverFactory - - - - \ No newline at end of file diff --git a/Tests/CSF.WebDriverFactory.Tests/ConfigurationWebDriverFactoryProviderTests.cs b/Tests/CSF.WebDriverFactory.Tests/ConfigurationWebDriverFactoryProviderTests.cs deleted file mode 100644 index b75e7c97..00000000 --- a/Tests/CSF.WebDriverFactory.Tests/ConfigurationWebDriverFactoryProviderTests.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using CSF.WebDriverFactory.Config; -using CSF.WebDriverFactory.Impl; -using Moq; -using NUnit.Framework; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.NUnit3; - -namespace CSF.WebDriverFactory.Tests -{ - [TestFixture,Parallelizable] - public class ConfigurationWebDriverFactoryProviderTests - { - [TestCase(typeof(ChromeWebDriverFactory))] - [TestCase(typeof(FirefoxGeckoDriverWebDriverFactory))] - [TestCase(typeof(InternetExplorerWebDriverFactory))] - [TestCase(typeof(RemoteWebDriverFactory))] - [TestCase(typeof(RemoteWebDriverFromEnvironmentFactory))] - public void GetFactory_gets_factory_of_appropriate_type(Type expectedType) - { - // Arrange - var config = GetConfig(expectedType); - var sut = new ConfigurationWebDriverFactoryProvider(config); - - // Act - var result = sut.GetFactory(); - - // Assert - Assert.IsInstanceOf(expectedType, result); - } - - [AutoData] - public void GetFactory_sets_CommandTimeoutSeconds_property(int commandTimeout) - { - // Arrange - var props = new Dictionary { - { nameof(ChromeWebDriverFactory.CommandTimeoutSeconds), commandTimeout.ToString() } - }; - var config = GetConfig(typeof(ChromeWebDriverFactory), props); - var sut = new ConfigurationWebDriverFactoryProvider(config); - - // Act - var result = (ChromeWebDriverFactory) sut.GetFactory(); - - // Assert - Assert.AreEqual(commandTimeout, result.CommandTimeoutSeconds); - } - - IWebDriverFactoryConfiguration GetConfig(Type factoryType, - IDictionary properties = null) - { - var config = Mock.Of(); - Mock.Get(config) - .Setup(x => x.GetFactoryType()) - .Returns(factoryType); - Mock.Get(config) - .Setup(x => x.GetFactoryProperties()) - .Returns(properties?? new Dictionary()); - return config; - } - } -} diff --git a/Tests/CSF.WebDriverFactory.Tests/packages.config b/Tests/CSF.WebDriverFactory.Tests/packages.config deleted file mode 100644 index 74426c78..00000000 --- a/Tests/CSF.WebDriverFactory.Tests/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file From 7fee16081935a2582d945ca7fda1d608b66ce229 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Mon, 5 Feb 2018 20:34:10 +0000 Subject: [PATCH 002/213] WIP #10 - Bulk rename and file reorganisation CSF.Screenplay.Web is now CSF.Screenplay.Selenium Also, the file/directory structure no longer needs to be so deep. --- .../Abilities/BrowseTheWebTests.cs | 0 .../Actions/ClearCookiesTests.cs | 0 .../Actions/ClearTests.cs | 0 .../Actions/ClickTests.cs | 0 .../Actions/DeselectTests.cs | 0 .../Actions/EnterTests.cs | 0 .../Actions/ExecuteScriptTests.cs | 0 .../Actions/OpenTests.cs | 0 .../Actions/SelectTests.cs | 0 .../Actions/TargetNotFoundTests.cs | 0 .../App.AppVeyor.config | 0 .../App.Travis.config | 0 .../App.config | 0 .../BrowserName.cs | 0 .../CSF.Screenplay.Selenium.Tests.csproj | 68 +++++----- .../IgnoreOn.cs | 0 .../NUnitIntegrationTests.cs | 0 .../Pages/GoogleHomePage.cs | 0 .../Pages/HomePage.cs | 0 .../Pages/PageThree.cs | 0 .../Pages/PageTwo.cs | 0 .../Questions/FindElementsTests.cs | 0 .../Questions/GetAttributeTests.cs | 0 .../Questions/GetCssValueTests.cs | 0 .../Questions/GetOptionsTests.cs | 0 .../Questions/GetTextTests.cs | 0 .../Questions/GetValueTests.cs | 0 .../Questions/GetWindowTitleTests.cs | 0 .../SauceConnectWebDriverFactory.cs | 0 .../ScenarioExtensions.cs | 0 .../ScreenplayConfig.cs | 11 +- .../ScreenplayScenarioAttribute.cs | 0 .../EnterTextIntoThePageTwoInputField.cs | 0 .../Tasks/EnterTheDateTests.cs | 0 .../Tasks/NavigateToNewPageByClickingTests.cs | 0 .../Waits/GeneralWaitTests.cs | 0 .../Waits/WaitUntilVisibleTests.cs | 0 .../packages.config | 7 + CSF.Screenplay.Selenium.sln | 38 ++++++ .../Abilities/BrowseTheWeb.cs | 0 .../Abilities/Capabilities.cs | 0 .../Abilities/IUriTransformer.cs | 0 .../Abilities/MissingCapabilityException.cs | 0 .../Abilities/NoOpUriTransformer.cs | 0 .../Abilities/RootUriPrependingTransformer.cs | 0 .../Actions/ClearCookies.cs | 0 .../Actions/ClearLocalStorage.cs | 0 .../Actions/ClearTheContents.cs | 0 .../Actions/Click.cs | 0 .../Actions/DeleteCookie.cs | 0 .../Actions/DeselectAll.cs | 0 .../Actions/DeselectByIndex.cs | 0 .../Actions/DeselectByText.cs | 0 .../Actions/DeselectByValue.cs | 0 .../Actions/Enter.cs | 0 .../Actions/ExecuteJavaScript.cs | 0 .../Actions/ExecuteJavaScriptAndGetResult.cs | 0 .../Actions/IActionDriver.cs | 0 .../Actions/Open.cs | 0 .../Actions/SelectActionDriver.cs | 0 .../Actions/SelectByIndex.cs | 0 .../Actions/SelectByText.cs | 0 .../Actions/SelectByValue.cs | 0 .../Actions/TargettedAction.cs | 0 .../Builders/Clear.cs | 0 .../Builders/ClearTheirBrowser.cs | 0 .../Builders/Click.cs | 0 .../Builders/Deselect.cs | 0 .../Builders/Elements.cs | 0 .../Builders/ElementsInThePageBody.cs | 0 .../Builders/ElementsWithin.cs | 0 .../Builders/Enter.cs | 0 .../Builders/Execute.cs | 0 .../Builders/Get.cs | 0 .../Builders/Matcher.cs | 0 .../Builders/Navigate.cs | 0 .../Builders/OpenTheirBrowserOn.cs | 0 .../Builders/Select.cs | 0 .../Builders/SelectStrategy.cs | 0 .../Builders/TheAttribute.cs | 0 .../Builders/TheCss.cs | 0 .../Builders/TheLocation.cs | 0 .../Builders/TheOptions.cs | 0 .../Builders/TheSize.cs | 0 .../Builders/TheText.cs | 0 .../Builders/TheValue.cs | 0 .../Builders/TheVisibility.cs | 0 .../Builders/TheWindow.cs | 0 .../Builders/Wait.cs | 0 .../CSF.Screenplay.Selenium.csproj | 25 ++-- .../CSF.Screenplay.Selenium.nuspec | 0 .../ElementMatching/AndMatcher.cs | 0 .../ElementMatching/IMatcher.cs | 0 .../ElementMatching/Matcher`1.cs | 0 .../ElementMatching/OrMatcher.cs | 0 .../Models/AppUri.cs | 0 .../Models/ClassName.cs | 0 .../Models/CssSelector.cs | 0 .../Models/DurationFormatter.cs | 0 .../Models/ElementCollection.cs | 0 .../Models/ElementId.cs | 0 .../Models/GeneralWaitBuilder.cs | 0 .../Models/GivenUpWaitingException.cs | 0 .../Models/IDurationFormatter.cs | 0 .../Models/IHasTargetName.cs | 0 .../Models/ILocatorBasedTarget.cs | 0 .../Models/IProvidesTimespan.cs | 0 .../Models/ITarget.cs | 0 .../Models/IUriProvider.cs | 0 .../Models/IWebElementAdapter.cs | 0 .../Models/InvalidTargetException.cs | 0 .../Models/Option.cs | 0 .../Models/Page.cs | 0 .../Models/PixelDistance.cs | 0 .../Models/Position.cs | 0 .../Models/SeleniumWebElementAdapter.cs | 0 .../Models/Size.cs | 0 .../Models/StringBasedTarget.cs | 0 .../Models/TargetNotFoundException.cs | 0 .../Models/TimespanBuilder.cs | 0 .../Models/TimespanBuilder`1.cs | 0 .../Models/TimespanWrapper.cs | 0 .../Models/XPath.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Queries/AttributeQuery.cs | 0 .../Queries/ClickableQuery.cs | 0 .../Queries/CssQuery.cs | 0 .../Queries/IQuery.cs | 0 .../Queries/IQuery`1.cs | 0 .../Queries/LocationQuery.cs | 0 .../Queries/OptionsQuery.cs | 0 .../Queries/Query.cs | 0 .../Queries/SelectedOptionsQuery.cs | 0 .../Queries/SizeQuery.cs | 0 .../Queries/TextQuery.cs | 0 .../Queries/TextQuery`1.cs | 0 .../Queries/ValueQuery.cs | 0 .../Queries/ValueQuery`1.cs | 0 .../Queries/VisibilityQuery.cs | 0 .../Questions/FindElements.cs | 0 .../Questions/FindElementsOnPage.cs | 0 .../Questions/GetElement.cs | 0 .../Questions/GetWindowTitle.cs | 0 .../Questions/Question.cs | 0 .../Questions/TargettedMultiQuestion`1.cs | 0 .../Questions/TargettedQuestion`1.cs | 0 .../Questions/TargettedVisibilityQuestion.cs | 0 .../Reporting/ElementCollectionFormatter.cs | 6 +- .../Reporting/OptionCollectionFormatter.cs | 12 +- .../Resources/Javascripts.Designer.cs | 0 .../Resources/Javascripts.resx | 0 .../Tasks/EnterADateBySettingTheValue.cs | 0 .../Tasks/EnterTheDate.cs | 0 .../EnterTheDateAsAnIsoFormattedString.cs | 0 .../EnterTheDateIntoAnHtml5InputTypeDate.cs | 0 .../Tasks/GetTheLocaleFormattedDate.cs | 0 .../Tasks/NavigateToNewPageByClicking.cs | 0 .../Waits/GeneralWait.cs | 0 .../Waits/ITargettedWait.cs | 0 .../Waits/TargettedWait.cs | 0 .../Waits/WaitForACondition.cs | 0 .../Waits/WaitUntilThePageLoads.cs | 0 ...WebBrowsingIntegrationBuilderExtensions.cs | 71 +++++----- .../packages.config | 4 + .../WebBrowsingResolverExtensions.cs | 28 ---- .../App_Start/RouteConfig.cs | 0 .../CSF.Screenplay.WebTestWebsite.csproj | 56 ++++---- .../Content/css/common.css | 0 .../Content/css/reset.css | 0 .../Controllers/ControllerBase.cs | 0 .../Controllers/HomeController.cs | 0 .../Controllers/PageThreeController.cs | 0 .../Controllers/PageTwoController.cs | 0 .../Global.asax | 0 .../Global.asax.cs | 0 .../Models/ModelBase.cs | 0 .../Scripts/PageThree.js | 0 .../Scripts/PageTwo.js | 0 .../Scripts/jquery-3.2.1.min.js | 0 .../Views/Home/Index.pt | 0 .../Views/PageThree/Index.pt | 0 .../Views/PageTwo/Index.pt | 0 .../Views/Shared/Footer.pt | 0 .../Views/Shared/Header.pt | 0 .../Views/Shared/Page.pt | 0 .../Views/Web.config | 0 .../Web.config | 3 +- .../packages.config | 0 CSF.Screenplay.sln | 122 ------------------ .../ApiControllers/DataController.cs | 35 ----- .../ApiControllers/ExecutionController.cs | 43 ------ .../Models/SampleApiData.cs | 12 -- 192 files changed, 172 insertions(+), 369 deletions(-) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Abilities/BrowseTheWebTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/ClearCookiesTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/ClearTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/ClickTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/DeselectTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/EnterTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/ExecuteScriptTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/OpenTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/SelectTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Actions/TargetNotFoundTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/App.AppVeyor.config (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/App.Travis.config (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/App.config (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/BrowserName.cs (100%) rename Tests/CSF.Screenplay.Web.Tests/CSF.Screenplay.Web.Tests.csproj => CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj (64%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/IgnoreOn.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/NUnitIntegrationTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Pages/GoogleHomePage.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Pages/HomePage.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Pages/PageThree.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Pages/PageTwo.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/FindElementsTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/GetAttributeTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/GetCssValueTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/GetOptionsTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/GetTextTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/GetValueTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Questions/GetWindowTitleTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/SauceConnectWebDriverFactory.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/ScenarioExtensions.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/ScreenplayConfig.cs (90%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/ScreenplayScenarioAttribute.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Tasks/EnterTextIntoThePageTwoInputField.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Tasks/EnterTheDateTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Tasks/NavigateToNewPageByClickingTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Waits/GeneralWaitTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/Waits/WaitUntilVisibleTests.cs (100%) rename {Tests/CSF.Screenplay.Web.Tests => CSF.Screenplay.Selenium.Tests}/packages.config (53%) create mode 100644 CSF.Screenplay.Selenium.sln rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Abilities/BrowseTheWeb.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Abilities/Capabilities.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Abilities/IUriTransformer.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Abilities/MissingCapabilityException.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Abilities/NoOpUriTransformer.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Abilities/RootUriPrependingTransformer.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/ClearCookies.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/ClearLocalStorage.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/ClearTheContents.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/Click.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/DeleteCookie.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/DeselectAll.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/DeselectByIndex.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/DeselectByText.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/DeselectByValue.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/Enter.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/ExecuteJavaScript.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/ExecuteJavaScriptAndGetResult.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/IActionDriver.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/Open.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/SelectActionDriver.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/SelectByIndex.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/SelectByText.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/SelectByValue.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Actions/TargettedAction.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Clear.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/ClearTheirBrowser.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Click.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Deselect.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Elements.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/ElementsInThePageBody.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/ElementsWithin.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Enter.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Execute.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Get.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Matcher.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Navigate.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/OpenTheirBrowserOn.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Select.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/SelectStrategy.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheAttribute.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheCss.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheLocation.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheOptions.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheSize.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheText.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheValue.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheVisibility.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/TheWindow.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Builders/Wait.cs (100%) rename CSF.Screenplay.Web/CSF.Screenplay.Web.csproj => CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj (91%) rename CSF.Screenplay.Web/CSF.Screenplay.Web.nuspec => CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.nuspec (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/ElementMatching/AndMatcher.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/ElementMatching/IMatcher.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/ElementMatching/Matcher`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/ElementMatching/OrMatcher.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/AppUri.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/ClassName.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/CssSelector.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/DurationFormatter.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/ElementCollection.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/ElementId.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/GeneralWaitBuilder.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/GivenUpWaitingException.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/IDurationFormatter.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/IHasTargetName.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/ILocatorBasedTarget.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/IProvidesTimespan.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/ITarget.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/IUriProvider.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/IWebElementAdapter.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/InvalidTargetException.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/Option.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/Page.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/PixelDistance.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/Position.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/SeleniumWebElementAdapter.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/Size.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/StringBasedTarget.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/TargetNotFoundException.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/TimespanBuilder.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/TimespanBuilder`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/TimespanWrapper.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Models/XPath.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Properties/AssemblyInfo.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/AttributeQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/ClickableQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/CssQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/IQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/IQuery`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/LocationQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/OptionsQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/Query.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/SelectedOptionsQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/SizeQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/TextQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/TextQuery`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/ValueQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/ValueQuery`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Queries/VisibilityQuery.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/FindElements.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/FindElementsOnPage.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/GetElement.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/GetWindowTitle.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/Question.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/TargettedMultiQuestion`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/TargettedQuestion`1.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Questions/TargettedVisibilityQuestion.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Reporting/ElementCollectionFormatter.cs (66%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Reporting/OptionCollectionFormatter.cs (70%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Resources/Javascripts.Designer.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Resources/Javascripts.resx (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Tasks/EnterADateBySettingTheValue.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Tasks/EnterTheDate.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Tasks/EnterTheDateAsAnIsoFormattedString.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Tasks/EnterTheDateIntoAnHtml5InputTypeDate.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Tasks/GetTheLocaleFormattedDate.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Tasks/NavigateToNewPageByClicking.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Waits/GeneralWait.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Waits/ITargettedWait.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Waits/TargettedWait.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Waits/WaitForACondition.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/Waits/WaitUntilThePageLoads.cs (100%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/WebBrowsingIntegrationBuilderExtensions.cs (74%) rename {CSF.Screenplay.Web => CSF.Screenplay.Selenium}/packages.config (53%) delete mode 100644 CSF.Screenplay.Web/WebBrowsingResolverExtensions.cs rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/App_Start/RouteConfig.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/CSF.Screenplay.WebTestWebsite.csproj (62%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Content/css/common.css (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Content/css/reset.css (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Controllers/ControllerBase.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Controllers/HomeController.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Controllers/PageThreeController.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Controllers/PageTwoController.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Global.asax (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Global.asax.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Models/ModelBase.cs (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Scripts/PageThree.js (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Scripts/PageTwo.js (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Scripts/jquery-3.2.1.min.js (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/Home/Index.pt (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/PageThree/Index.pt (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/PageTwo/Index.pt (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/Shared/Footer.pt (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/Shared/Header.pt (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/Shared/Page.pt (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Views/Web.config (100%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/Web.config (92%) rename {Tests/CSF.Screenplay.WebTestWebsite => CSF.Screenplay.WebTestWebsite}/packages.config (100%) delete mode 100644 CSF.Screenplay.sln delete mode 100644 Tests/CSF.Screenplay.WebTestWebsite/ApiControllers/DataController.cs delete mode 100644 Tests/CSF.Screenplay.WebTestWebsite/ApiControllers/ExecutionController.cs delete mode 100644 Tests/CSF.Screenplay.WebTestWebsite/Models/SampleApiData.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Abilities/BrowseTheWebTests.cs b/CSF.Screenplay.Selenium.Tests/Abilities/BrowseTheWebTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Abilities/BrowseTheWebTests.cs rename to CSF.Screenplay.Selenium.Tests/Abilities/BrowseTheWebTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/ClearCookiesTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/ClearCookiesTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/ClearCookiesTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/ClearCookiesTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/ClearTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/ClearTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/ClearTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/ClearTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/ClickTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/ClickTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/DeselectTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/DeselectTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/DeselectTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/DeselectTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/EnterTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/EnterTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/EnterTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/EnterTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/ExecuteScriptTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/ExecuteScriptTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/ExecuteScriptTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/ExecuteScriptTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/OpenTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/OpenTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/OpenTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/OpenTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/SelectTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/SelectTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/SelectTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/SelectTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Actions/TargetNotFoundTests.cs b/CSF.Screenplay.Selenium.Tests/Actions/TargetNotFoundTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Actions/TargetNotFoundTests.cs rename to CSF.Screenplay.Selenium.Tests/Actions/TargetNotFoundTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/App.AppVeyor.config b/CSF.Screenplay.Selenium.Tests/App.AppVeyor.config similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/App.AppVeyor.config rename to CSF.Screenplay.Selenium.Tests/App.AppVeyor.config diff --git a/Tests/CSF.Screenplay.Web.Tests/App.Travis.config b/CSF.Screenplay.Selenium.Tests/App.Travis.config similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/App.Travis.config rename to CSF.Screenplay.Selenium.Tests/App.Travis.config diff --git a/Tests/CSF.Screenplay.Web.Tests/App.config b/CSF.Screenplay.Selenium.Tests/App.config similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/App.config rename to CSF.Screenplay.Selenium.Tests/App.config diff --git a/Tests/CSF.Screenplay.Web.Tests/BrowserName.cs b/CSF.Screenplay.Selenium.Tests/BrowserName.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/BrowserName.cs rename to CSF.Screenplay.Selenium.Tests/BrowserName.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/CSF.Screenplay.Web.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj similarity index 64% rename from Tests/CSF.Screenplay.Web.Tests/CSF.Screenplay.Web.Tests.csproj rename to CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index 92fbc7fd..c8d6691a 100644 --- a/Tests/CSF.Screenplay.Web.Tests/CSF.Screenplay.Web.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -28,31 +28,53 @@ - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll + ..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll + nunit - ..\..\packages\Selenium.WebDriver.3.4.0\lib\net40\WebDriver.dll + ..\packages\Selenium.WebDriver.3.4.0\lib\net40\WebDriver.dll - ..\..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll + ..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll - ..\..\packages\FluentAssertions.4.19.3\lib\net45\FluentAssertions.Core.dll + ..\packages\FluentAssertions.4.19.3\lib\net45\FluentAssertions.Core.dll - ..\..\packages\FluentAssertions.4.19.3\lib\net45\FluentAssertions.dll + ..\packages\FluentAssertions.4.19.3\lib\net45\FluentAssertions.dll - ..\..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll + ..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll - ..\..\packages\Moq.4.7.99\lib\net45\Moq.dll + ..\packages\Moq.4.7.99\lib\net45\Moq.dll - ..\..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll + ..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll + + + ..\packages\CSF.Screenplay.0.10.0-alpha\lib\net45\CSF.Screenplay.dll + + + ..\packages\CSF.Screenplay.Reporting.0.10.0-alpha\lib\net45\CSF.Screenplay.Reporting.dll + + + ..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll + + + ..\packages\CSF.Screenplay.NUnit.0.10.0-alpha\lib\net45\CSF.Screenplay.NUnit.dll + + + ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\CSF.WebDriverExtras.0.3.0-beta\lib\net45\CSF.WebDriverExtras.dll @@ -61,28 +83,6 @@ - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B} - CSF.Screenplay.Web - - - {C99466AD-CA21-4C12-9E05-6730CDC3C031} - CSF.WebDriverFactory - - - {18010B4E-22A7-4462-B057-7199B3386D48} - CSF.Screenplay.Reporting - - - {78571AD2-4C55-4459-A4D9-2CD63A9AACC7} - CSF.Screenplay.NUnit - - @@ -125,6 +125,12 @@ + + + {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B} + CSF.Screenplay.Selenium + + - + \ No newline at end of file diff --git a/Tests/CSF.Screenplay.Web.Tests/IgnoreOn.cs b/CSF.Screenplay.Selenium.Tests/IgnoreOn.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/IgnoreOn.cs rename to CSF.Screenplay.Selenium.Tests/IgnoreOn.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/NUnitIntegrationTests.cs b/CSF.Screenplay.Selenium.Tests/NUnitIntegrationTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/NUnitIntegrationTests.cs rename to CSF.Screenplay.Selenium.Tests/NUnitIntegrationTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Pages/GoogleHomePage.cs b/CSF.Screenplay.Selenium.Tests/Pages/GoogleHomePage.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Pages/GoogleHomePage.cs rename to CSF.Screenplay.Selenium.Tests/Pages/GoogleHomePage.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Pages/HomePage.cs b/CSF.Screenplay.Selenium.Tests/Pages/HomePage.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Pages/HomePage.cs rename to CSF.Screenplay.Selenium.Tests/Pages/HomePage.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Pages/PageThree.cs b/CSF.Screenplay.Selenium.Tests/Pages/PageThree.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Pages/PageThree.cs rename to CSF.Screenplay.Selenium.Tests/Pages/PageThree.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Pages/PageTwo.cs b/CSF.Screenplay.Selenium.Tests/Pages/PageTwo.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Pages/PageTwo.cs rename to CSF.Screenplay.Selenium.Tests/Pages/PageTwo.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/FindElementsTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/FindElementsTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/FindElementsTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/FindElementsTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/GetAttributeTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/GetAttributeTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/GetAttributeTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/GetAttributeTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/GetCssValueTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/GetCssValueTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/GetCssValueTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/GetCssValueTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/GetOptionsTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/GetOptionsTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/GetOptionsTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/GetOptionsTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/GetTextTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/GetTextTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/GetTextTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/GetTextTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/GetValueTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/GetValueTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/GetValueTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/GetValueTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Questions/GetWindowTitleTests.cs b/CSF.Screenplay.Selenium.Tests/Questions/GetWindowTitleTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Questions/GetWindowTitleTests.cs rename to CSF.Screenplay.Selenium.Tests/Questions/GetWindowTitleTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/SauceConnectWebDriverFactory.cs b/CSF.Screenplay.Selenium.Tests/SauceConnectWebDriverFactory.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/SauceConnectWebDriverFactory.cs rename to CSF.Screenplay.Selenium.Tests/SauceConnectWebDriverFactory.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/ScenarioExtensions.cs b/CSF.Screenplay.Selenium.Tests/ScenarioExtensions.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/ScenarioExtensions.cs rename to CSF.Screenplay.Selenium.Tests/ScenarioExtensions.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/ScreenplayConfig.cs b/CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs similarity index 90% rename from Tests/CSF.Screenplay.Web.Tests/ScreenplayConfig.cs rename to CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs index 2865f7f4..34418870 100644 --- a/Tests/CSF.Screenplay.Web.Tests/ScreenplayConfig.cs +++ b/CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs @@ -8,7 +8,7 @@ using CSF.Screenplay.Web.Abilities; using CSF.Screenplay.Web.Reporting; using CSF.Screenplay.Web.Tests; -using CSF.WebDriverFactory; +using CSF.WebDriverExtras; using OpenQA.Selenium; [assembly: ScreenplayAssembly(typeof(ScreenplayConfig))] @@ -29,8 +29,7 @@ public void Configure(IIntegrationConfigBuilder builder) .WithFormatter(); }); builder.UseSharedUriTransformer(new RootUriPrependingTransformer("http://localhost:8080/")); - builder.UseWebDriverFactory(); - builder.UseWebDriver(GetWebDriver); + builder.UseWebDriverFromConfiguration(); builder.UseWebBrowser(GetWebBrowser); } @@ -83,12 +82,6 @@ void ConfigureBrowserCapabilities(BrowseTheWeb ability, IWebDriverFactory factor BrowserName.Edge); } - string GetTestName(IResolvesServices resolver) - { - var scenarioName = resolver.Resolve(); - return $"{scenarioName.FeatureId.Name} -> {scenarioName.ScenarioId.Name}"; - } - void WriteReport(IObjectFormattingService formatter, Report report) { var path = "NUnit.report.txt"; diff --git a/Tests/CSF.Screenplay.Web.Tests/ScreenplayScenarioAttribute.cs b/CSF.Screenplay.Selenium.Tests/ScreenplayScenarioAttribute.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/ScreenplayScenarioAttribute.cs rename to CSF.Screenplay.Selenium.Tests/ScreenplayScenarioAttribute.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Tasks/EnterTextIntoThePageTwoInputField.cs b/CSF.Screenplay.Selenium.Tests/Tasks/EnterTextIntoThePageTwoInputField.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Tasks/EnterTextIntoThePageTwoInputField.cs rename to CSF.Screenplay.Selenium.Tests/Tasks/EnterTextIntoThePageTwoInputField.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Tasks/EnterTheDateTests.cs b/CSF.Screenplay.Selenium.Tests/Tasks/EnterTheDateTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Tasks/EnterTheDateTests.cs rename to CSF.Screenplay.Selenium.Tests/Tasks/EnterTheDateTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Tasks/NavigateToNewPageByClickingTests.cs b/CSF.Screenplay.Selenium.Tests/Tasks/NavigateToNewPageByClickingTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Tasks/NavigateToNewPageByClickingTests.cs rename to CSF.Screenplay.Selenium.Tests/Tasks/NavigateToNewPageByClickingTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Waits/GeneralWaitTests.cs b/CSF.Screenplay.Selenium.Tests/Waits/GeneralWaitTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Waits/GeneralWaitTests.cs rename to CSF.Screenplay.Selenium.Tests/Waits/GeneralWaitTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/Waits/WaitUntilVisibleTests.cs b/CSF.Screenplay.Selenium.Tests/Waits/WaitUntilVisibleTests.cs similarity index 100% rename from Tests/CSF.Screenplay.Web.Tests/Waits/WaitUntilVisibleTests.cs rename to CSF.Screenplay.Selenium.Tests/Waits/WaitUntilVisibleTests.cs diff --git a/Tests/CSF.Screenplay.Web.Tests/packages.config b/CSF.Screenplay.Selenium.Tests/packages.config similarity index 53% rename from Tests/CSF.Screenplay.Web.Tests/packages.config rename to CSF.Screenplay.Selenium.Tests/packages.config index b62ab61d..04c4d6ad 100644 --- a/Tests/CSF.Screenplay.Web.Tests/packages.config +++ b/CSF.Screenplay.Selenium.Tests/packages.config @@ -1,10 +1,17 @@  + + + + + + + diff --git a/CSF.Screenplay.Selenium.sln b/CSF.Screenplay.Selenium.sln new file mode 100644 index 00000000..d73eace3 --- /dev/null +++ b/CSF.Screenplay.Selenium.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{ED939EED-BD26-4C3C-9089-48E04DD01CD8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSF.Screenplay.Selenium", "CSF.Screenplay.Selenium\CSF.Screenplay.Selenium.csproj", "{13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSF.Screenplay.Selenium.Tests", "CSF.Screenplay.Selenium.Tests\CSF.Screenplay.Selenium.Tests.csproj", "{09AA41BD-AD31-485F-8912-D687CBA5BD88}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSF.Screenplay.WebTestWebsite", "CSF.Screenplay.WebTestWebsite\CSF.Screenplay.WebTestWebsite.csproj", "{7E16FEE8-2CEA-4581-B559-A399EF5A86A9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B}.Release|Any CPU.Build.0 = Release|Any CPU + {09AA41BD-AD31-485F-8912-D687CBA5BD88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09AA41BD-AD31-485F-8912-D687CBA5BD88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09AA41BD-AD31-485F-8912-D687CBA5BD88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09AA41BD-AD31-485F-8912-D687CBA5BD88}.Release|Any CPU.Build.0 = Release|Any CPU + {7E16FEE8-2CEA-4581-B559-A399EF5A86A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E16FEE8-2CEA-4581-B559-A399EF5A86A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E16FEE8-2CEA-4581-B559-A399EF5A86A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E16FEE8-2CEA-4581-B559-A399EF5A86A9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {09AA41BD-AD31-485F-8912-D687CBA5BD88} = {ED939EED-BD26-4C3C-9089-48E04DD01CD8} + {7E16FEE8-2CEA-4581-B559-A399EF5A86A9} = {ED939EED-BD26-4C3C-9089-48E04DD01CD8} + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + version = 0.8.0-alpha + EndGlobalSection +EndGlobal diff --git a/CSF.Screenplay.Web/Abilities/BrowseTheWeb.cs b/CSF.Screenplay.Selenium/Abilities/BrowseTheWeb.cs similarity index 100% rename from CSF.Screenplay.Web/Abilities/BrowseTheWeb.cs rename to CSF.Screenplay.Selenium/Abilities/BrowseTheWeb.cs diff --git a/CSF.Screenplay.Web/Abilities/Capabilities.cs b/CSF.Screenplay.Selenium/Abilities/Capabilities.cs similarity index 100% rename from CSF.Screenplay.Web/Abilities/Capabilities.cs rename to CSF.Screenplay.Selenium/Abilities/Capabilities.cs diff --git a/CSF.Screenplay.Web/Abilities/IUriTransformer.cs b/CSF.Screenplay.Selenium/Abilities/IUriTransformer.cs similarity index 100% rename from CSF.Screenplay.Web/Abilities/IUriTransformer.cs rename to CSF.Screenplay.Selenium/Abilities/IUriTransformer.cs diff --git a/CSF.Screenplay.Web/Abilities/MissingCapabilityException.cs b/CSF.Screenplay.Selenium/Abilities/MissingCapabilityException.cs similarity index 100% rename from CSF.Screenplay.Web/Abilities/MissingCapabilityException.cs rename to CSF.Screenplay.Selenium/Abilities/MissingCapabilityException.cs diff --git a/CSF.Screenplay.Web/Abilities/NoOpUriTransformer.cs b/CSF.Screenplay.Selenium/Abilities/NoOpUriTransformer.cs similarity index 100% rename from CSF.Screenplay.Web/Abilities/NoOpUriTransformer.cs rename to CSF.Screenplay.Selenium/Abilities/NoOpUriTransformer.cs diff --git a/CSF.Screenplay.Web/Abilities/RootUriPrependingTransformer.cs b/CSF.Screenplay.Selenium/Abilities/RootUriPrependingTransformer.cs similarity index 100% rename from CSF.Screenplay.Web/Abilities/RootUriPrependingTransformer.cs rename to CSF.Screenplay.Selenium/Abilities/RootUriPrependingTransformer.cs diff --git a/CSF.Screenplay.Web/Actions/ClearCookies.cs b/CSF.Screenplay.Selenium/Actions/ClearCookies.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/ClearCookies.cs rename to CSF.Screenplay.Selenium/Actions/ClearCookies.cs diff --git a/CSF.Screenplay.Web/Actions/ClearLocalStorage.cs b/CSF.Screenplay.Selenium/Actions/ClearLocalStorage.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/ClearLocalStorage.cs rename to CSF.Screenplay.Selenium/Actions/ClearLocalStorage.cs diff --git a/CSF.Screenplay.Web/Actions/ClearTheContents.cs b/CSF.Screenplay.Selenium/Actions/ClearTheContents.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/ClearTheContents.cs rename to CSF.Screenplay.Selenium/Actions/ClearTheContents.cs diff --git a/CSF.Screenplay.Web/Actions/Click.cs b/CSF.Screenplay.Selenium/Actions/Click.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/Click.cs rename to CSF.Screenplay.Selenium/Actions/Click.cs diff --git a/CSF.Screenplay.Web/Actions/DeleteCookie.cs b/CSF.Screenplay.Selenium/Actions/DeleteCookie.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/DeleteCookie.cs rename to CSF.Screenplay.Selenium/Actions/DeleteCookie.cs diff --git a/CSF.Screenplay.Web/Actions/DeselectAll.cs b/CSF.Screenplay.Selenium/Actions/DeselectAll.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/DeselectAll.cs rename to CSF.Screenplay.Selenium/Actions/DeselectAll.cs diff --git a/CSF.Screenplay.Web/Actions/DeselectByIndex.cs b/CSF.Screenplay.Selenium/Actions/DeselectByIndex.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/DeselectByIndex.cs rename to CSF.Screenplay.Selenium/Actions/DeselectByIndex.cs diff --git a/CSF.Screenplay.Web/Actions/DeselectByText.cs b/CSF.Screenplay.Selenium/Actions/DeselectByText.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/DeselectByText.cs rename to CSF.Screenplay.Selenium/Actions/DeselectByText.cs diff --git a/CSF.Screenplay.Web/Actions/DeselectByValue.cs b/CSF.Screenplay.Selenium/Actions/DeselectByValue.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/DeselectByValue.cs rename to CSF.Screenplay.Selenium/Actions/DeselectByValue.cs diff --git a/CSF.Screenplay.Web/Actions/Enter.cs b/CSF.Screenplay.Selenium/Actions/Enter.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/Enter.cs rename to CSF.Screenplay.Selenium/Actions/Enter.cs diff --git a/CSF.Screenplay.Web/Actions/ExecuteJavaScript.cs b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScript.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/ExecuteJavaScript.cs rename to CSF.Screenplay.Selenium/Actions/ExecuteJavaScript.cs diff --git a/CSF.Screenplay.Web/Actions/ExecuteJavaScriptAndGetResult.cs b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptAndGetResult.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/ExecuteJavaScriptAndGetResult.cs rename to CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptAndGetResult.cs diff --git a/CSF.Screenplay.Web/Actions/IActionDriver.cs b/CSF.Screenplay.Selenium/Actions/IActionDriver.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/IActionDriver.cs rename to CSF.Screenplay.Selenium/Actions/IActionDriver.cs diff --git a/CSF.Screenplay.Web/Actions/Open.cs b/CSF.Screenplay.Selenium/Actions/Open.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/Open.cs rename to CSF.Screenplay.Selenium/Actions/Open.cs diff --git a/CSF.Screenplay.Web/Actions/SelectActionDriver.cs b/CSF.Screenplay.Selenium/Actions/SelectActionDriver.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/SelectActionDriver.cs rename to CSF.Screenplay.Selenium/Actions/SelectActionDriver.cs diff --git a/CSF.Screenplay.Web/Actions/SelectByIndex.cs b/CSF.Screenplay.Selenium/Actions/SelectByIndex.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/SelectByIndex.cs rename to CSF.Screenplay.Selenium/Actions/SelectByIndex.cs diff --git a/CSF.Screenplay.Web/Actions/SelectByText.cs b/CSF.Screenplay.Selenium/Actions/SelectByText.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/SelectByText.cs rename to CSF.Screenplay.Selenium/Actions/SelectByText.cs diff --git a/CSF.Screenplay.Web/Actions/SelectByValue.cs b/CSF.Screenplay.Selenium/Actions/SelectByValue.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/SelectByValue.cs rename to CSF.Screenplay.Selenium/Actions/SelectByValue.cs diff --git a/CSF.Screenplay.Web/Actions/TargettedAction.cs b/CSF.Screenplay.Selenium/Actions/TargettedAction.cs similarity index 100% rename from CSF.Screenplay.Web/Actions/TargettedAction.cs rename to CSF.Screenplay.Selenium/Actions/TargettedAction.cs diff --git a/CSF.Screenplay.Web/Builders/Clear.cs b/CSF.Screenplay.Selenium/Builders/Clear.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Clear.cs rename to CSF.Screenplay.Selenium/Builders/Clear.cs diff --git a/CSF.Screenplay.Web/Builders/ClearTheirBrowser.cs b/CSF.Screenplay.Selenium/Builders/ClearTheirBrowser.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/ClearTheirBrowser.cs rename to CSF.Screenplay.Selenium/Builders/ClearTheirBrowser.cs diff --git a/CSF.Screenplay.Web/Builders/Click.cs b/CSF.Screenplay.Selenium/Builders/Click.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Click.cs rename to CSF.Screenplay.Selenium/Builders/Click.cs diff --git a/CSF.Screenplay.Web/Builders/Deselect.cs b/CSF.Screenplay.Selenium/Builders/Deselect.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Deselect.cs rename to CSF.Screenplay.Selenium/Builders/Deselect.cs diff --git a/CSF.Screenplay.Web/Builders/Elements.cs b/CSF.Screenplay.Selenium/Builders/Elements.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Elements.cs rename to CSF.Screenplay.Selenium/Builders/Elements.cs diff --git a/CSF.Screenplay.Web/Builders/ElementsInThePageBody.cs b/CSF.Screenplay.Selenium/Builders/ElementsInThePageBody.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/ElementsInThePageBody.cs rename to CSF.Screenplay.Selenium/Builders/ElementsInThePageBody.cs diff --git a/CSF.Screenplay.Web/Builders/ElementsWithin.cs b/CSF.Screenplay.Selenium/Builders/ElementsWithin.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/ElementsWithin.cs rename to CSF.Screenplay.Selenium/Builders/ElementsWithin.cs diff --git a/CSF.Screenplay.Web/Builders/Enter.cs b/CSF.Screenplay.Selenium/Builders/Enter.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Enter.cs rename to CSF.Screenplay.Selenium/Builders/Enter.cs diff --git a/CSF.Screenplay.Web/Builders/Execute.cs b/CSF.Screenplay.Selenium/Builders/Execute.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Execute.cs rename to CSF.Screenplay.Selenium/Builders/Execute.cs diff --git a/CSF.Screenplay.Web/Builders/Get.cs b/CSF.Screenplay.Selenium/Builders/Get.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Get.cs rename to CSF.Screenplay.Selenium/Builders/Get.cs diff --git a/CSF.Screenplay.Web/Builders/Matcher.cs b/CSF.Screenplay.Selenium/Builders/Matcher.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Matcher.cs rename to CSF.Screenplay.Selenium/Builders/Matcher.cs diff --git a/CSF.Screenplay.Web/Builders/Navigate.cs b/CSF.Screenplay.Selenium/Builders/Navigate.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Navigate.cs rename to CSF.Screenplay.Selenium/Builders/Navigate.cs diff --git a/CSF.Screenplay.Web/Builders/OpenTheirBrowserOn.cs b/CSF.Screenplay.Selenium/Builders/OpenTheirBrowserOn.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/OpenTheirBrowserOn.cs rename to CSF.Screenplay.Selenium/Builders/OpenTheirBrowserOn.cs diff --git a/CSF.Screenplay.Web/Builders/Select.cs b/CSF.Screenplay.Selenium/Builders/Select.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Select.cs rename to CSF.Screenplay.Selenium/Builders/Select.cs diff --git a/CSF.Screenplay.Web/Builders/SelectStrategy.cs b/CSF.Screenplay.Selenium/Builders/SelectStrategy.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/SelectStrategy.cs rename to CSF.Screenplay.Selenium/Builders/SelectStrategy.cs diff --git a/CSF.Screenplay.Web/Builders/TheAttribute.cs b/CSF.Screenplay.Selenium/Builders/TheAttribute.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheAttribute.cs rename to CSF.Screenplay.Selenium/Builders/TheAttribute.cs diff --git a/CSF.Screenplay.Web/Builders/TheCss.cs b/CSF.Screenplay.Selenium/Builders/TheCss.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheCss.cs rename to CSF.Screenplay.Selenium/Builders/TheCss.cs diff --git a/CSF.Screenplay.Web/Builders/TheLocation.cs b/CSF.Screenplay.Selenium/Builders/TheLocation.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheLocation.cs rename to CSF.Screenplay.Selenium/Builders/TheLocation.cs diff --git a/CSF.Screenplay.Web/Builders/TheOptions.cs b/CSF.Screenplay.Selenium/Builders/TheOptions.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheOptions.cs rename to CSF.Screenplay.Selenium/Builders/TheOptions.cs diff --git a/CSF.Screenplay.Web/Builders/TheSize.cs b/CSF.Screenplay.Selenium/Builders/TheSize.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheSize.cs rename to CSF.Screenplay.Selenium/Builders/TheSize.cs diff --git a/CSF.Screenplay.Web/Builders/TheText.cs b/CSF.Screenplay.Selenium/Builders/TheText.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheText.cs rename to CSF.Screenplay.Selenium/Builders/TheText.cs diff --git a/CSF.Screenplay.Web/Builders/TheValue.cs b/CSF.Screenplay.Selenium/Builders/TheValue.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheValue.cs rename to CSF.Screenplay.Selenium/Builders/TheValue.cs diff --git a/CSF.Screenplay.Web/Builders/TheVisibility.cs b/CSF.Screenplay.Selenium/Builders/TheVisibility.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheVisibility.cs rename to CSF.Screenplay.Selenium/Builders/TheVisibility.cs diff --git a/CSF.Screenplay.Web/Builders/TheWindow.cs b/CSF.Screenplay.Selenium/Builders/TheWindow.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/TheWindow.cs rename to CSF.Screenplay.Selenium/Builders/TheWindow.cs diff --git a/CSF.Screenplay.Web/Builders/Wait.cs b/CSF.Screenplay.Selenium/Builders/Wait.cs similarity index 100% rename from CSF.Screenplay.Web/Builders/Wait.cs rename to CSF.Screenplay.Selenium/Builders/Wait.cs diff --git a/CSF.Screenplay.Web/CSF.Screenplay.Web.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj similarity index 91% rename from CSF.Screenplay.Web/CSF.Screenplay.Web.csproj rename to CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 16400a54..ff3df891 100644 --- a/CSF.Screenplay.Web/CSF.Screenplay.Web.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -45,6 +45,18 @@ ..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll + + ..\packages\CSF.Screenplay.0.10.0-alpha\lib\net45\CSF.Screenplay.dll + + + ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll + + + ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\CSF.WebDriverExtras.0.3.0-beta\lib\net45\CSF.WebDriverExtras.dll + @@ -144,7 +156,6 @@ - @@ -172,19 +183,9 @@ - - - {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} - CSF.Screenplay - - - {C99466AD-CA21-4C12-9E05-6730CDC3C031} - CSF.WebDriverFactory - - - + diff --git a/CSF.Screenplay.Web/CSF.Screenplay.Web.nuspec b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.nuspec similarity index 100% rename from CSF.Screenplay.Web/CSF.Screenplay.Web.nuspec rename to CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.nuspec diff --git a/CSF.Screenplay.Web/ElementMatching/AndMatcher.cs b/CSF.Screenplay.Selenium/ElementMatching/AndMatcher.cs similarity index 100% rename from CSF.Screenplay.Web/ElementMatching/AndMatcher.cs rename to CSF.Screenplay.Selenium/ElementMatching/AndMatcher.cs diff --git a/CSF.Screenplay.Web/ElementMatching/IMatcher.cs b/CSF.Screenplay.Selenium/ElementMatching/IMatcher.cs similarity index 100% rename from CSF.Screenplay.Web/ElementMatching/IMatcher.cs rename to CSF.Screenplay.Selenium/ElementMatching/IMatcher.cs diff --git a/CSF.Screenplay.Web/ElementMatching/Matcher`1.cs b/CSF.Screenplay.Selenium/ElementMatching/Matcher`1.cs similarity index 100% rename from CSF.Screenplay.Web/ElementMatching/Matcher`1.cs rename to CSF.Screenplay.Selenium/ElementMatching/Matcher`1.cs diff --git a/CSF.Screenplay.Web/ElementMatching/OrMatcher.cs b/CSF.Screenplay.Selenium/ElementMatching/OrMatcher.cs similarity index 100% rename from CSF.Screenplay.Web/ElementMatching/OrMatcher.cs rename to CSF.Screenplay.Selenium/ElementMatching/OrMatcher.cs diff --git a/CSF.Screenplay.Web/Models/AppUri.cs b/CSF.Screenplay.Selenium/Models/AppUri.cs similarity index 100% rename from CSF.Screenplay.Web/Models/AppUri.cs rename to CSF.Screenplay.Selenium/Models/AppUri.cs diff --git a/CSF.Screenplay.Web/Models/ClassName.cs b/CSF.Screenplay.Selenium/Models/ClassName.cs similarity index 100% rename from CSF.Screenplay.Web/Models/ClassName.cs rename to CSF.Screenplay.Selenium/Models/ClassName.cs diff --git a/CSF.Screenplay.Web/Models/CssSelector.cs b/CSF.Screenplay.Selenium/Models/CssSelector.cs similarity index 100% rename from CSF.Screenplay.Web/Models/CssSelector.cs rename to CSF.Screenplay.Selenium/Models/CssSelector.cs diff --git a/CSF.Screenplay.Web/Models/DurationFormatter.cs b/CSF.Screenplay.Selenium/Models/DurationFormatter.cs similarity index 100% rename from CSF.Screenplay.Web/Models/DurationFormatter.cs rename to CSF.Screenplay.Selenium/Models/DurationFormatter.cs diff --git a/CSF.Screenplay.Web/Models/ElementCollection.cs b/CSF.Screenplay.Selenium/Models/ElementCollection.cs similarity index 100% rename from CSF.Screenplay.Web/Models/ElementCollection.cs rename to CSF.Screenplay.Selenium/Models/ElementCollection.cs diff --git a/CSF.Screenplay.Web/Models/ElementId.cs b/CSF.Screenplay.Selenium/Models/ElementId.cs similarity index 100% rename from CSF.Screenplay.Web/Models/ElementId.cs rename to CSF.Screenplay.Selenium/Models/ElementId.cs diff --git a/CSF.Screenplay.Web/Models/GeneralWaitBuilder.cs b/CSF.Screenplay.Selenium/Models/GeneralWaitBuilder.cs similarity index 100% rename from CSF.Screenplay.Web/Models/GeneralWaitBuilder.cs rename to CSF.Screenplay.Selenium/Models/GeneralWaitBuilder.cs diff --git a/CSF.Screenplay.Web/Models/GivenUpWaitingException.cs b/CSF.Screenplay.Selenium/Models/GivenUpWaitingException.cs similarity index 100% rename from CSF.Screenplay.Web/Models/GivenUpWaitingException.cs rename to CSF.Screenplay.Selenium/Models/GivenUpWaitingException.cs diff --git a/CSF.Screenplay.Web/Models/IDurationFormatter.cs b/CSF.Screenplay.Selenium/Models/IDurationFormatter.cs similarity index 100% rename from CSF.Screenplay.Web/Models/IDurationFormatter.cs rename to CSF.Screenplay.Selenium/Models/IDurationFormatter.cs diff --git a/CSF.Screenplay.Web/Models/IHasTargetName.cs b/CSF.Screenplay.Selenium/Models/IHasTargetName.cs similarity index 100% rename from CSF.Screenplay.Web/Models/IHasTargetName.cs rename to CSF.Screenplay.Selenium/Models/IHasTargetName.cs diff --git a/CSF.Screenplay.Web/Models/ILocatorBasedTarget.cs b/CSF.Screenplay.Selenium/Models/ILocatorBasedTarget.cs similarity index 100% rename from CSF.Screenplay.Web/Models/ILocatorBasedTarget.cs rename to CSF.Screenplay.Selenium/Models/ILocatorBasedTarget.cs diff --git a/CSF.Screenplay.Web/Models/IProvidesTimespan.cs b/CSF.Screenplay.Selenium/Models/IProvidesTimespan.cs similarity index 100% rename from CSF.Screenplay.Web/Models/IProvidesTimespan.cs rename to CSF.Screenplay.Selenium/Models/IProvidesTimespan.cs diff --git a/CSF.Screenplay.Web/Models/ITarget.cs b/CSF.Screenplay.Selenium/Models/ITarget.cs similarity index 100% rename from CSF.Screenplay.Web/Models/ITarget.cs rename to CSF.Screenplay.Selenium/Models/ITarget.cs diff --git a/CSF.Screenplay.Web/Models/IUriProvider.cs b/CSF.Screenplay.Selenium/Models/IUriProvider.cs similarity index 100% rename from CSF.Screenplay.Web/Models/IUriProvider.cs rename to CSF.Screenplay.Selenium/Models/IUriProvider.cs diff --git a/CSF.Screenplay.Web/Models/IWebElementAdapter.cs b/CSF.Screenplay.Selenium/Models/IWebElementAdapter.cs similarity index 100% rename from CSF.Screenplay.Web/Models/IWebElementAdapter.cs rename to CSF.Screenplay.Selenium/Models/IWebElementAdapter.cs diff --git a/CSF.Screenplay.Web/Models/InvalidTargetException.cs b/CSF.Screenplay.Selenium/Models/InvalidTargetException.cs similarity index 100% rename from CSF.Screenplay.Web/Models/InvalidTargetException.cs rename to CSF.Screenplay.Selenium/Models/InvalidTargetException.cs diff --git a/CSF.Screenplay.Web/Models/Option.cs b/CSF.Screenplay.Selenium/Models/Option.cs similarity index 100% rename from CSF.Screenplay.Web/Models/Option.cs rename to CSF.Screenplay.Selenium/Models/Option.cs diff --git a/CSF.Screenplay.Web/Models/Page.cs b/CSF.Screenplay.Selenium/Models/Page.cs similarity index 100% rename from CSF.Screenplay.Web/Models/Page.cs rename to CSF.Screenplay.Selenium/Models/Page.cs diff --git a/CSF.Screenplay.Web/Models/PixelDistance.cs b/CSF.Screenplay.Selenium/Models/PixelDistance.cs similarity index 100% rename from CSF.Screenplay.Web/Models/PixelDistance.cs rename to CSF.Screenplay.Selenium/Models/PixelDistance.cs diff --git a/CSF.Screenplay.Web/Models/Position.cs b/CSF.Screenplay.Selenium/Models/Position.cs similarity index 100% rename from CSF.Screenplay.Web/Models/Position.cs rename to CSF.Screenplay.Selenium/Models/Position.cs diff --git a/CSF.Screenplay.Web/Models/SeleniumWebElementAdapter.cs b/CSF.Screenplay.Selenium/Models/SeleniumWebElementAdapter.cs similarity index 100% rename from CSF.Screenplay.Web/Models/SeleniumWebElementAdapter.cs rename to CSF.Screenplay.Selenium/Models/SeleniumWebElementAdapter.cs diff --git a/CSF.Screenplay.Web/Models/Size.cs b/CSF.Screenplay.Selenium/Models/Size.cs similarity index 100% rename from CSF.Screenplay.Web/Models/Size.cs rename to CSF.Screenplay.Selenium/Models/Size.cs diff --git a/CSF.Screenplay.Web/Models/StringBasedTarget.cs b/CSF.Screenplay.Selenium/Models/StringBasedTarget.cs similarity index 100% rename from CSF.Screenplay.Web/Models/StringBasedTarget.cs rename to CSF.Screenplay.Selenium/Models/StringBasedTarget.cs diff --git a/CSF.Screenplay.Web/Models/TargetNotFoundException.cs b/CSF.Screenplay.Selenium/Models/TargetNotFoundException.cs similarity index 100% rename from CSF.Screenplay.Web/Models/TargetNotFoundException.cs rename to CSF.Screenplay.Selenium/Models/TargetNotFoundException.cs diff --git a/CSF.Screenplay.Web/Models/TimespanBuilder.cs b/CSF.Screenplay.Selenium/Models/TimespanBuilder.cs similarity index 100% rename from CSF.Screenplay.Web/Models/TimespanBuilder.cs rename to CSF.Screenplay.Selenium/Models/TimespanBuilder.cs diff --git a/CSF.Screenplay.Web/Models/TimespanBuilder`1.cs b/CSF.Screenplay.Selenium/Models/TimespanBuilder`1.cs similarity index 100% rename from CSF.Screenplay.Web/Models/TimespanBuilder`1.cs rename to CSF.Screenplay.Selenium/Models/TimespanBuilder`1.cs diff --git a/CSF.Screenplay.Web/Models/TimespanWrapper.cs b/CSF.Screenplay.Selenium/Models/TimespanWrapper.cs similarity index 100% rename from CSF.Screenplay.Web/Models/TimespanWrapper.cs rename to CSF.Screenplay.Selenium/Models/TimespanWrapper.cs diff --git a/CSF.Screenplay.Web/Models/XPath.cs b/CSF.Screenplay.Selenium/Models/XPath.cs similarity index 100% rename from CSF.Screenplay.Web/Models/XPath.cs rename to CSF.Screenplay.Selenium/Models/XPath.cs diff --git a/CSF.Screenplay.Web/Properties/AssemblyInfo.cs b/CSF.Screenplay.Selenium/Properties/AssemblyInfo.cs similarity index 100% rename from CSF.Screenplay.Web/Properties/AssemblyInfo.cs rename to CSF.Screenplay.Selenium/Properties/AssemblyInfo.cs diff --git a/CSF.Screenplay.Web/Queries/AttributeQuery.cs b/CSF.Screenplay.Selenium/Queries/AttributeQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/AttributeQuery.cs rename to CSF.Screenplay.Selenium/Queries/AttributeQuery.cs diff --git a/CSF.Screenplay.Web/Queries/ClickableQuery.cs b/CSF.Screenplay.Selenium/Queries/ClickableQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/ClickableQuery.cs rename to CSF.Screenplay.Selenium/Queries/ClickableQuery.cs diff --git a/CSF.Screenplay.Web/Queries/CssQuery.cs b/CSF.Screenplay.Selenium/Queries/CssQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/CssQuery.cs rename to CSF.Screenplay.Selenium/Queries/CssQuery.cs diff --git a/CSF.Screenplay.Web/Queries/IQuery.cs b/CSF.Screenplay.Selenium/Queries/IQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/IQuery.cs rename to CSF.Screenplay.Selenium/Queries/IQuery.cs diff --git a/CSF.Screenplay.Web/Queries/IQuery`1.cs b/CSF.Screenplay.Selenium/Queries/IQuery`1.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/IQuery`1.cs rename to CSF.Screenplay.Selenium/Queries/IQuery`1.cs diff --git a/CSF.Screenplay.Web/Queries/LocationQuery.cs b/CSF.Screenplay.Selenium/Queries/LocationQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/LocationQuery.cs rename to CSF.Screenplay.Selenium/Queries/LocationQuery.cs diff --git a/CSF.Screenplay.Web/Queries/OptionsQuery.cs b/CSF.Screenplay.Selenium/Queries/OptionsQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/OptionsQuery.cs rename to CSF.Screenplay.Selenium/Queries/OptionsQuery.cs diff --git a/CSF.Screenplay.Web/Queries/Query.cs b/CSF.Screenplay.Selenium/Queries/Query.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/Query.cs rename to CSF.Screenplay.Selenium/Queries/Query.cs diff --git a/CSF.Screenplay.Web/Queries/SelectedOptionsQuery.cs b/CSF.Screenplay.Selenium/Queries/SelectedOptionsQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/SelectedOptionsQuery.cs rename to CSF.Screenplay.Selenium/Queries/SelectedOptionsQuery.cs diff --git a/CSF.Screenplay.Web/Queries/SizeQuery.cs b/CSF.Screenplay.Selenium/Queries/SizeQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/SizeQuery.cs rename to CSF.Screenplay.Selenium/Queries/SizeQuery.cs diff --git a/CSF.Screenplay.Web/Queries/TextQuery.cs b/CSF.Screenplay.Selenium/Queries/TextQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/TextQuery.cs rename to CSF.Screenplay.Selenium/Queries/TextQuery.cs diff --git a/CSF.Screenplay.Web/Queries/TextQuery`1.cs b/CSF.Screenplay.Selenium/Queries/TextQuery`1.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/TextQuery`1.cs rename to CSF.Screenplay.Selenium/Queries/TextQuery`1.cs diff --git a/CSF.Screenplay.Web/Queries/ValueQuery.cs b/CSF.Screenplay.Selenium/Queries/ValueQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/ValueQuery.cs rename to CSF.Screenplay.Selenium/Queries/ValueQuery.cs diff --git a/CSF.Screenplay.Web/Queries/ValueQuery`1.cs b/CSF.Screenplay.Selenium/Queries/ValueQuery`1.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/ValueQuery`1.cs rename to CSF.Screenplay.Selenium/Queries/ValueQuery`1.cs diff --git a/CSF.Screenplay.Web/Queries/VisibilityQuery.cs b/CSF.Screenplay.Selenium/Queries/VisibilityQuery.cs similarity index 100% rename from CSF.Screenplay.Web/Queries/VisibilityQuery.cs rename to CSF.Screenplay.Selenium/Queries/VisibilityQuery.cs diff --git a/CSF.Screenplay.Web/Questions/FindElements.cs b/CSF.Screenplay.Selenium/Questions/FindElements.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/FindElements.cs rename to CSF.Screenplay.Selenium/Questions/FindElements.cs diff --git a/CSF.Screenplay.Web/Questions/FindElementsOnPage.cs b/CSF.Screenplay.Selenium/Questions/FindElementsOnPage.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/FindElementsOnPage.cs rename to CSF.Screenplay.Selenium/Questions/FindElementsOnPage.cs diff --git a/CSF.Screenplay.Web/Questions/GetElement.cs b/CSF.Screenplay.Selenium/Questions/GetElement.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/GetElement.cs rename to CSF.Screenplay.Selenium/Questions/GetElement.cs diff --git a/CSF.Screenplay.Web/Questions/GetWindowTitle.cs b/CSF.Screenplay.Selenium/Questions/GetWindowTitle.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/GetWindowTitle.cs rename to CSF.Screenplay.Selenium/Questions/GetWindowTitle.cs diff --git a/CSF.Screenplay.Web/Questions/Question.cs b/CSF.Screenplay.Selenium/Questions/Question.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/Question.cs rename to CSF.Screenplay.Selenium/Questions/Question.cs diff --git a/CSF.Screenplay.Web/Questions/TargettedMultiQuestion`1.cs b/CSF.Screenplay.Selenium/Questions/TargettedMultiQuestion`1.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/TargettedMultiQuestion`1.cs rename to CSF.Screenplay.Selenium/Questions/TargettedMultiQuestion`1.cs diff --git a/CSF.Screenplay.Web/Questions/TargettedQuestion`1.cs b/CSF.Screenplay.Selenium/Questions/TargettedQuestion`1.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/TargettedQuestion`1.cs rename to CSF.Screenplay.Selenium/Questions/TargettedQuestion`1.cs diff --git a/CSF.Screenplay.Web/Questions/TargettedVisibilityQuestion.cs b/CSF.Screenplay.Selenium/Questions/TargettedVisibilityQuestion.cs similarity index 100% rename from CSF.Screenplay.Web/Questions/TargettedVisibilityQuestion.cs rename to CSF.Screenplay.Selenium/Questions/TargettedVisibilityQuestion.cs diff --git a/CSF.Screenplay.Web/Reporting/ElementCollectionFormatter.cs b/CSF.Screenplay.Selenium/Reporting/ElementCollectionFormatter.cs similarity index 66% rename from CSF.Screenplay.Web/Reporting/ElementCollectionFormatter.cs rename to CSF.Screenplay.Selenium/Reporting/ElementCollectionFormatter.cs index 2afef2d9..4a100c4a 100644 --- a/CSF.Screenplay.Web/Reporting/ElementCollectionFormatter.cs +++ b/CSF.Screenplay.Selenium/Reporting/ElementCollectionFormatter.cs @@ -9,13 +9,13 @@ namespace CSF.Screenplay.Web.Reporting /// /// Formatter for collections of HTML elements. /// - public class ElementCollectionFormatter : GenericObjectFormatter + public class ElementCollectionFormatter : ObjectFormatter { /// - /// Gets a formatted name for the given input. + /// Formats the given object. /// /// Object. - protected override string GetFormattedName(ElementCollection obj) + public override string Format(ElementCollection obj) => $"a collection of elements representing '{obj.GetName()}'"; } } diff --git a/CSF.Screenplay.Web/Reporting/OptionCollectionFormatter.cs b/CSF.Screenplay.Selenium/Reporting/OptionCollectionFormatter.cs similarity index 70% rename from CSF.Screenplay.Web/Reporting/OptionCollectionFormatter.cs rename to CSF.Screenplay.Selenium/Reporting/OptionCollectionFormatter.cs index af479cca..48d65517 100644 --- a/CSF.Screenplay.Web/Reporting/OptionCollectionFormatter.cs +++ b/CSF.Screenplay.Selenium/Reporting/OptionCollectionFormatter.cs @@ -9,13 +9,13 @@ namespace CSF.Screenplay.Web.Reporting /// /// Formatter for collections of options (as would appear in an HTML select element). /// - public class OptionCollectionFormatter : GenericObjectFormatter> + public class OptionCollectionFormatter : ObjectFormatter> { - /// - /// Gets a formatted name for the given input. - /// - /// Object. - protected override string GetFormattedName(IEnumerable diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests/packages.config b/CSF.Screenplay.Selenium.BrowserFlags.Tests/packages.config index 638b6242..f9f00b23 100644 --- a/CSF.Screenplay.Selenium.BrowserFlags.Tests/packages.config +++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests/packages.config @@ -5,7 +5,7 @@ - + diff --git a/CSF.Screenplay.Selenium.BrowserFlags/CSF.Screenplay.Selenium.BrowserFlags.csproj b/CSF.Screenplay.Selenium.BrowserFlags/CSF.Screenplay.Selenium.BrowserFlags.csproj index cf5fb1be..73570591 100644 --- a/CSF.Screenplay.Selenium.BrowserFlags/CSF.Screenplay.Selenium.BrowserFlags.csproj +++ b/CSF.Screenplay.Selenium.BrowserFlags/CSF.Screenplay.Selenium.BrowserFlags.csproj @@ -42,7 +42,7 @@ - ..\packages\CSF.WebDriverExtras.0.5.0-beta\lib\net45\CSF.WebDriverExtras.dll + ..\packages\CSF.WebDriverExtras.1.0.0\lib\net45\CSF.WebDriverExtras.dll diff --git a/CSF.Screenplay.Selenium.BrowserFlags/packages.config b/CSF.Screenplay.Selenium.BrowserFlags/packages.config index ccf82f77..ff0a6c4a 100644 --- a/CSF.Screenplay.Selenium.BrowserFlags/packages.config +++ b/CSF.Screenplay.Selenium.BrowserFlags/packages.config @@ -1,7 +1,7 @@  - + \ No newline at end of file diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index 208f8461..68be13d4 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -52,29 +52,29 @@ ..\packages\Moq.4.7.99\lib\net45\Moq.dll - - ..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - ..\packages\CSF.Screenplay.0.10.0-alpha\lib\net45\CSF.Screenplay.dll - - - ..\packages\CSF.Screenplay.Reporting.0.10.0-alpha\lib\net45\CSF.Screenplay.Reporting.dll - ..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll - - ..\packages\CSF.Screenplay.NUnit.0.10.0-alpha\lib\net45\CSF.Screenplay.NUnit.dll - ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\CSF.FlexDi.1.0.0\lib\net45\CSF.FlexDi.dll + + + ..\packages\CSF.Screenplay.0.12.0-beta\lib\net45\CSF.Screenplay.dll + + + ..\packages\CSF.Screenplay.NUnit.0.12.0-beta\lib\net45\CSF.Screenplay.NUnit.dll + + + ..\packages\CSF.Screenplay.Reporting.0.12.0-beta\lib\net45\CSF.Screenplay.Reporting.dll + - ..\packages\CSF.WebDriverExtras.0.5.0-beta\lib\net45\CSF.WebDriverExtras.dll + ..\packages\CSF.WebDriverExtras.1.0.0\lib\net45\CSF.WebDriverExtras.dll diff --git a/CSF.Screenplay.Selenium.Tests/packages.config b/CSF.Screenplay.Selenium.Tests/packages.config index 0e361be2..db89d4ee 100644 --- a/CSF.Screenplay.Selenium.Tests/packages.config +++ b/CSF.Screenplay.Selenium.Tests/packages.config @@ -2,13 +2,13 @@ - + - - - + + + - + diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 9543f36a..f42718f9 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -42,20 +42,20 @@ ..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll - - ..\packages\CSF.FlexDi.0.5.0-beta\lib\net45\CSF.FlexDi.dll - - - ..\packages\CSF.Screenplay.0.10.0-alpha\lib\net45\CSF.Screenplay.dll - ..\packages\CSF.Configuration.1.1.0\lib\net45\CSF.Configuration.dll ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\CSF.FlexDi.1.0.0\lib\net45\CSF.FlexDi.dll + + + ..\packages\CSF.Screenplay.0.12.0-beta\lib\net45\CSF.Screenplay.dll + - ..\packages\CSF.WebDriverExtras.0.5.0-beta\lib\net45\CSF.WebDriverExtras.dll + ..\packages\CSF.WebDriverExtras.1.0.0\lib\net45\CSF.WebDriverExtras.dll diff --git a/CSF.Screenplay.Selenium/packages.config b/CSF.Screenplay.Selenium/packages.config index e4cafd44..ae2fa92a 100644 --- a/CSF.Screenplay.Selenium/packages.config +++ b/CSF.Screenplay.Selenium/packages.config @@ -1,10 +1,10 @@  - - + + - + diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index 338b71a8..baa87bd8 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -72,52 +72,52 @@ ..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll + + + ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + - ..\packages\CSF.Zpt.Abstractions.1.0.0\lib\net45\CSF.Zpt.Abstractions.dll + ..\packages\CSF.Zpt.Abstractions.1.0.5\lib\net45\CSF.Zpt.Abstractions.dll - ..\packages\CSF.Zpt.1.0.0\lib\net45\CSF.Zpt.dll + ..\packages\CSF.Zpt.1.0.5\lib\net45\CSF.Zpt.dll - ..\packages\CSF.Zpt.DocumentProviders.XmlLinq.1.0.0\lib\net45\CSF.Zpt.DocumentProviders.XmlLinq.dll + ..\packages\CSF.Zpt.DocumentProviders.XmlLinq.1.0.5\lib\net45\CSF.Zpt.DocumentProviders.XmlLinq.dll - ..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.0\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.dll + ..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.5\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.dll - ..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.0\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpFramework.dll + ..\packages\CSF.Zpt.ExpressionEvaluators.CSharpExpressions.1.0.5\lib\net45\CSF.Zpt.ExpressionEvaluators.CSharpFramework.dll - - ..\packages\CSF.Zpt.ExpressionEvaluators.NotExpressions.1.0.0\lib\net45\CSF.Zpt.ExpressionEvaluators.NotExpressions.dll + ..\packages\CSF.Zpt.ExpressionEvaluators.NotExpressions.1.0.5\lib\net45\CSF.Zpt.ExpressionEvaluators.NotExpressions.dll - ..\packages\CSF.Zpt.ExpressionEvaluators.PathExpressions.1.0.0\lib\net45\CSF.Zpt.ExpressionEvaluators.PathExpressions.dll + ..\packages\CSF.Zpt.ExpressionEvaluators.PathExpressions.1.0.5\lib\net45\CSF.Zpt.ExpressionEvaluators.PathExpressions.dll - ..\packages\CSF.Zpt.ExpressionEvaluators.StringExpressions.1.0.0\lib\net45\CSF.Zpt.ExpressionEvaluators.StringExpressions.dll + ..\packages\CSF.Zpt.ExpressionEvaluators.StringExpressions.1.0.5\lib\net45\CSF.Zpt.ExpressionEvaluators.StringExpressions.dll - ..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll + ..\packages\HtmlAgilityPack.1.6.17\lib\Net45\HtmlAgilityPack.dll - ..\packages\CSF.Zpt.DocumentProviders.HtmlHAP.1.0.0\lib\net45\CSF.Zpt.DocumentProviders.HtmlHAP.dll + ..\packages\CSF.Zpt.DocumentProviders.HtmlHAP.1.0.5\lib\net45\CSF.Zpt.DocumentProviders.HtmlHAP.dll - ..\packages\CSF.Zpt.MVC5.1.0.0\lib\net45\CSF.Zpt.MVC5.dll - - - ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll - - - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll - - - - ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll - - - ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + ..\packages\CSF.Zpt.MVC5.1.0.5\lib\net45\CSF.Zpt.MVC5.dll diff --git a/CSF.Screenplay.WebTestWebsite/packages.config b/CSF.Screenplay.WebTestWebsite/packages.config index 6e2856c2..a9adfd21 100644 --- a/CSF.Screenplay.WebTestWebsite/packages.config +++ b/CSF.Screenplay.WebTestWebsite/packages.config @@ -4,16 +4,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -23,6 +23,6 @@ - - + + \ No newline at end of file From 0b32cb113727964aa783ebf82d68058a1b0d2cb3 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Mon, 5 Mar 2018 19:26:27 +0000 Subject: [PATCH 075/213] Resolve #42 - Remove redundant builder --- .../NUnitIntegrationTests.cs | 1 + CSF.Screenplay.Selenium/Builders/Navigate.cs | 1 + CSF.Screenplay.Selenium/Builders/Wait.cs | 3 +- .../CSF.Screenplay.Selenium.csproj | 4 -- .../Models/IProvidesTimespan.cs | 15 ----- .../Models/TimespanBuilder.cs | 18 ------ .../Models/TimespanBuilder`1.cs | 60 ------------------- .../Models/TimespanWrapper.cs | 22 ------- 8 files changed, 4 insertions(+), 120 deletions(-) delete mode 100644 CSF.Screenplay.Selenium/Models/IProvidesTimespan.cs delete mode 100644 CSF.Screenplay.Selenium/Models/TimespanBuilder.cs delete mode 100644 CSF.Screenplay.Selenium/Models/TimespanBuilder`1.cs delete mode 100644 CSF.Screenplay.Selenium/Models/TimespanWrapper.cs diff --git a/CSF.Screenplay.Selenium.Tests/NUnitIntegrationTests.cs b/CSF.Screenplay.Selenium.Tests/NUnitIntegrationTests.cs index 4d241e5b..68bc0b14 100644 --- a/CSF.Screenplay.Selenium.Tests/NUnitIntegrationTests.cs +++ b/CSF.Screenplay.Selenium.Tests/NUnitIntegrationTests.cs @@ -1,6 +1,7 @@ using System; using NUnit.Framework; using CSF.Screenplay.NUnit; +using CSF.Screenplay.Scenarios; namespace CSF.Screenplay.Selenium.Tests { diff --git a/CSF.Screenplay.Selenium/Builders/Navigate.cs b/CSF.Screenplay.Selenium/Builders/Navigate.cs index f74a8552..fa79ac4f 100644 --- a/CSF.Screenplay.Selenium/Builders/Navigate.cs +++ b/CSF.Screenplay.Selenium/Builders/Navigate.cs @@ -1,4 +1,5 @@ using System; +using CSF.Screenplay.Builders; using CSF.Screenplay.Performables; using CSF.Screenplay.Selenium.Models; using CSF.Screenplay.Selenium.Tasks; diff --git a/CSF.Screenplay.Selenium/Builders/Wait.cs b/CSF.Screenplay.Selenium/Builders/Wait.cs index 8b0e58e4..06e44b53 100644 --- a/CSF.Screenplay.Selenium/Builders/Wait.cs +++ b/CSF.Screenplay.Selenium/Builders/Wait.cs @@ -1,4 +1,5 @@ using System; +using CSF.Screenplay.Builders; using CSF.Screenplay.Performables; using CSF.Screenplay.Selenium.Models; using CSF.Screenplay.Selenium.Queries; @@ -25,7 +26,7 @@ public class Wait public static TimespanBuilder ForAtMost(int timeValue) { var builder = new Wait(); - var wrapper = new TimespanBuilder(timeValue, builder); + var wrapper = TimespanBuilder.Create(timeValue, builder); builder.timespanProvider = wrapper; return wrapper; } diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index f42718f9..85c635a4 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -147,9 +147,6 @@ - - - @@ -167,7 +164,6 @@ - diff --git a/CSF.Screenplay.Selenium/Models/IProvidesTimespan.cs b/CSF.Screenplay.Selenium/Models/IProvidesTimespan.cs deleted file mode 100644 index b835923c..00000000 --- a/CSF.Screenplay.Selenium/Models/IProvidesTimespan.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -namespace CSF.Screenplay.Selenium.Models -{ - /// - /// Type which provides a System.TimeSpan. - /// - public interface IProvidesTimespan - { - /// - /// Gets the timespan. - /// - /// The timespan. - TimeSpan GetTimespan(); - } -} diff --git a/CSF.Screenplay.Selenium/Models/TimespanBuilder.cs b/CSF.Screenplay.Selenium/Models/TimespanBuilder.cs deleted file mode 100644 index b6d27bac..00000000 --- a/CSF.Screenplay.Selenium/Models/TimespanBuilder.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -namespace CSF.Screenplay.Selenium.Models -{ - /// - /// Static helper class for creating timespan builders. - /// - public static class TimespanBuilder - { - /// - /// Static factory method creates instances of timespan builder. - /// - /// The timeout value. - /// Other builder. - /// The 1st type parameter. - internal static TimespanBuilder Create(int value, T otherBuilder) where T : class - => new TimespanBuilder(value, otherBuilder); - } -} diff --git a/CSF.Screenplay.Selenium/Models/TimespanBuilder`1.cs b/CSF.Screenplay.Selenium/Models/TimespanBuilder`1.cs deleted file mode 100644 index 2976abc0..00000000 --- a/CSF.Screenplay.Selenium/Models/TimespanBuilder`1.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; - -namespace CSF.Screenplay.Selenium.Models -{ - /// - /// Builder for System.TimeSpan instances. - /// - public class TimespanBuilder : IProvidesTimespan - where TBuilder : class - { - readonly TBuilder otherBuilder; - readonly int value; - TimeSpan timespan; - - TimeSpan IProvidesTimespan.GetTimespan() => timespan; - - /// - /// Sets the timespan to be measures in milliseconds and returns the contained builder. - /// - public TBuilder Milliseconds() - { - timespan = TimeSpan.FromMilliseconds(value); - return otherBuilder; - } - - /// - /// Sets the timespan to be measures in seconds and returns the contained builder. - /// - public TBuilder Seconds() - { - timespan = TimeSpan.FromSeconds(value); - return otherBuilder; - } - - /// - /// Sets the timespan to be measures in minutes and returns the contained builder. - /// - public TBuilder Minutes() - { - timespan = TimeSpan.FromMinutes(value); - return otherBuilder; - } - - /// - /// Initializes a new instance of the class. - /// - /// Value. - /// Other builder. - internal TimespanBuilder(int value, TBuilder otherBuilder) - { - if(otherBuilder == null) - throw new ArgumentNullException(nameof(otherBuilder)); - if(value < 0) - throw new ArgumentOutOfRangeException(nameof(value), value, "Value must not be negative"); - - this.value = value; - this.otherBuilder = otherBuilder; - } - } -} diff --git a/CSF.Screenplay.Selenium/Models/TimespanWrapper.cs b/CSF.Screenplay.Selenium/Models/TimespanWrapper.cs deleted file mode 100644 index 07a55d22..00000000 --- a/CSF.Screenplay.Selenium/Models/TimespanWrapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -namespace CSF.Screenplay.Selenium.Models -{ - /// - /// Basic timespan provider which wraps a given value. - /// - public class TimespanWrapper : IProvidesTimespan - { - TimeSpan timespan; - - TimeSpan IProvidesTimespan.GetTimespan() => timespan; - - /// - /// Initializes a new instance of the class. - /// - /// Timespan. - public TimespanWrapper(TimeSpan timespan) - { - this.timespan = timespan; - } - } -} From d9e68ca39613f4493f5a59fff4609131dae2708c Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Mon, 5 Mar 2018 19:30:45 +0000 Subject: [PATCH 076/213] Resolve #38 - Delete obsolete class --- .../Abilities/Capabilities.cs | 26 ------------------- .../CSF.Screenplay.Selenium.csproj | 1 - 2 files changed, 27 deletions(-) delete mode 100644 CSF.Screenplay.Selenium/Abilities/Capabilities.cs diff --git a/CSF.Screenplay.Selenium/Abilities/Capabilities.cs b/CSF.Screenplay.Selenium/Abilities/Capabilities.cs deleted file mode 100644 index 40ed1601..00000000 --- a/CSF.Screenplay.Selenium/Abilities/Capabilities.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -namespace CSF.Screenplay.Selenium.Abilities -{ - /// - /// Enumerates the various capabilities which a web browser may or may not have. - /// - public static class Capabilities - { - /// - /// A capability which indicates that the browser is able to clear all of its cookies for a given domain. - /// - public static readonly string ClearDomainCookies = "Clear all cookies for a domain"; - - /// - /// A capability which indicates that the browser allows the user to enter locale-formatted dates - /// into <input type="date" /> controls. - /// - public static readonly string EnterDatesInLocaleFormat = "Enter values into input type='date' controls as a locale-formatted string"; - - /// - /// A capability which indicates that the browser allows the user to enter locale-formatted dates - /// into <input type="date" /> controls. - /// - public static readonly string EnterDatesAsIsoStrings = "Enter values into input type='date' controls as an ISO-formatted string (Year-Month-Day)"; - } -} diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 85c635a4..a453c6b1 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -166,7 +166,6 @@ - From 0ad6342722eff72597e752d2d2cb19b9d5c9df56 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 19:29:15 +0000 Subject: [PATCH 077/213] WIP #36 - Add script resource types for stored JavaScripts --- .../CSF.Screenplay.Selenium.Tests.csproj | 6 ++ .../StoredScripts/SampleScript.cs | 34 ++++++++++ .../StoredScripts/SampleScript.js | 4 ++ .../StoredScripts/ScriptResourceTests.cs | 65 +++++++++++++++++++ CSF.Screenplay.Selenium.sln | 2 +- .../CSF.Screenplay.Selenium.csproj | 6 ++ .../StoredScripts/IProvidesScript.cs | 47 ++++++++++++++ .../StoredScripts/ScriptResource.cs | 60 +++++++++++++++++ CSF.Screenplay.Selenium/packages.config | 1 + 9 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.cs create mode 100644 CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.js create mode 100644 CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptResourceTests.cs create mode 100644 CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs create mode 100644 CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index 68be13d4..819b2ccd 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -114,6 +114,8 @@ + + @@ -122,6 +124,7 @@ + @@ -133,6 +136,9 @@ CSF.Screenplay.Selenium.BrowserFlags + + + \ No newline at end of file diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.cs new file mode 100644 index 00000000..96426a1e --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.cs @@ -0,0 +1,34 @@ +// +// SampleScript.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.Tests.StoredScripts +{ + public class SampleScript : ScriptResource + { + } +} diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.js b/CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.js new file mode 100644 index 00000000..02f5bb61 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/SampleScript.js @@ -0,0 +1,4 @@ +function executeScript(argsArray) +{ + window.console.log('Test'); +} \ No newline at end of file diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptResourceTests.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptResourceTests.cs new file mode 100644 index 00000000..86d9d9a7 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptResourceTests.cs @@ -0,0 +1,65 @@ +// +// ScriptResourceTests.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using NUnit.Framework; + +namespace CSF.Screenplay.Selenium.Tests.StoredScripts +{ + [TestFixture] + public class ScriptResourceTests + { + [Test] + public void Sample_Script_has_correct_script_body() + { + // Arrange + var expectedScript = @"function executeScript(argsArray) +{ + window.console.log('Test'); +}"; + var sut = new SampleScript(); + + // Act + var actualScript = sut.GetScript(); + + // Assert + Assert.That(actualScript, Is.EqualTo(expectedScript)); + } + + [Test] + public void Sample_Script_has_correct_entry_point_name() + { + // Arrange + var expectedName = @"executeScript"; + var sut = new SampleScript(); + + // Act + var actualName = sut.GetEntryPointName(); + + // Assert + Assert.That(actualName, Is.EqualTo(expectedName)); + } + } +} diff --git a/CSF.Screenplay.Selenium.sln b/CSF.Screenplay.Selenium.sln index 51d60541..98f5afad 100644 --- a/CSF.Screenplay.Selenium.sln +++ b/CSF.Screenplay.Selenium.sln @@ -60,6 +60,6 @@ Global {87454F03-FBB3-4506-9055-551297445891} = {ED939EED-BD26-4C3C-9089-48E04DD01CD8} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution - version = 0.2.2-alpha + version = 0.2.2-alpha EndGlobalSection EndGlobal diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index a453c6b1..6a21904c 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -57,6 +57,9 @@ ..\packages\CSF.WebDriverExtras.1.0.0\lib\net45\CSF.WebDriverExtras.dll + + ..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll + @@ -183,6 +186,8 @@ + + @@ -203,6 +208,7 @@ + diff --git a/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs b/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs new file mode 100644 index 00000000..fad41ffe --- /dev/null +++ b/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs @@ -0,0 +1,47 @@ +// +// IStoredScript.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace CSF.Screenplay.Selenium.StoredScripts +{ + /// + /// A service which provides a JavaScript fragment with a named entry point. + /// + public interface IProvidesScript + { + /// + /// Gets the script fragment as a named function. The name of that function is exposed via + /// . + /// + /// The script. + string GetScript(); + + /// + /// Gets the name of the entry point to the script - this is the function exposed by . + /// + /// The name of the entry point function. + string GetEntryPointName(); + } +} diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs new file mode 100644 index 00000000..e1f7c93e --- /dev/null +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs @@ -0,0 +1,60 @@ +// +// ScriptResource.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Reflection; +using CSF.Reflection; + +namespace CSF.Screenplay.Selenium.StoredScripts +{ + /// + /// Abstract implementation of for a JavaScript which is stored as an embedded resource. + /// + public abstract class ScriptResource : IProvidesScript + { + const string + DefaultEntryPointName = "executeScript"; + + /// + /// Gets the name of the entry point to the script - this is the function exposed by + /// . + /// + /// The name of the entry point function. + public virtual string GetEntryPointName() => DefaultEntryPointName; + + /// + /// Gets the script fragment as a named function. The name of that function is exposed via + /// . + /// + /// The script. + public string GetScript() + { + var thisType = GetType(); + var scriptAssembly = thisType.Assembly; + + return scriptAssembly.GetManifestResourceText(thisType, $"{thisType.Name}.js"); + } + } +} diff --git a/CSF.Screenplay.Selenium/packages.config b/CSF.Screenplay.Selenium/packages.config index ae2fa92a..ebe368ce 100644 --- a/CSF.Screenplay.Selenium/packages.config +++ b/CSF.Screenplay.Selenium/packages.config @@ -2,6 +2,7 @@ + From 3447d3cfb502906e8ef0af544d7f056562a0ab53 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 19:49:20 +0000 Subject: [PATCH 078/213] WIP #36 - Add script runner implementation --- .../CSF.Screenplay.Selenium.Tests.csproj | 1 + .../StoredScripts/ScriptRunnerTests.cs | 76 +++++++++++++++++++ .../CSF.Screenplay.Selenium.csproj | 2 + .../StoredScripts/IRunsScripts.cs | 45 +++++++++++ .../StoredScripts/ScriptRunner.cs | 57 ++++++++++++++ 5 files changed, 181 insertions(+) create mode 100644 CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs create mode 100644 CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs create mode 100644 CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index 819b2ccd..01f0cc84 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -116,6 +116,7 @@ + diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs new file mode 100644 index 00000000..b34494f8 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs @@ -0,0 +1,76 @@ +// +// ScriptRunnerTests.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; +using Moq; +using NUnit.Framework; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.Tests.StoredScripts +{ + [TestFixture] + public class ScriptRunnerTests + { + [Test] + public void ExecuteScript_passes_correct_script_to_webdriver() + { + // Arrange + var script = Mock.Of(); + var driver = Mock.Of(); + var sut = new ScriptRunner(); + + Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}"); + Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar"); + + var expectedExecutedScript = @"function fooBar(argsArray) {} +fooBar(arguments);"; + + // Act + sut.ExecuteScript(script, driver); + + // Assert + Mock.Get(driver).Verify(x => x.ExecuteScript(expectedExecutedScript), Times.Once); + } + + [Test] + public void ExecuteScript_passes_correct_script_arguments_to_webdriver() + { + // Arrange + var script = Mock.Of(); + var driver = Mock.Of(); + var sut = new ScriptRunner(); + + Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}"); + Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar"); + + // Act + sut.ExecuteScript(script, driver, 1, 2, "three"); + + // Assert + Mock.Get(driver).Verify(x => x.ExecuteScript(It.IsAny(), 1, 2, "three"), Times.Once); + } + } +} diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 6a21904c..1912f9e0 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -188,6 +188,8 @@ + + diff --git a/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs b/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs new file mode 100644 index 00000000..414481ed --- /dev/null +++ b/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs @@ -0,0 +1,45 @@ +// +// IRunsStoredScripts.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.StoredScripts +{ + /// + /// A service which executes JavaScripts using given parameters. + /// + public interface IRunsScripts + { + /// + /// Executes the script and returns the result. + /// + /// The script result. + /// A JavaScript. + /// A web driver that runs scripts. + /// The script arguments. + object ExecuteScript(IProvidesScript script, IJavaScriptExecutor webDriver, params object[] arguments); + } +} diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs new file mode 100644 index 00000000..821cce40 --- /dev/null +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs @@ -0,0 +1,57 @@ +// +// ScriptRunner.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.StoredScripts +{ + /// + /// Default implementation of + /// + public class ScriptRunner : IRunsScripts + { + /// + /// Executes the script and returns the result. + /// + /// The script result. + /// A JavaScript. + /// A web driver that runs scripts. + /// The script arguments. + public object ExecuteScript(IProvidesScript script, IJavaScriptExecutor webDriver, params object[] arguments) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + if(webDriver == null) + throw new ArgumentNullException(nameof(webDriver)); + + var runnableScript = GetRunnableScript(script); + return webDriver.ExecuteScript(runnableScript, arguments); + } + + string GetRunnableScript(IProvidesScript script) + => String.Concat(script.GetScript(), Environment.NewLine, $"{script.GetEntryPointName()}(arguments);"); + } +} From e85cea71879fdff71ce17b9b693a2609315248d2 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 20:12:22 +0000 Subject: [PATCH 079/213] WIP #36 - Add new script provider actions and refactor --- .../StoredScripts/ScriptRunnerTests.cs | 18 ++-- .../Actions/ExecuteJavaScript.cs | 20 ++-- .../Actions/ExecuteJavaScriptAndGetResult.cs | 55 ++++------- .../Actions/ExecuteJavaScriptProvider.cs | 77 +++++++++++++++ .../ExecuteJavaScriptProviderAndGetResult.cs | 94 +++++++++++++++++++ .../Actions/IPerformableJavaScript.cs | 43 +++++++++ .../IPerformableJavaScriptWithResult.cs | 44 +++++++++ CSF.Screenplay.Selenium/Builders/Execute.cs | 44 ++++++++- .../CSF.Screenplay.Selenium.csproj | 4 + .../StoredScripts/IProvidesScript.cs | 6 ++ .../StoredScripts/IRunsScripts.cs | 13 ++- .../StoredScripts/ScriptResource.cs | 6 ++ .../StoredScripts/ScriptRunner.cs | 34 ++++++- .../Waits/WaitUntilThePageLoads.cs | 2 +- 14 files changed, 397 insertions(+), 63 deletions(-) create mode 100644 CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProvider.cs create mode 100644 CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProviderAndGetResult.cs create mode 100644 CSF.Screenplay.Selenium/Actions/IPerformableJavaScript.cs create mode 100644 CSF.Screenplay.Selenium/Actions/IPerformableJavaScriptWithResult.cs diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs index b34494f8..47e27415 100644 --- a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs @@ -39,7 +39,8 @@ public void ExecuteScript_passes_correct_script_to_webdriver() { // Arrange var script = Mock.Of(); - var driver = Mock.Of(); + var driver = new Mock(); + driver.As(); var sut = new ScriptRunner(); Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}"); @@ -49,10 +50,12 @@ public void ExecuteScript_passes_correct_script_to_webdriver() fooBar(arguments);"; // Act - sut.ExecuteScript(script, driver); + sut.ExecuteScript(script, driver.Object); // Assert - Mock.Get(driver).Verify(x => x.ExecuteScript(expectedExecutedScript), Times.Once); + driver + .As() + .Verify(x => x.ExecuteScript(expectedExecutedScript), Times.Once); } [Test] @@ -60,17 +63,20 @@ public void ExecuteScript_passes_correct_script_arguments_to_webdriver() { // Arrange var script = Mock.Of(); - var driver = Mock.Of(); + var driver = new Mock(); + driver.As(); var sut = new ScriptRunner(); Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}"); Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar"); // Act - sut.ExecuteScript(script, driver, 1, 2, "three"); + sut.ExecuteScript(script, driver.Object, 1, 2, "three"); // Assert - Mock.Get(driver).Verify(x => x.ExecuteScript(It.IsAny(), 1, 2, "three"), Times.Once); + driver + .As() + .Verify(x => x.ExecuteScript(It.IsAny(), 1, 2, "three"), Times.Once); } } } diff --git a/CSF.Screenplay.Selenium/Actions/ExecuteJavaScript.cs b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScript.cs index ea0d011b..fdb28c33 100644 --- a/CSF.Screenplay.Selenium/Actions/ExecuteJavaScript.cs +++ b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScript.cs @@ -15,21 +15,21 @@ namespace CSF.Screenplay.Selenium.Actions /// the result. /// /// - public class ExecuteJavaScript : Performable + public class ExecuteJavaScript : Performable, IPerformableJavaScript { readonly ExecuteJavaScriptAndGetResult innerScriptAction; - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. + /// + /// Gets the report of the current instance, for the given actor. + /// + /// The human-readable report text. + /// An actor for whom to write the report. protected override string GetReport(INamed actor) => $"{actor.Name} executes some JavaScript in the browser"; - /// - /// Performs this operation, as the given actor. - /// - /// The actor performing this task. + /// + /// Performs this operation, as the given actor. + /// + /// The actor performing this task. protected override void PerformAs(IPerformer actor) => ((IPerformable) innerScriptAction).PerformAs(actor); diff --git a/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptAndGetResult.cs b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptAndGetResult.cs index ac9b5b6b..d97e008c 100644 --- a/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptAndGetResult.cs +++ b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptAndGetResult.cs @@ -2,6 +2,7 @@ using CSF.Screenplay.Actors; using CSF.Screenplay.Performables; using CSF.Screenplay.Selenium.Abilities; +using CSF.Screenplay.Selenium.StoredScripts; using OpenQA.Selenium; namespace CSF.Screenplay.Selenium.Actions @@ -9,30 +10,31 @@ namespace CSF.Screenplay.Selenium.Actions /// /// Executes some JavaScript and returns the result. /// - public class ExecuteJavaScriptAndGetResult : Question + public class ExecuteJavaScriptAndGetResult : Question, IPerformableJavaScriptWithResult { readonly string script; readonly object[] parameters; + readonly IRunsScripts scriptRunner; - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. + /// + /// Gets the report of the current instance, for the given actor. + /// + /// The human-readable report text. + /// An actor for whom to write the report. protected override string GetReport(INamed actor) => $"{actor.Name} executes some JavaScript in the browser and gets the result"; - /// - /// Performs this operation, as the given actor. - /// - /// The response or result. - /// The actor performing this task. + /// + /// Performs this operation, as the given actor. + /// + /// The response or result. + /// The actor performing this task. protected override object PerformAs(IPerformer actor) { if(actor == null) throw new ArgumentNullException(nameof(actor)); - var ability = GetJavascriptAbility(actor); - return ability.ExecuteScript(script, parameters); + var ability = actor.GetAbility(); + return scriptRunner.ExecuteScript(script, ability.WebDriver, parameters); } /// @@ -45,31 +47,7 @@ public object PerformWith(IWebDriver driver) if(driver == null) throw new ArgumentNullException(nameof(driver)); - var jsDriver = GetJavascriptAbility(driver); - return jsDriver.ExecuteScript(script, parameters); - } - - IJavaScriptExecutor GetJavascriptAbility(IPerformer actor) - { - var ability = actor.GetAbility(); - try - { - return GetJavascriptAbility(ability.WebDriver); - } - catch(ArgumentException ex) - { - throw new MissingAbilityException($"{actor.Name} must have a {nameof(BrowseTheWeb)} ability which supports the execution of JavaScript.", ex); - } - } - - IJavaScriptExecutor GetJavascriptAbility(IWebDriver driver) - { - var jsDriver = driver as IJavaScriptExecutor; - - if(jsDriver == null) - throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver)); - - return jsDriver; + return scriptRunner.ExecuteScript(script, driver, parameters); } /// @@ -84,6 +62,7 @@ public ExecuteJavaScriptAndGetResult(string script, params object[] parameters) this.script = script; this.parameters = parameters; + scriptRunner = new ScriptRunner(); } } } diff --git a/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProvider.cs b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProvider.cs new file mode 100644 index 00000000..b91eade9 --- /dev/null +++ b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProvider.cs @@ -0,0 +1,77 @@ +// +// ExecuteJavaScriptProvider.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.StoredScripts; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.Actions +{ + /// + /// An action class which executes a named/provided script in the web browser and ignores the result. + /// + public class ExecuteJavaScriptProvider : Performable, IPerformableJavaScript + { + readonly ExecuteJavaScriptProviderAndGetResult innerScriptAction; + readonly IProvidesScript provider; + + /// + /// Gets the report of the current instance, for the given actor. + /// + /// The human-readable report text. + /// An actor for whom to write the report. + protected override string GetReport(INamed actor) + => $"{actor.Name} executes {provider.Name} in their browser"; + + /// + /// Performs this operation, as the given actor. + /// + /// The actor performing this task. + protected override void PerformAs(IPerformer actor) + => ((IPerformable) innerScriptAction).PerformAs(actor); + + /// + /// Performs the current action using a given IWebDriver. + /// + /// The web driver. + public void PerformWith(IWebDriver driver) => innerScriptAction.PerformWith(driver); + + /// + /// Initializes a new instance of the class. + /// + /// Script. + /// Parameters. + public ExecuteJavaScriptProvider(IProvidesScript script, params object[] parameters) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + + innerScriptAction = new ExecuteJavaScriptProviderAndGetResult(script, parameters); + provider = script; + } + } +} diff --git a/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProviderAndGetResult.cs b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProviderAndGetResult.cs new file mode 100644 index 00000000..874d33af --- /dev/null +++ b/CSF.Screenplay.Selenium/Actions/ExecuteJavaScriptProviderAndGetResult.cs @@ -0,0 +1,94 @@ +// +// ExecuteJavaScriptProviderAndGetResult.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.Abilities; +using CSF.Screenplay.Selenium.StoredScripts; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.Actions +{ + /// + /// A question class which executes a named/provided script in the web browser and returns the result. + /// + public class ExecuteJavaScriptProviderAndGetResult : Question, IPerformableJavaScriptWithResult + { + readonly IProvidesScript provider; + readonly object[] parameters; + readonly IRunsScripts scriptRunner; + + /// + /// Gets the report of the current instance, for the given actor. + /// + /// The human-readable report text. + /// An actor for whom to write the report. + protected override string GetReport(INamed actor) + => $"{actor.Name} executes {provider.Name} in their browser and gets the result"; + + /// + /// Performs this operation, as the given actor. + /// + /// The response or result. + /// The actor performing this task. + protected override object PerformAs(IPerformer actor) + { + if(actor == null) + throw new ArgumentNullException(nameof(actor)); + + var ability = actor.GetAbility(); + return scriptRunner.ExecuteScript(provider, ability.WebDriver, parameters); + } + + /// + /// Performs the current action using a given IWebDriver. + /// + /// The script result. + /// The web driver. + public object PerformWith(IWebDriver driver) + { + if(driver == null) + throw new ArgumentNullException(nameof(driver)); + + return scriptRunner.ExecuteScript(provider, driver, parameters); + } + + /// + /// Initializes a new instance of the class. + /// + /// The script provider. + /// Parameters. + public ExecuteJavaScriptProviderAndGetResult(IProvidesScript provider, params object[] parameters) + { + if(provider == null) + throw new ArgumentNullException(nameof(provider)); + + this.provider = provider; + this.parameters = parameters; + scriptRunner = new ScriptRunner(); + } + } +} diff --git a/CSF.Screenplay.Selenium/Actions/IPerformableJavaScript.cs b/CSF.Screenplay.Selenium/Actions/IPerformableJavaScript.cs new file mode 100644 index 00000000..a5869b59 --- /dev/null +++ b/CSF.Screenplay.Selenium/Actions/IPerformableJavaScript.cs @@ -0,0 +1,43 @@ +// +// IExecutesJavaScript.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Performables; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.Actions +{ + /// + /// A specialisation of which relates to the execution of JavaScript. + /// + public interface IPerformableJavaScript : IPerformable + { + /// + /// Performs the current action using a given IWebDriver. + /// + /// The web driver. + void PerformWith(IWebDriver driver); + } +} diff --git a/CSF.Screenplay.Selenium/Actions/IPerformableJavaScriptWithResult.cs b/CSF.Screenplay.Selenium/Actions/IPerformableJavaScriptWithResult.cs new file mode 100644 index 00000000..bef4f2db --- /dev/null +++ b/CSF.Screenplay.Selenium/Actions/IPerformableJavaScriptWithResult.cs @@ -0,0 +1,44 @@ +// +// IPerformableJavaScript1.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Performables; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.Actions +{ + /// + /// A specialisation of which relates to the execution of JavaScript. + /// + public interface IPerformableJavaScriptWithResult : IPerformable + { + /// + /// Performs the current action using a given IWebDriver. + /// + /// The script result. + /// The web driver. + object PerformWith(IWebDriver driver); + } +} diff --git a/CSF.Screenplay.Selenium/Builders/Execute.cs b/CSF.Screenplay.Selenium/Builders/Execute.cs index 8f437dec..67d6384f 100644 --- a/CSF.Screenplay.Selenium/Builders/Execute.cs +++ b/CSF.Screenplay.Selenium/Builders/Execute.cs @@ -1,6 +1,7 @@ using System; using CSF.Screenplay.Performables; using CSF.Screenplay.Selenium.Actions; +using CSF.Screenplay.Selenium.StoredScripts; namespace CSF.Screenplay.Selenium.Builders { @@ -10,15 +11,31 @@ namespace CSF.Screenplay.Selenium.Builders public class Execute { readonly string script; + readonly IProvidesScript scriptProvider; object[] parameters; /// /// Gets a builder instance for a given piece of script. /// - /// The java script. + /// A JavaScript execution builder. /// Script. public static Execute TheJavaScript(string script) => new Execute(script); + /// + /// Gets a builder instance for a given script provider type. + /// + /// A JavaScript execution builder. + /// The JavaScript provider type. + public static Execute TheJavaScript() where TProvider : IProvidesScript,new() + => new Execute(new TProvider()); + + /// + /// Gets a builder instance for a given script provider. + /// + /// A script provider. + /// A JavaScript execution builder. + public static Execute TheJavaScript(IProvidesScript provider) => new Execute(provider); + /// /// Indicates that the given parameters are to be passed to the script, via the arguments biult-in /// JavaScript keyword. @@ -35,13 +52,25 @@ public Execute WithTheParameters(params object[] parameters) /// Gets the action; a result from the script will be returned. /// /// The action. - public ExecuteJavaScriptAndGetResult AndGetTheResult() => new ExecuteJavaScriptAndGetResult(script, parameters); + public IPerformableJavaScriptWithResult AndGetTheResult() + { + if(scriptProvider != null) + return new ExecuteJavaScriptProviderAndGetResult(scriptProvider, parameters); + + return new ExecuteJavaScriptAndGetResult(script, parameters); + } /// /// Gets the action; any result from the script will be discarded. /// /// The action. - public ExecuteJavaScript AndIgnoreTheResult() => new ExecuteJavaScript(script, parameters); + public IPerformableJavaScript AndIgnoreTheResult() + { + if(scriptProvider != null) + return new ExecuteJavaScriptProvider(scriptProvider, parameters); + + return new ExecuteJavaScript(script, parameters); + } Execute(string script) { @@ -51,5 +80,14 @@ public Execute WithTheParameters(params object[] parameters) this.script = script; parameters = new object[0]; } + + Execute(IProvidesScript scriptProvider) + { + if(scriptProvider == null) + throw new ArgumentNullException(nameof(scriptProvider)); + + this.scriptProvider = scriptProvider; + parameters = new object[0]; + } } } diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 1912f9e0..63ec1a43 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -190,6 +190,10 @@ + + + + diff --git a/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs b/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs index fad41ffe..37eb785d 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/IProvidesScript.cs @@ -31,6 +31,12 @@ namespace CSF.Screenplay.Selenium.StoredScripts /// public interface IProvidesScript { + /// + /// Gets the name of this script. + /// + /// The name. + string Name { get; } + /// /// Gets the script fragment as a named function. The name of that function is exposed via /// . diff --git a/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs b/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs index 414481ed..244a2c2c 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/IRunsScripts.cs @@ -33,13 +33,22 @@ namespace CSF.Screenplay.Selenium.StoredScripts /// public interface IRunsScripts { + /// + /// Executes the script exposed by the given script provider and returns the result. + /// + /// The script result. + /// A JavaScript provider. + /// A web driver. + /// The script arguments. + object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments); + /// /// Executes the script and returns the result. /// /// The script result. /// A JavaScript. - /// A web driver that runs scripts. + /// A web driver. /// The script arguments. - object ExecuteScript(IProvidesScript script, IJavaScriptExecutor webDriver, params object[] arguments); + object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments); } } diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs index e1f7c93e..4418bcbb 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs @@ -37,6 +37,12 @@ public abstract class ScriptResource : IProvidesScript const string DefaultEntryPointName = "executeScript"; + /// + /// Gets the name of this script. + /// + /// The name. + public virtual string Name => GetType().Name; + /// /// Gets the name of the entry point to the script - this is the function exposed by /// . diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs index 821cce40..c2eb4db6 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs @@ -38,9 +38,27 @@ public class ScriptRunner : IRunsScripts /// /// The script result. /// A JavaScript. - /// A web driver that runs scripts. + /// A web driver. /// The script arguments. - public object ExecuteScript(IProvidesScript script, IJavaScriptExecutor webDriver, params object[] arguments) + public object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + if(webDriver == null) + throw new ArgumentNullException(nameof(webDriver)); + + var javaScriptRunner = GetJavaScriptExecutor(webDriver); + return javaScriptRunner.ExecuteScript(script, arguments); + } + + /// + /// Executes the script exposed by the given script provider and returns the result. + /// + /// The script result. + /// A JavaScript provider. + /// A web driver. + /// The script arguments. + public object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments) { if(script == null) throw new ArgumentNullException(nameof(script)); @@ -48,10 +66,20 @@ public object ExecuteScript(IProvidesScript script, IJavaScriptExecutor webDrive throw new ArgumentNullException(nameof(webDriver)); var runnableScript = GetRunnableScript(script); - return webDriver.ExecuteScript(runnableScript, arguments); + return ExecuteScript(runnableScript, webDriver, arguments); } string GetRunnableScript(IProvidesScript script) => String.Concat(script.GetScript(), Environment.NewLine, $"{script.GetEntryPointName()}(arguments);"); + + IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver) + { + var jsDriver = driver as IJavaScriptExecutor; + + if(jsDriver == null) + throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver)); + + return jsDriver; + } } } diff --git a/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs b/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs index 4f8da8d7..72d9a91a 100644 --- a/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs +++ b/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs @@ -53,7 +53,7 @@ protected override void PerformAs(IPerformer actor) } } - ExecuteJavaScriptAndGetResult GetAction() + IPerformableJavaScriptWithResult GetAction() { var script = Javascripts.GetDocumentReadyState; return Execute.TheJavaScript(script).AndGetTheResult(); From 6832f3419f4ecfe604beb85a6f2b1cd167635bc1 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 21:17:33 +0000 Subject: [PATCH 080/213] WIP #36 - Replace base controller with action filter --- .../ActionFilters/BaseUriAttribute.cs | 70 +++++++++++++++++++ .../CSF.Screenplay.WebTestWebsite.csproj | 3 +- .../Controllers/ControllerBase.cs | 16 ----- .../Controllers/HomeController.cs | 10 +-- .../Controllers/PageThreeController.cs | 24 +++---- .../Controllers/PageTwoController.cs | 34 ++++----- 6 files changed, 107 insertions(+), 50 deletions(-) create mode 100644 CSF.Screenplay.WebTestWebsite/ActionFilters/BaseUriAttribute.cs delete mode 100644 CSF.Screenplay.WebTestWebsite/Controllers/ControllerBase.cs diff --git a/CSF.Screenplay.WebTestWebsite/ActionFilters/BaseUriAttribute.cs b/CSF.Screenplay.WebTestWebsite/ActionFilters/BaseUriAttribute.cs new file mode 100644 index 00000000..184036dd --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/ActionFilters/BaseUriAttribute.cs @@ -0,0 +1,70 @@ +// +// BaseUrlAttribute.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Web.Mvc; +using CSF.Screenplay.WebTestWebsite.Models; + +namespace CSF.Screenplay.WebTestWebsite.ActionFilters +{ + public class BaseUriAttribute : ActionFilterAttribute + { + const string DefaultBaseUri = "http://localhost:8080/"; + + readonly string baseUri; + + public override void OnResultExecuting(ResultExecutingContext filterContext) + { + var viewResult = GetViewResult(filterContext); + if(viewResult == null) return; + + var baseModel = GetBaseModel(viewResult); + if(baseModel == null) return; + + baseModel.BaseUri = new Uri(baseUri); + + base.OnResultExecuting(filterContext); + } + + ViewResultBase GetViewResult(ResultExecutingContext filterContext) + => filterContext?.Result as ViewResultBase; + + ModelBase GetBaseModel(ViewResultBase viewResult) + => viewResult.Model as ModelBase; + + public BaseUriAttribute(string baseUri) + { + if(baseUri == null) + throw new ArgumentNullException(nameof(baseUri)); + + this.baseUri = baseUri; + } + + public BaseUriAttribute() + { + baseUri = DefaultBaseUri; + } + } +} diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index baa87bd8..944dedb1 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -127,6 +127,7 @@ + @@ -134,10 +135,10 @@ Global.asax - + diff --git a/CSF.Screenplay.WebTestWebsite/Controllers/ControllerBase.cs b/CSF.Screenplay.WebTestWebsite/Controllers/ControllerBase.cs deleted file mode 100644 index 22f8b07c..00000000 --- a/CSF.Screenplay.WebTestWebsite/Controllers/ControllerBase.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Web.Mvc; - -namespace CSF.Screenplay.WebTestWebsite.Controllers -{ - public class ControllerBase : Controller - { - protected virtual void PopulateModel(Models.ModelBase model) - { - if(model == null) - throw new ArgumentNullException(nameof(model)); - - model.BaseUri = new Uri("http://localhost:8080/"); - } - } -} diff --git a/CSF.Screenplay.WebTestWebsite/Controllers/HomeController.cs b/CSF.Screenplay.WebTestWebsite/Controllers/HomeController.cs index 0d308003..664bb11c 100644 --- a/CSF.Screenplay.WebTestWebsite/Controllers/HomeController.cs +++ b/CSF.Screenplay.WebTestWebsite/Controllers/HomeController.cs @@ -5,20 +5,22 @@ using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; +using CSF.Screenplay.WebTestWebsite.ActionFilters; using CSF.Screenplay.WebTestWebsite.Models; namespace CSF.Screenplay.WebTestWebsite.Controllers.Controllers { - public class HomeController : ControllerBase + public class HomeController : Controller { + [BaseUri] public ActionResult Index(int? delay) { if(delay.GetValueOrDefault() > 0) Thread.Sleep(TimeSpan.FromSeconds(delay.GetValueOrDefault())); - var model = new ModelBase(); - PopulateModel(model); - model.LoadingPause = delay.GetValueOrDefault(); + var model = new ModelBase { + LoadingPause = delay.GetValueOrDefault() + }; return View(model); } } diff --git a/CSF.Screenplay.WebTestWebsite/Controllers/PageThreeController.cs b/CSF.Screenplay.WebTestWebsite/Controllers/PageThreeController.cs index a3b6d678..4f56b793 100644 --- a/CSF.Screenplay.WebTestWebsite/Controllers/PageThreeController.cs +++ b/CSF.Screenplay.WebTestWebsite/Controllers/PageThreeController.cs @@ -1,19 +1,19 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using CSF.Screenplay.WebTestWebsite.ActionFilters; using CSF.Screenplay.WebTestWebsite.Models; -namespace CSF.Screenplay.WebTestWebsite.Controllers +namespace CSF.Screenplay.WebTestWebsite.Controllers { - public class PageThreeController : ControllerBase + public class PageThreeController : Controller { + [BaseUri] public ActionResult Index() { - var model = new ModelBase(); - PopulateModel(model); - return View(model); + return View(new ModelBase()); } - } -} + } +} diff --git a/CSF.Screenplay.WebTestWebsite/Controllers/PageTwoController.cs b/CSF.Screenplay.WebTestWebsite/Controllers/PageTwoController.cs index 56a6400e..13c22225 100644 --- a/CSF.Screenplay.WebTestWebsite/Controllers/PageTwoController.cs +++ b/CSF.Screenplay.WebTestWebsite/Controllers/PageTwoController.cs @@ -1,19 +1,19 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using CSF.Screenplay.WebTestWebsite.ActionFilters; using CSF.Screenplay.WebTestWebsite.Models; -namespace CSF.Screenplay.WebTestWebsite.Controllers -{ - public class PageTwoController : ControllerBase - { - public ActionResult Index() - { - var model = new ModelBase(); - PopulateModel(model); - return View(model); - } - } -} +namespace CSF.Screenplay.WebTestWebsite.Controllers +{ + public class PageTwoController : Controller + { + [BaseUri] + public ActionResult Index() + { + return View(new ModelBase()); + } + } +} From 5f28a27dbebed6bbdc6d82b7cc01adfb002ac999 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 21:18:37 +0000 Subject: [PATCH 081/213] WIP #36 - Add Jasmine test framework --- .../CSF.Screenplay.WebTestWebsite.csproj | 6 + .../Content/jasmine/jasmine.css | 58 + .../Content/jasmine/jasmine_favicon.png | Bin 0 -> 1486 bytes .../Scripts/jasmine/boot.js | 133 + .../Scripts/jasmine/console.js | 190 + .../Scripts/jasmine/jasmine-html.js | 499 ++ .../Scripts/jasmine/jasmine.js | 5001 +++++++++++++++++ CSF.Screenplay.WebTestWebsite/packages.config | 1 + 8 files changed, 5888 insertions(+) create mode 100644 CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine.css create mode 100644 CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine_favicon.png create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/jasmine/boot.js create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/jasmine/console.js create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine-html.js create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine.js diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index 944dedb1..81ccd0cb 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -148,6 +148,12 @@ + + + + + + diff --git a/CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine.css b/CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine.css new file mode 100644 index 00000000..63199827 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine.css @@ -0,0 +1,58 @@ +body { overflow-y: scroll; } + +.jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } +.jasmine_html-reporter a { text-decoration: none; } +.jasmine_html-reporter a:hover { text-decoration: underline; } +.jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } +.jasmine_html-reporter .jasmine-banner, .jasmine_html-reporter .jasmine-symbol-summary, .jasmine_html-reporter .jasmine-summary, .jasmine_html-reporter .jasmine-result-message, .jasmine_html-reporter .jasmine-spec .jasmine-description, .jasmine_html-reporter .jasmine-spec-detail .jasmine-description, .jasmine_html-reporter .jasmine-alert .jasmine-bar, .jasmine_html-reporter .jasmine-stack-trace { padding-left: 9px; padding-right: 9px; } +.jasmine_html-reporter .jasmine-banner { position: relative; } +.jasmine_html-reporter .jasmine-banner .jasmine-title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } +.jasmine_html-reporter .jasmine-banner .jasmine-version { margin-left: 14px; position: relative; top: 6px; } +.jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } +.jasmine_html-reporter .jasmine-version { color: #aaa; } +.jasmine_html-reporter .jasmine-banner { margin-top: 14px; } +.jasmine_html-reporter .jasmine-duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } +.jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } +.jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; } +.jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; } +.jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } +.jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; } +.jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } +.jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; } +.jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } +.jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; } +.jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; } +.jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; } +.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; } +.jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; } +.jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; } +.jasmine_html-reporter .jasmine-bar a { color: white; } +.jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list, .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures { display: none; } +.jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list, .jasmine_html-reporter.jasmine-failure-list .jasmine-summary { display: none; } +.jasmine_html-reporter .jasmine-results { margin-top: 14px; } +.jasmine_html-reporter .jasmine-summary { margin-top: 14px; } +.jasmine_html-reporter .jasmine-summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } +.jasmine_html-reporter .jasmine-summary ul.jasmine-suite { margin-top: 7px; margin-bottom: 7px; } +.jasmine_html-reporter .jasmine-summary li.jasmine-passed a { color: #007069; } +.jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; } +.jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; } +.jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; } +.jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; } +.jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; } +.jasmine_html-reporter .jasmine-suite { margin-top: 14px; } +.jasmine_html-reporter .jasmine-suite a { color: #333; } +.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; } +.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; } +.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; } +.jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; } +.jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; } +.jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } diff --git a/CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine_favicon.png b/CSF.Screenplay.WebTestWebsite/Content/jasmine/jasmine_favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..3b84583be4b9d5ae9cd5cae07b2dbaa5ebb0ad1c GIT binary patch literal 1486 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0VDb;}332@o1PuQh8X8uGu4-^- zn3*=SA+%wV=cI;&hMB$%-Lc(MLmN8%IwwUpbcA;F2Q;)twND9bn-tpC9oR4-vb8I; zp+Bg#FSKP+P(yD-%f!%zo}iZgh=%Ua=KkP@iNVbiLYsSn8~VeW`+}P$1~&ACHcbd_ z=nZb_32o{NZkZ6&1k^hrxT!a&r8lIdAIJ@9nh?|iRMsET+#A%`AKKg-(%2K)*cZ|~ zA-J&*$PEUH08MM`4Q=iVY3vVfhN$TUscGs5sR8P31X|G_+SnTcv<0XVC=Rr!u|K4# zHyCJU6UYRR;%2BtKv^I=q#2|DECn_k@wXU|=@ zeD&J(8#iy=zH|5fgNKiwJbm`!<*V0k-oF3v@zdvTKYsrD^Y>rGdNDU(R>|^oaSW-5 z%f0Y2x+hSk{p0&HA;E60Oq1S3r7U;(X3MH#?W9nxXzk)srlC4P;cZYe&v*G}mgi%< ze(bTl{@&_)cX8b-kvX%ff9D22e*M~7edm|;|Jb8m2JBzkzKiSBKR0n*?XSyM6fxZY zJ4bb;vGKRiKP(ztq3sJx9iq$Re`-EEQU0KE$sdyqayzp6H-7x+oGKZ_6;hQ_Y|p&y z7o`N7g@ z8Yl1HKL;mFo4BdxljF1}KbfMR6nNdLyPnEap1MqBdI?{g$L58$P8+wftLX5R70)7n`#pwItnbma$w{%`M(`wpsu2rJ60rdGCc> z+~lm)viMYM`=uXwK_$`#_UtRZMO=2-IV)l2vc~)doyPvg-RmxtACQ#v{7}5$&isV+ zPws~n?@yNGy#H1=vTI?;CAl9~9#VgqJ+7`4y~R+Wyj0U+){?lm9r6mtf0gl_VmUW^ z%eje%?jM%^eLuUg#ybXaQM{yQy&8UgiQ`HQ+=iTpjfd0iJ@ ssyFi&dF4%9dEry;pNN)Q>$jg_dr3r;PHA*CFc&d+y85}Sb4q9e0J812W&i*H literal 0 HcmV?d00001 diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/boot.js b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/boot.js new file mode 100644 index 00000000..d9b5a80b --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/boot.js @@ -0,0 +1,133 @@ +/** + Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. + + If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. + + The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. + + [jasmine-gem]: http://github.com/pivotal/jasmine-gem + */ + +(function() { + + /** + * ## Require & Instantiate + * + * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. + */ + window.jasmine = jasmineRequire.core(jasmineRequire); + + /** + * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. + */ + jasmineRequire.html(jasmine); + + /** + * Create the Jasmine environment. This is used to run all specs in a project. + */ + var env = jasmine.getEnv(); + + /** + * ## The Global Interface + * + * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. + */ + var jasmineInterface = jasmineRequire.interface(jasmine, env); + + /** + * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. + */ + extend(window, jasmineInterface); + + /** + * ## Runner Parameters + * + * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. + */ + + var queryString = new jasmine.QueryString({ + getWindowLocation: function() { return window.location; } + }); + + var filterSpecs = !!queryString.getParam("spec"); + + var catchingExceptions = queryString.getParam("catch"); + env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); + + var throwingExpectationFailures = queryString.getParam("throwFailures"); + env.throwOnExpectationFailure(throwingExpectationFailures); + + var random = queryString.getParam("random"); + env.randomizeTests(random); + + var seed = queryString.getParam("seed"); + if (seed) { + env.seed(seed); + } + + /** + * ## Reporters + * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). + */ + var htmlReporter = new jasmine.HtmlReporter({ + env: env, + onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, + onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, + onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); }, + addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, + getContainer: function() { return document.body; }, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); }, + timer: new jasmine.Timer(), + filterSpecs: filterSpecs + }); + + /** + * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. + */ + env.addReporter(jasmineInterface.jsApiReporter); + env.addReporter(htmlReporter); + + /** + * Filter which specs will be run by matching the start of the full name against the `spec` query param. + */ + var specFilter = new jasmine.HtmlSpecFilter({ + filterString: function() { return queryString.getParam("spec"); } + }); + + env.specFilter = function(spec) { + return specFilter.matches(spec.getFullName()); + }; + + /** + * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. + */ + window.setTimeout = window.setTimeout; + window.setInterval = window.setInterval; + window.clearTimeout = window.clearTimeout; + window.clearInterval = window.clearInterval; + + /** + * ## Execution + * + * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. + */ + var currentWindowOnload = window.onload; + + window.onload = function() { + if (currentWindowOnload) { + currentWindowOnload(); + } + htmlReporter.initialize(); + env.execute(); + }; + + /** + * Helper function for readability above. + */ + function extend(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; + } + +}()); diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/console.js b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/console.js new file mode 100644 index 00000000..38ad952d --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/console.js @@ -0,0 +1,190 @@ +/* +Copyright (c) 2008-2017 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +function getJasmineRequireObj() { + if (typeof module !== 'undefined' && module.exports) { + return exports; + } else { + window.jasmineRequire = window.jasmineRequire || {}; + return window.jasmineRequire; + } +} + +getJasmineRequireObj().console = function(jRequire, j$) { + j$.ConsoleReporter = jRequire.ConsoleReporter(); +}; + +getJasmineRequireObj().ConsoleReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + function ConsoleReporter(options) { + var print = options.print, + showColors = options.showColors || false, + onComplete = options.onComplete || function() {}, + timer = options.timer || noopTimer, + specCount, + failureCount, + failedSpecs = [], + pendingCount, + ansi = { + green: '\x1B[32m', + red: '\x1B[31m', + yellow: '\x1B[33m', + none: '\x1B[0m' + }, + failedSuites = []; + + print('ConsoleReporter is deprecated and will be removed in a future version.'); + + this.jasmineStarted = function() { + specCount = 0; + failureCount = 0; + pendingCount = 0; + print('Started'); + printNewline(); + timer.start(); + }; + + this.jasmineDone = function() { + printNewline(); + for (var i = 0; i < failedSpecs.length; i++) { + specFailureDetails(failedSpecs[i]); + } + + if(specCount > 0) { + printNewline(); + + var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + + failureCount + ' ' + plural('failure', failureCount); + + if (pendingCount) { + specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); + } + + print(specCounts); + } else { + print('No specs found'); + } + + printNewline(); + var seconds = timer.elapsed() / 1000; + print('Finished in ' + seconds + ' ' + plural('second', seconds)); + printNewline(); + + for(i = 0; i < failedSuites.length; i++) { + suiteFailureDetails(failedSuites[i]); + } + + onComplete(failureCount === 0); + }; + + this.specDone = function(result) { + specCount++; + + if (result.status == 'pending') { + pendingCount++; + print(colored('yellow', '*')); + return; + } + + if (result.status == 'passed') { + print(colored('green', '.')); + return; + } + + if (result.status == 'failed') { + failureCount++; + failedSpecs.push(result); + print(colored('red', 'F')); + } + }; + + this.suiteDone = function(result) { + if (result.failedExpectations && result.failedExpectations.length > 0) { + failureCount++; + failedSuites.push(result); + } + }; + + return this; + + function printNewline() { + print('\n'); + } + + function colored(color, str) { + return showColors ? (ansi[color] + str + ansi.none) : str; + } + + function plural(str, count) { + return count == 1 ? str : str + 's'; + } + + function repeat(thing, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(thing); + } + return arr; + } + + function indent(str, spaces) { + var lines = (str || '').split('\n'); + var newArr = []; + for (var i = 0; i < lines.length; i++) { + newArr.push(repeat(' ', spaces).join('') + lines[i]); + } + return newArr.join('\n'); + } + + function specFailureDetails(result) { + printNewline(); + print(result.fullName); + + for (var i = 0; i < result.failedExpectations.length; i++) { + var failedExpectation = result.failedExpectations[i]; + printNewline(); + print(indent(failedExpectation.message, 2)); + print(indent(failedExpectation.stack, 2)); + } + + printNewline(); + } + + function suiteFailureDetails(result) { + for (var i = 0; i < result.failedExpectations.length; i++) { + printNewline(); + print(colored('red', 'An error was thrown in an afterAll')); + printNewline(); + print(colored('red', 'AfterAll ' + result.failedExpectations[i].message)); + + } + printNewline(); + } + } + + return ConsoleReporter; +}; diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine-html.js b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine-html.js new file mode 100644 index 00000000..90407cc0 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine-html.js @@ -0,0 +1,499 @@ +/* +Copyright (c) 2008-2017 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +jasmineRequire.html = function(j$) { + j$.ResultsNode = jasmineRequire.ResultsNode(); + j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); + j$.QueryString = jasmineRequire.QueryString(); + j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); +}; + +jasmineRequire.HtmlReporter = function(j$) { + + var noopTimer = { + start: function() {}, + elapsed: function() { return 0; } + }; + + function HtmlReporter(options) { + var env = options.env || {}, + getContainer = options.getContainer, + createElement = options.createElement, + createTextNode = options.createTextNode, + onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, + onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, + onRandomClick = options.onRandomClick || function() {}, + addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, + filterSpecs = options.filterSpecs, + timer = options.timer || noopTimer, + results = [], + specsExecuted = 0, + failureCount = 0, + pendingSpecCount = 0, + htmlReporterMain, + symbols, + failedSuites = []; + + this.initialize = function() { + clearPrior(); + htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, + createDom('div', {className: 'jasmine-banner'}, + createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}), + createDom('span', {className: 'jasmine-version'}, j$.version) + ), + createDom('ul', {className: 'jasmine-symbol-summary'}), + createDom('div', {className: 'jasmine-alert'}), + createDom('div', {className: 'jasmine-results'}, + createDom('div', {className: 'jasmine-failures'}) + ) + ); + getContainer().appendChild(htmlReporterMain); + }; + + var totalSpecsDefined; + this.jasmineStarted = function(options) { + totalSpecsDefined = options.totalSpecsDefined || 0; + timer.start(); + }; + + var summary = createDom('div', {className: 'jasmine-summary'}); + + var topResults = new j$.ResultsNode({}, '', null), + currentParent = topResults; + + this.suiteStarted = function(result) { + currentParent.addChild(result, 'suite'); + currentParent = currentParent.last(); + }; + + this.suiteDone = function(result) { + if (result.status == 'failed') { + failedSuites.push(result); + } + + if (currentParent == topResults) { + return; + } + + currentParent = currentParent.parent; + }; + + this.specStarted = function(result) { + currentParent.addChild(result, 'spec'); + }; + + var failures = []; + this.specDone = function(result) { + if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); + } + + if (result.status != 'disabled') { + specsExecuted++; + } + + if (!symbols){ + symbols = find('.jasmine-symbol-summary'); + } + + symbols.appendChild(createDom('li', { + className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status, + id: 'spec_' + result.id, + title: result.fullName + } + )); + + if (result.status == 'failed') { + failureCount++; + + var failure = + createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, + createDom('div', {className: 'jasmine-description'}, + createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) + ), + createDom('div', {className: 'jasmine-messages'}) + ); + var messages = failure.childNodes[1]; + + for (var i = 0; i < result.failedExpectations.length; i++) { + var expectation = result.failedExpectations[i]; + messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message)); + messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack)); + } + + failures.push(failure); + } + + if (result.status == 'pending') { + pendingSpecCount++; + } + }; + + this.jasmineDone = function(doneResult) { + var banner = find('.jasmine-banner'); + var alert = find('.jasmine-alert'); + var order = doneResult && doneResult.order; + alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); + + banner.appendChild( + createDom('div', { className: 'jasmine-run-options' }, + createDom('span', { className: 'jasmine-trigger' }, 'Options'), + createDom('div', { className: 'jasmine-payload' }, + createDom('div', { className: 'jasmine-exceptions' }, + createDom('input', { + className: 'jasmine-raise', + id: 'jasmine-raise-exceptions', + type: 'checkbox' + }), + createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')), + createDom('div', { className: 'jasmine-throw-failures' }, + createDom('input', { + className: 'jasmine-throw', + id: 'jasmine-throw-failures', + type: 'checkbox' + }), + createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')), + createDom('div', { className: 'jasmine-random-order' }, + createDom('input', { + className: 'jasmine-random', + id: 'jasmine-random-order', + type: 'checkbox' + }), + createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')) + ) + )); + + var raiseCheckbox = find('#jasmine-raise-exceptions'); + + raiseCheckbox.checked = !env.catchingExceptions(); + raiseCheckbox.onclick = onRaiseExceptionsClick; + + var throwCheckbox = find('#jasmine-throw-failures'); + throwCheckbox.checked = env.throwingExpectationFailures(); + throwCheckbox.onclick = onThrowExpectationsClick; + + var randomCheckbox = find('#jasmine-random-order'); + randomCheckbox.checked = env.randomTests(); + randomCheckbox.onclick = onRandomClick; + + var optionsMenu = find('.jasmine-run-options'), + optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'), + optionsPayload = optionsMenu.querySelector('.jasmine-payload'), + isOpen = /\bjasmine-open\b/; + + optionsTrigger.onclick = function() { + if (isOpen.test(optionsPayload.className)) { + optionsPayload.className = optionsPayload.className.replace(isOpen, ''); + } else { + optionsPayload.className += ' jasmine-open'; + } + }; + + if (specsExecuted < totalSpecsDefined) { + var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; + var skippedLink = order && order.random ? '?random=true' : '?'; + alert.appendChild( + createDom('span', {className: 'jasmine-bar jasmine-skipped'}, + createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage) + ) + ); + } + var statusBarMessage = ''; + var statusBarClassName = 'jasmine-bar '; + + if (totalSpecsDefined > 0) { + statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); + if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } + statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed'; + } else { + statusBarClassName += 'jasmine-skipped'; + statusBarMessage += 'No specs found'; + } + + var seedBar; + if (order && order.random) { + seedBar = createDom('span', {className: 'jasmine-seed-bar'}, + ', randomized with seed ', + createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed) + ); + } + + alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar)); + + var errorBarClassName = 'jasmine-bar jasmine-errored'; + var errorBarMessagePrefix = 'AfterAll '; + + for(var i = 0; i < failedSuites.length; i++) { + var failedSuite = failedSuites[i]; + for(var j = 0; j < failedSuite.failedExpectations.length; j++) { + alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message)); + } + } + + var globalFailures = (doneResult && doneResult.failedExpectations) || []; + for(i = 0; i < globalFailures.length; i++) { + var failure = globalFailures[i]; + alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message)); + } + + var results = find('.jasmine-results'); + results.appendChild(summary); + + summaryList(topResults, summary); + + function summaryList(resultsTree, domParent) { + var specListNode; + for (var i = 0; i < resultsTree.children.length; i++) { + var resultNode = resultsTree.children[i]; + if (filterSpecs && !hasActiveSpec(resultNode)) { + continue; + } + if (resultNode.type == 'suite') { + var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id}, + createDom('li', {className: 'jasmine-suite-detail'}, + createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + ) + ); + + summaryList(resultNode, suiteListNode); + domParent.appendChild(suiteListNode); + } + if (resultNode.type == 'spec') { + if (domParent.getAttribute('class') != 'jasmine-specs') { + specListNode = createDom('ul', {className: 'jasmine-specs'}); + domParent.appendChild(specListNode); + } + var specDescription = resultNode.result.description; + if(noExpectations(resultNode.result)) { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } + if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { + specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; + } + specListNode.appendChild( + createDom('li', { + className: 'jasmine-' + resultNode.result.status, + id: 'spec-' + resultNode.result.id + }, + createDom('a', {href: specHref(resultNode.result)}, specDescription) + ) + ); + } + } + } + + if (failures.length) { + alert.appendChild( + createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'}, + createDom('span', {}, 'Spec List | '), + createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures'))); + alert.appendChild( + createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'}, + createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'), + createDom('span', {}, ' | Failures '))); + + find('.jasmine-failures-menu').onclick = function() { + setMenuModeTo('jasmine-failure-list'); + }; + find('.jasmine-spec-list-menu').onclick = function() { + setMenuModeTo('jasmine-spec-list'); + }; + + setMenuModeTo('jasmine-failure-list'); + + var failureNode = find('.jasmine-failures'); + for (i = 0; i < failures.length; i++) { + failureNode.appendChild(failures[i]); + } + } + }; + + return this; + + function find(selector) { + return getContainer().querySelector('.jasmine_html-reporter ' + selector); + } + + function clearPrior() { + // return the reporter + var oldReporter = find(''); + + if(oldReporter) { + getContainer().removeChild(oldReporter); + } + } + + function createDom(type, attrs, childrenVarArgs) { + var el = createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(createTextNode(child)); + } else { + if (child) { + el.appendChild(child); + } + } + } + + for (var attr in attrs) { + if (attr == 'className') { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; + } + + function pluralize(singular, count) { + var word = (count == 1 ? singular : singular + 's'); + + return '' + count + ' ' + word; + } + + function specHref(result) { + return addToExistingQueryString('spec', result.fullName); + } + + function seedHref(seed) { + return addToExistingQueryString('seed', seed); + } + + function defaultQueryString(key, value) { + return '?' + key + '=' + value; + } + + function setMenuModeTo(mode) { + htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); + } + + function noExpectations(result) { + return (result.failedExpectations.length + result.passedExpectations.length) === 0 && + result.status === 'passed'; + } + + function hasActiveSpec(resultNode) { + if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') { + return true; + } + + if (resultNode.type == 'suite') { + for (var i = 0, j = resultNode.children.length; i < j; i++) { + if (hasActiveSpec(resultNode.children[i])) { + return true; + } + } + } + } + } + + return HtmlReporter; +}; + +jasmineRequire.HtmlSpecFilter = function() { + function HtmlSpecFilter(options) { + var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); + var filterPattern = new RegExp(filterString); + + this.matches = function(specName) { + return filterPattern.test(specName); + }; + } + + return HtmlSpecFilter; +}; + +jasmineRequire.ResultsNode = function() { + function ResultsNode(result, type, parent) { + this.result = result; + this.type = type; + this.parent = parent; + + this.children = []; + + this.addChild = function(result, type) { + this.children.push(new ResultsNode(result, type, this)); + }; + + this.last = function() { + return this.children[this.children.length - 1]; + }; + } + + return ResultsNode; +}; + +jasmineRequire.QueryString = function() { + function QueryString(options) { + + this.navigateWithNewParam = function(key, value) { + options.getWindowLocation().search = this.fullStringWithNewParam(key, value); + }; + + this.fullStringWithNewParam = function(key, value) { + var paramMap = queryStringToParamMap(); + paramMap[key] = value; + return toQueryString(paramMap); + }; + + this.getParam = function(key) { + return queryStringToParamMap()[key]; + }; + + return this; + + function toQueryString(paramMap) { + var qStrPairs = []; + for (var prop in paramMap) { + qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); + } + return '?' + qStrPairs.join('&'); + } + + function queryStringToParamMap() { + var paramStr = options.getWindowLocation().search.substring(1), + params = [], + paramMap = {}; + + if (paramStr.length > 0) { + params = paramStr.split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + var value = decodeURIComponent(p[1]); + if (value === 'true' || value === 'false') { + value = JSON.parse(value); + } + paramMap[decodeURIComponent(p[0])] = value; + } + } + + return paramMap; + } + + } + + return QueryString; +}; diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine.js b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine.js new file mode 100644 index 00000000..82901601 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/jasmine/jasmine.js @@ -0,0 +1,5001 @@ +/* +Copyright (c) 2008-2017 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +var getJasmineRequireObj = (function (jasmineGlobal) { + var jasmineRequire; + + if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') { + if (typeof global !== 'undefined') { + jasmineGlobal = global; + } else { + jasmineGlobal = {}; + } + jasmineRequire = exports; + } else { + if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') { + jasmineGlobal = window; + } + jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {}; + } + + function getJasmineRequire() { + return jasmineRequire; + } + + getJasmineRequire().core = function(jRequire) { + var j$ = {}; + + jRequire.base(j$, jasmineGlobal); + j$.util = jRequire.util(); + j$.errors = jRequire.errors(); + j$.formatErrorMsg = jRequire.formatErrorMsg(); + j$.Any = jRequire.Any(j$); + j$.Anything = jRequire.Anything(j$); + j$.CallTracker = jRequire.CallTracker(j$); + j$.MockDate = jRequire.MockDate(); + j$.getClearStack = jRequire.clearStack(j$); + j$.Clock = jRequire.Clock(); + j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); + j$.Env = jRequire.Env(j$); + j$.ExceptionFormatter = jRequire.ExceptionFormatter(); + j$.Expectation = jRequire.Expectation(); + j$.buildExpectationResult = jRequire.buildExpectationResult(); + j$.JsApiReporter = jRequire.JsApiReporter(); + j$.matchersUtil = jRequire.matchersUtil(j$); + j$.ObjectContaining = jRequire.ObjectContaining(j$); + j$.ArrayContaining = jRequire.ArrayContaining(j$); + j$.pp = jRequire.pp(j$); + j$.QueueRunner = jRequire.QueueRunner(j$); + j$.ReportDispatcher = jRequire.ReportDispatcher(); + j$.Spec = jRequire.Spec(j$); + j$.Spy = jRequire.Spy(j$); + j$.SpyRegistry = jRequire.SpyRegistry(j$); + j$.SpyStrategy = jRequire.SpyStrategy(j$); + j$.StringMatching = jRequire.StringMatching(j$); + j$.Suite = jRequire.Suite(j$); + j$.Timer = jRequire.Timer(); + j$.TreeProcessor = jRequire.TreeProcessor(); + j$.version = jRequire.version(); + j$.Order = jRequire.Order(); + j$.DiffBuilder = jRequire.DiffBuilder(j$); + j$.NullDiffBuilder = jRequire.NullDiffBuilder(j$); + j$.ObjectPath = jRequire.ObjectPath(j$); + j$.GlobalErrors = jRequire.GlobalErrors(j$); + + j$.matchers = jRequire.requireMatchers(jRequire, j$); + + return j$; + }; + + return getJasmineRequire; +})(this); + +getJasmineRequireObj().requireMatchers = function(jRequire, j$) { + var availableMatchers = [ + 'toBe', + 'toBeCloseTo', + 'toBeDefined', + 'toBeFalsy', + 'toBeGreaterThan', + 'toBeGreaterThanOrEqual', + 'toBeLessThan', + 'toBeLessThanOrEqual', + 'toBeNaN', + 'toBeNegativeInfinity', + 'toBeNull', + 'toBePositiveInfinity', + 'toBeTruthy', + 'toBeUndefined', + 'toContain', + 'toEqual', + 'toHaveBeenCalled', + 'toHaveBeenCalledBefore', + 'toHaveBeenCalledTimes', + 'toHaveBeenCalledWith', + 'toMatch', + 'toThrow', + 'toThrowError' + ], + matchers = {}; + + for (var i = 0; i < availableMatchers.length; i++) { + var name = availableMatchers[i]; + matchers[name] = jRequire[name](j$); + } + + return matchers; +}; + +getJasmineRequireObj().base = function(j$, jasmineGlobal) { + j$.unimplementedMethod_ = function() { + throw new Error('unimplemented method'); + }; + + /** + * Maximum object depth the pretty printer will print to. + * Set this to a lower value to speed up pretty printing if you have large objects. + * @name jasmine.MAX_PRETTY_PRINT_DEPTH + */ + j$.MAX_PRETTY_PRINT_DEPTH = 40; + /** + * Maximum number of array elements to display when pretty printing objects. + * Elements past this number will be ellipised. + * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH + */ + j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; + /** + * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete. + * @name jasmine.DEFAULT_TIMEOUT_INTERVAL + */ + j$.DEFAULT_TIMEOUT_INTERVAL = 5000; + + j$.getGlobal = function() { + return jasmineGlobal; + }; + + /** + * Get the currently booted Jasmine Environment. + * + * @name jasmine.getEnv + * @function + * @return {Env} + */ + j$.getEnv = function(options) { + var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); + //jasmine. singletons in here (setTimeout blah blah). + return env; + }; + + j$.isArray_ = function(value) { + return j$.isA_('Array', value); + }; + + j$.isObject_ = function(value) { + return !j$.util.isUndefined(value) && value !== null && j$.isA_('Object', value); + }; + + j$.isString_ = function(value) { + return j$.isA_('String', value); + }; + + j$.isNumber_ = function(value) { + return j$.isA_('Number', value); + }; + + j$.isFunction_ = function(value) { + return j$.isA_('Function', value); + }; + + j$.isA_ = function(typeName, value) { + return j$.getType_(value) === '[object ' + typeName + ']'; + }; + + j$.getType_ = function(value) { + return Object.prototype.toString.apply(value); + }; + + j$.isDomNode = function(obj) { + return obj.nodeType > 0; + }; + + j$.fnNameFor = function(func) { + if (func.name) { + return func.name; + } + + var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/); + return matches ? matches[1] : ''; + }; + + /** + * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), + * that will succeed if the actual value being compared is an instance of the specified class/constructor. + * @name jasmine.any + * @function + * @param {Constructor} clazz - The constructor to check against. + */ + j$.any = function(clazz) { + return new j$.Any(clazz); + }; + + /** + * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), + * that will succeed if the actual value being compared is not `null` and not `undefined`. + * @name jasmine.anything + * @function + */ + j$.anything = function() { + return new j$.Anything(); + }; + + /** + * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), + * that will succeed if the actual value being compared contains at least the keys and values. + * @name jasmine.objectContaining + * @function + * @param {Object} sample - The subset of properties that _must_ be in the actual. + */ + j$.objectContaining = function(sample) { + return new j$.ObjectContaining(sample); + }; + + /** + * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), + * that will succeed if the actual value is a `String` that matches the `RegExp` or `String`. + * @name jasmine.stringMatching + * @function + * @param {RegExp|String} expected + */ + j$.stringMatching = function(expected) { + return new j$.StringMatching(expected); + }; + + /** + * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), + * that will succeed if the actual value is an `Array` that contains at least the elements in the sample. + * @name jasmine.arrayContaining + * @function + * @param {Array} sample + */ + j$.arrayContaining = function(sample) { + return new j$.ArrayContaining(sample); + }; + + /** + * Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it. + * @name jasmine.createSpy + * @function + * @param {String} [name] - Name to give the spy. This will be displayed in failure messages. + * @param {Function} [originalFn] - Function to act as the real implementation. + * @return {Spy} + */ + j$.createSpy = function(name, originalFn) { + return j$.Spy(name, originalFn); + }; + + j$.isSpy = function(putativeSpy) { + if (!putativeSpy) { + return false; + } + return putativeSpy.and instanceof j$.SpyStrategy && + putativeSpy.calls instanceof j$.CallTracker; + }; + + /** + * Create an object with multiple {@link Spy}s as its members. + * @name jasmine.createSpyObj + * @function + * @param {String} [baseName] - Base name for the spies in the object. + * @param {String[]|Object} methodNames - Array of method names to create spies for, or Object whose keys will be method names and values the {@link Spy#and#returnValue|returnValue}. + * @return {Object} + */ + j$.createSpyObj = function(baseName, methodNames) { + var baseNameIsCollection = j$.isObject_(baseName) || j$.isArray_(baseName); + + if (baseNameIsCollection && j$.util.isUndefined(methodNames)) { + methodNames = baseName; + baseName = 'unknown'; + } + + var obj = {}; + var spiesWereSet = false; + + if (j$.isArray_(methodNames)) { + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); + spiesWereSet = true; + } + } else if (j$.isObject_(methodNames)) { + for (var key in methodNames) { + if (methodNames.hasOwnProperty(key)) { + obj[key] = j$.createSpy(baseName + '.' + key); + obj[key].and.returnValue(methodNames[key]); + spiesWereSet = true; + } + } + } + + if (!spiesWereSet) { + throw 'createSpyObj requires a non-empty array or object of method names to create spies for'; + } + + return obj; + }; +}; + +getJasmineRequireObj().util = function() { + + var util = {}; + + util.inherit = function(childClass, parentClass) { + var Subclass = function() { + }; + Subclass.prototype = parentClass.prototype; + childClass.prototype = new Subclass(); + }; + + util.htmlEscape = function(str) { + if (!str) { + return str; + } + return str.replace(/&/g, '&') + .replace(//g, '>'); + }; + + util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) { + arrayOfArgs.push(args[i]); + } + return arrayOfArgs; + }; + + util.isUndefined = function(obj) { + return obj === void 0; + }; + + util.arrayContains = function(array, search) { + var i = array.length; + while (i--) { + if (array[i] === search) { + return true; + } + } + return false; + }; + + util.clone = function(obj) { + if (Object.prototype.toString.apply(obj) === '[object Array]') { + return obj.slice(); + } + + var cloned = {}; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + cloned[prop] = obj[prop]; + } + } + + return cloned; + }; + + util.getPropertyDescriptor = function(obj, methodName) { + var descriptor, + proto = obj; + + do { + descriptor = Object.getOwnPropertyDescriptor(proto, methodName); + proto = Object.getPrototypeOf(proto); + } while (!descriptor && proto); + + return descriptor; + }; + + util.objectDifference = function(obj, toRemove) { + var diff = {}; + + for (var key in obj) { + if (util.has(obj, key) && !util.has(toRemove, key)) { + diff[key] = obj[key]; + } + } + + return diff; + }; + + util.has = function(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + }; + + return util; +}; + +getJasmineRequireObj().Spec = function(j$) { + function Spec(attrs) { + this.expectationFactory = attrs.expectationFactory; + this.resultCallback = attrs.resultCallback || function() {}; + this.id = attrs.id; + this.description = attrs.description || ''; + this.queueableFn = attrs.queueableFn; + this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; }; + this.userContext = attrs.userContext || function() { return {}; }; + this.onStart = attrs.onStart || function() {}; + this.getSpecName = attrs.getSpecName || function() { return ''; }; + this.expectationResultFactory = attrs.expectationResultFactory || function() { }; + this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; + this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; + this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; + + if (!this.queueableFn.fn) { + this.pend(); + } + + this.result = { + id: this.id, + description: this.description, + fullName: this.getFullName(), + failedExpectations: [], + passedExpectations: [], + pendingReason: '' + }; + } + + Spec.prototype.addExpectationResult = function(passed, data, isError) { + var expectationResult = this.expectationResultFactory(data); + if (passed) { + this.result.passedExpectations.push(expectationResult); + } else { + this.result.failedExpectations.push(expectationResult); + + if (this.throwOnExpectationFailure && !isError) { + throw new j$.errors.ExpectationFailed(); + } + } + }; + + Spec.prototype.expect = function(actual) { + return this.expectationFactory(actual, this); + }; + + Spec.prototype.execute = function(onComplete, enabled) { + var self = this; + + this.onStart(this); + + if (!this.isExecutable() || this.markedPending || enabled === false) { + complete(enabled); + return; + } + + var fns = this.beforeAndAfterFns(); + var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters); + + this.queueRunnerFactory({ + queueableFns: allFns, + onException: function() { self.onException.apply(self, arguments); }, + onComplete: complete, + userContext: this.userContext() + }); + + function complete(enabledAgain) { + self.result.status = self.status(enabledAgain); + self.resultCallback(self.result); + + if (onComplete) { + onComplete(); + } + } + }; + + Spec.prototype.onException = function onException(e) { + if (Spec.isPendingSpecException(e)) { + this.pend(extractCustomPendingMessage(e)); + return; + } + + if (e instanceof j$.errors.ExpectationFailed) { + return; + } + + this.addExpectationResult(false, { + matcherName: '', + passed: false, + expected: '', + actual: '', + error: e + }, true); + }; + + Spec.prototype.disable = function() { + this.disabled = true; + }; + + Spec.prototype.pend = function(message) { + this.markedPending = true; + if (message) { + this.result.pendingReason = message; + } + }; + + Spec.prototype.getResult = function() { + this.result.status = this.status(); + return this.result; + }; + + Spec.prototype.status = function(enabled) { + if (this.disabled || enabled === false) { + return 'disabled'; + } + + if (this.markedPending) { + return 'pending'; + } + + if (this.result.failedExpectations.length > 0) { + return 'failed'; + } else { + return 'passed'; + } + }; + + Spec.prototype.isExecutable = function() { + return !this.disabled; + }; + + Spec.prototype.getFullName = function() { + return this.getSpecName(this); + }; + + var extractCustomPendingMessage = function(e) { + var fullMessage = e.toString(), + boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage), + boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length; + + return fullMessage.substr(boilerplateEnd); + }; + + Spec.pendingSpecExceptionMessage = '=> marked Pending'; + + Spec.isPendingSpecException = function(e) { + return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); + }; + + return Spec; +}; + +if (typeof window == void 0 && typeof exports == 'object') { + exports.Spec = jasmineRequire.Spec; +} + +/*jshint bitwise: false*/ + +getJasmineRequireObj().Order = function() { + function Order(options) { + this.random = 'random' in options ? options.random : true; + var seed = this.seed = options.seed || generateSeed(); + this.sort = this.random ? randomOrder : naturalOrder; + + function naturalOrder(items) { + return items; + } + + function randomOrder(items) { + var copy = items.slice(); + copy.sort(function(a, b) { + return jenkinsHash(seed + a.id) - jenkinsHash(seed + b.id); + }); + return copy; + } + + function generateSeed() { + return String(Math.random()).slice(-5); + } + + // Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function + // used to get a different output when the key changes slighly. + // We use your return to sort the children randomly in a consistent way when + // used in conjunction with a seed + + function jenkinsHash(key) { + var hash, i; + for(hash = i = 0; i < key.length; ++i) { + hash += key.charCodeAt(i); + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return hash; + } + + } + + return Order; +}; + +getJasmineRequireObj().Env = function(j$) { + /** + * _Note:_ Do not construct this directly, Jasmine will make one during booting. + * @name Env + * @classdesc The Jasmine environment + * @constructor + */ + function Env(options) { + options = options || {}; + + var self = this; + var global = options.global || j$.getGlobal(); + + var totalSpecsDefined = 0; + + var catchExceptions = true; + + var realSetTimeout = j$.getGlobal().setTimeout; + var realClearTimeout = j$.getGlobal().clearTimeout; + var clearStack = j$.getClearStack(j$.getGlobal()); + this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global)); + + var runnableResources = {}; + + var currentSpec = null; + var currentlyExecutingSuites = []; + var currentDeclarationSuite = null; + var throwOnExpectationFailure = false; + var random = false; + var seed = null; + + var currentSuite = function() { + return currentlyExecutingSuites[currentlyExecutingSuites.length - 1]; + }; + + var currentRunnable = function() { + return currentSpec || currentSuite(); + }; + + var reporter = new j$.ReportDispatcher([ + 'jasmineStarted', + 'jasmineDone', + 'suiteStarted', + 'suiteDone', + 'specStarted', + 'specDone' + ]); + + var globalErrors = new j$.GlobalErrors(); + + this.specFilter = function() { + return true; + }; + + this.addCustomEqualityTester = function(tester) { + if(!currentRunnable()) { + throw new Error('Custom Equalities must be added in a before function or a spec'); + } + runnableResources[currentRunnable().id].customEqualityTesters.push(tester); + }; + + this.addMatchers = function(matchersToAdd) { + if(!currentRunnable()) { + throw new Error('Matchers must be added in a before function or a spec'); + } + var customMatchers = runnableResources[currentRunnable().id].customMatchers; + for (var matcherName in matchersToAdd) { + customMatchers[matcherName] = matchersToAdd[matcherName]; + } + }; + + j$.Expectation.addCoreMatchers(j$.matchers); + + var nextSpecId = 0; + var getNextSpecId = function() { + return 'spec' + nextSpecId++; + }; + + var nextSuiteId = 0; + var getNextSuiteId = function() { + return 'suite' + nextSuiteId++; + }; + + var expectationFactory = function(actual, spec) { + return j$.Expectation.Factory({ + util: j$.matchersUtil, + customEqualityTesters: runnableResources[spec.id].customEqualityTesters, + customMatchers: runnableResources[spec.id].customMatchers, + actual: actual, + addExpectationResult: addExpectationResult + }); + + function addExpectationResult(passed, result) { + return spec.addExpectationResult(passed, result); + } + }; + + var defaultResourcesForRunnable = function(id, parentRunnableId) { + var resources = {spies: [], customEqualityTesters: [], customMatchers: {}}; + + if(runnableResources[parentRunnableId]){ + resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters); + resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers); + } + + runnableResources[id] = resources; + }; + + var clearResourcesForRunnable = function(id) { + spyRegistry.clearSpies(); + delete runnableResources[id]; + }; + + var beforeAndAfterFns = function(suite) { + return function() { + var befores = [], + afters = []; + + while(suite) { + befores = befores.concat(suite.beforeFns); + afters = afters.concat(suite.afterFns); + + suite = suite.parentSuite; + } + + return { + befores: befores.reverse(), + afters: afters + }; + }; + }; + + var getSpecName = function(spec, suite) { + var fullName = [spec.description], + suiteFullName = suite.getFullName(); + + if (suiteFullName !== '') { + fullName.unshift(suiteFullName); + } + return fullName.join(' '); + }; + + // TODO: we may just be able to pass in the fn instead of wrapping here + var buildExpectationResult = j$.buildExpectationResult, + exceptionFormatter = new j$.ExceptionFormatter(), + expectationResultFactory = function(attrs) { + attrs.messageFormatter = exceptionFormatter.message; + attrs.stackFormatter = exceptionFormatter.stack; + + return buildExpectationResult(attrs); + }; + + // TODO: fix this naming, and here's where the value comes in + this.catchExceptions = function(value) { + catchExceptions = !!value; + return catchExceptions; + }; + + this.catchingExceptions = function() { + return catchExceptions; + }; + + var maximumSpecCallbackDepth = 20; + var currentSpecCallbackDepth = 0; + + var catchException = function(e) { + return j$.Spec.isPendingSpecException(e) || catchExceptions; + }; + + this.throwOnExpectationFailure = function(value) { + throwOnExpectationFailure = !!value; + }; + + this.throwingExpectationFailures = function() { + return throwOnExpectationFailure; + }; + + this.randomizeTests = function(value) { + random = !!value; + }; + + this.randomTests = function() { + return random; + }; + + this.seed = function(value) { + if (value) { + seed = value; + } + return seed; + }; + + var queueRunnerFactory = function(options) { + options.catchException = catchException; + options.clearStack = options.clearStack || clearStack; + options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; + options.fail = self.fail; + options.globalErrors = globalErrors; + + new j$.QueueRunner(options).execute(); + }; + + var topSuite = new j$.Suite({ + env: this, + id: getNextSuiteId(), + description: 'Jasmine__TopLevel__Suite', + expectationFactory: expectationFactory, + expectationResultFactory: expectationResultFactory + }); + defaultResourcesForRunnable(topSuite.id); + currentDeclarationSuite = topSuite; + + this.topSuite = function() { + return topSuite; + }; + + this.execute = function(runnablesToRun) { + if(!runnablesToRun) { + if (focusedRunnables.length) { + runnablesToRun = focusedRunnables; + } else { + runnablesToRun = [topSuite.id]; + } + } + + var order = new j$.Order({ + random: random, + seed: seed + }); + + var processor = new j$.TreeProcessor({ + tree: topSuite, + runnableIds: runnablesToRun, + queueRunnerFactory: queueRunnerFactory, + nodeStart: function(suite) { + currentlyExecutingSuites.push(suite); + defaultResourcesForRunnable(suite.id, suite.parentSuite.id); + reporter.suiteStarted(suite.result); + }, + nodeComplete: function(suite, result) { + if (suite !== currentSuite()) { + throw new Error('Tried to complete the wrong suite'); + } + + if (!suite.markedPending) { + clearResourcesForRunnable(suite.id); + } + currentlyExecutingSuites.pop(); + reporter.suiteDone(result); + }, + orderChildren: function(node) { + return order.sort(node.children); + } + }); + + if(!processor.processTree().valid) { + throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times'); + } + + reporter.jasmineStarted({ + totalSpecsDefined: totalSpecsDefined + }); + + currentlyExecutingSuites.push(topSuite); + + globalErrors.install(); + processor.execute(function() { + clearResourcesForRunnable(topSuite.id); + currentlyExecutingSuites.pop(); + globalErrors.uninstall(); + + reporter.jasmineDone({ + order: order, + failedExpectations: topSuite.result.failedExpectations + }); + }); + }; + + /** + * Add a custom reporter to the Jasmine environment. + * @name Env#addReporter + * @function + * @see custom_reporter + */ + this.addReporter = function(reporterToAdd) { + reporter.addReporter(reporterToAdd); + }; + + this.provideFallbackReporter = function(reporterToAdd) { + reporter.provideFallbackReporter(reporterToAdd); + }; + + this.clearReporters = function() { + reporter.clearReporters(); + }; + + var spyRegistry = new j$.SpyRegistry({currentSpies: function() { + if(!currentRunnable()) { + throw new Error('Spies must be created in a before function or a spec'); + } + return runnableResources[currentRunnable().id].spies; + }}); + + this.allowRespy = function(allow){ + spyRegistry.allowRespy(allow); + }; + + this.spyOn = function() { + return spyRegistry.spyOn.apply(spyRegistry, arguments); + }; + + this.spyOnProperty = function() { + return spyRegistry.spyOnProperty.apply(spyRegistry, arguments); + }; + + var ensureIsFunction = function(fn, caller) { + if (!j$.isFunction_(fn)) { + throw new Error(caller + ' expects a function argument; received ' + j$.getType_(fn)); + } + }; + + var suiteFactory = function(description) { + var suite = new j$.Suite({ + env: self, + id: getNextSuiteId(), + description: description, + parentSuite: currentDeclarationSuite, + expectationFactory: expectationFactory, + expectationResultFactory: expectationResultFactory, + throwOnExpectationFailure: throwOnExpectationFailure + }); + + return suite; + }; + + this.describe = function(description, specDefinitions) { + ensureIsFunction(specDefinitions, 'describe'); + var suite = suiteFactory(description); + if (specDefinitions.length > 0) { + throw new Error('describe does not expect any arguments'); + } + if (currentDeclarationSuite.markedPending) { + suite.pend(); + } + addSpecsToSuite(suite, specDefinitions); + return suite; + }; + + this.xdescribe = function(description, specDefinitions) { + ensureIsFunction(specDefinitions, 'xdescribe'); + var suite = suiteFactory(description); + suite.pend(); + addSpecsToSuite(suite, specDefinitions); + return suite; + }; + + var focusedRunnables = []; + + this.fdescribe = function(description, specDefinitions) { + ensureIsFunction(specDefinitions, 'fdescribe'); + var suite = suiteFactory(description); + suite.isFocused = true; + + focusedRunnables.push(suite.id); + unfocusAncestor(); + addSpecsToSuite(suite, specDefinitions); + + return suite; + }; + + function addSpecsToSuite(suite, specDefinitions) { + var parentSuite = currentDeclarationSuite; + parentSuite.addChild(suite); + currentDeclarationSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch (e) { + declarationError = e; + } + + if (declarationError) { + self.it('encountered a declaration exception', function() { + throw declarationError; + }); + } + + currentDeclarationSuite = parentSuite; + } + + function findFocusedAncestor(suite) { + while (suite) { + if (suite.isFocused) { + return suite.id; + } + suite = suite.parentSuite; + } + + return null; + } + + function unfocusAncestor() { + var focusedAncestor = findFocusedAncestor(currentDeclarationSuite); + if (focusedAncestor) { + for (var i = 0; i < focusedRunnables.length; i++) { + if (focusedRunnables[i] === focusedAncestor) { + focusedRunnables.splice(i, 1); + break; + } + } + } + } + + var specFactory = function(description, fn, suite, timeout) { + totalSpecsDefined++; + var spec = new j$.Spec({ + id: getNextSpecId(), + beforeAndAfterFns: beforeAndAfterFns(suite), + expectationFactory: expectationFactory, + resultCallback: specResultCallback, + getSpecName: function(spec) { + return getSpecName(spec, suite); + }, + onStart: specStarted, + description: description, + expectationResultFactory: expectationResultFactory, + queueRunnerFactory: queueRunnerFactory, + userContext: function() { return suite.clonedSharedUserContext(); }, + queueableFn: { + fn: fn, + timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } + }, + throwOnExpectationFailure: throwOnExpectationFailure + }); + + if (!self.specFilter(spec)) { + spec.disable(); + } + + return spec; + + function specResultCallback(result) { + clearResourcesForRunnable(spec.id); + currentSpec = null; + reporter.specDone(result); + } + + function specStarted(spec) { + currentSpec = spec; + defaultResourcesForRunnable(spec.id, suite.id); + reporter.specStarted(spec.result); + } + }; + + this.it = function(description, fn, timeout) { + // it() sometimes doesn't have a fn argument, so only check the type if + // it's given. + if (arguments.length > 1 && typeof fn !== 'undefined') { + ensureIsFunction(fn, 'it'); + } + var spec = specFactory(description, fn, currentDeclarationSuite, timeout); + if (currentDeclarationSuite.markedPending) { + spec.pend(); + } + currentDeclarationSuite.addChild(spec); + return spec; + }; + + this.xit = function(description, fn, timeout) { + // xit(), like it(), doesn't always have a fn argument, so only check the + // type when needed. + if (arguments.length > 1 && typeof fn !== 'undefined') { + ensureIsFunction(fn, 'xit'); + } + var spec = this.it.apply(this, arguments); + spec.pend('Temporarily disabled with xit'); + return spec; + }; + + this.fit = function(description, fn, timeout){ + ensureIsFunction(fn, 'fit'); + var spec = specFactory(description, fn, currentDeclarationSuite, timeout); + currentDeclarationSuite.addChild(spec); + focusedRunnables.push(spec.id); + unfocusAncestor(); + return spec; + }; + + this.expect = function(actual) { + if (!currentRunnable()) { + throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); + } + + return currentRunnable().expect(actual); + }; + + this.beforeEach = function(beforeEachFunction, timeout) { + ensureIsFunction(beforeEachFunction, 'beforeEach'); + currentDeclarationSuite.beforeEach({ + fn: beforeEachFunction, + timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } + }); + }; + + this.beforeAll = function(beforeAllFunction, timeout) { + ensureIsFunction(beforeAllFunction, 'beforeAll'); + currentDeclarationSuite.beforeAll({ + fn: beforeAllFunction, + timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } + }); + }; + + this.afterEach = function(afterEachFunction, timeout) { + ensureIsFunction(afterEachFunction, 'afterEach'); + currentDeclarationSuite.afterEach({ + fn: afterEachFunction, + timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } + }); + }; + + this.afterAll = function(afterAllFunction, timeout) { + ensureIsFunction(afterAllFunction, 'afterAll'); + currentDeclarationSuite.afterAll({ + fn: afterAllFunction, + timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } + }); + }; + + this.pending = function(message) { + var fullMessage = j$.Spec.pendingSpecExceptionMessage; + if(message) { + fullMessage += message; + } + throw fullMessage; + }; + + this.fail = function(error) { + if (!currentRunnable()) { + throw new Error('\'fail\' was used when there was no current spec, this could be because an asynchronous test timed out'); + } + + var message = 'Failed'; + if (error) { + message += ': '; + if (error.message) { + message += error.message; + } else if (jasmine.isString_(error)) { + message += error; + } else { + // pretty print all kind of objects. This includes arrays. + message += jasmine.pp(error); + } + } + + currentRunnable().addExpectationResult(false, { + matcherName: '', + passed: false, + expected: '', + actual: '', + message: message, + error: error && error.message ? error : null + }); + }; + } + + return Env; +}; + +getJasmineRequireObj().JsApiReporter = function() { + + var noopTimer = { + start: function(){}, + elapsed: function(){ return 0; } + }; + + /** + * _Note:_ Do not construct this directly, use the global `jsApiReporter` to retrieve the instantiated object. + * + * @name jsApiReporter + * @classdesc Reporter added by default in `boot.js` to record results for retrieval in javascript code. + * @class + */ + function JsApiReporter(options) { + var timer = options.timer || noopTimer, + status = 'loaded'; + + this.started = false; + this.finished = false; + this.runDetails = {}; + + this.jasmineStarted = function() { + this.started = true; + status = 'started'; + timer.start(); + }; + + var executionTime; + + this.jasmineDone = function(runDetails) { + this.finished = true; + this.runDetails = runDetails; + executionTime = timer.elapsed(); + status = 'done'; + }; + + /** + * Get the current status for the Jasmine environment. + * @name jsApiReporter#status + * @function + * @return {String} - One of `loaded`, `started`, or `done` + */ + this.status = function() { + return status; + }; + + var suites = [], + suites_hash = {}; + + this.suiteStarted = function(result) { + suites_hash[result.id] = result; + }; + + this.suiteDone = function(result) { + storeSuite(result); + }; + + /** + * Get the results for a set of suites. + * + * Retrievable in slices for easier serialization. + * @name jsApiReporter#suiteResults + * @function + * @param {Number} index - The position in the suites list to start from. + * @param {Number} length - Maximum number of suite results to return. + * @return {Object[]} + */ + this.suiteResults = function(index, length) { + return suites.slice(index, index + length); + }; + + function storeSuite(result) { + suites.push(result); + suites_hash[result.id] = result; + } + + /** + * Get all of the suites in a single object, with their `id` as the key. + * @name jsApiReporter#suites + * @function + * @return {Object} + */ + this.suites = function() { + return suites_hash; + }; + + var specs = []; + + this.specDone = function(result) { + specs.push(result); + }; + + /** + * Get the results for a set of specs. + * + * Retrievable in slices for easier serialization. + * @name jsApiReporter#specResults + * @function + * @param {Number} index - The position in the specs list to start from. + * @param {Number} length - Maximum number of specs results to return. + * @return {Object[]} + */ + this.specResults = function(index, length) { + return specs.slice(index, index + length); + }; + + /** + * Get all spec results. + * @name jsApiReporter#specs + * @function + * @return {Object[]} + */ + this.specs = function() { + return specs; + }; + + /** + * Get the number of milliseconds it took for the full Jasmine suite to run. + * @name jsApiReporter#executionTime + * @function + * @return {Number} + */ + this.executionTime = function() { + return executionTime; + }; + + } + + return JsApiReporter; +}; + +getJasmineRequireObj().Any = function(j$) { + + function Any(expectedObject) { + if (typeof expectedObject === 'undefined') { + throw new TypeError( + 'jasmine.any() expects to be passed a constructor function. ' + + 'Please pass one or use jasmine.anything() to match any object.' + ); + } + this.expectedObject = expectedObject; + } + + Any.prototype.asymmetricMatch = function(other) { + if (this.expectedObject == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedObject == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedObject == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedObject == Object) { + return typeof other == 'object'; + } + + if (this.expectedObject == Boolean) { + return typeof other == 'boolean'; + } + + return other instanceof this.expectedObject; + }; + + Any.prototype.jasmineToString = function() { + return ''; + }; + + return Any; +}; + +getJasmineRequireObj().Anything = function(j$) { + + function Anything() {} + + Anything.prototype.asymmetricMatch = function(other) { + return !j$.util.isUndefined(other) && other !== null; + }; + + Anything.prototype.jasmineToString = function() { + return ''; + }; + + return Anything; +}; + +getJasmineRequireObj().ArrayContaining = function(j$) { + function ArrayContaining(sample) { + this.sample = sample; + } + + ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) { + var className = Object.prototype.toString.call(this.sample); + if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); } + + for (var i = 0; i < this.sample.length; i++) { + var item = this.sample[i]; + if (!j$.matchersUtil.contains(other, item, customTesters)) { + return false; + } + } + + return true; + }; + + ArrayContaining.prototype.jasmineToString = function () { + return ''; + }; + + return ArrayContaining; +}; + +getJasmineRequireObj().ObjectContaining = function(j$) { + + function ObjectContaining(sample) { + this.sample = sample; + } + + function getPrototype(obj) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(obj); + } + + if (obj.constructor.prototype == obj) { + return null; + } + + return obj.constructor.prototype; + } + + function hasProperty(obj, property) { + if (!obj) { + return false; + } + + if (Object.prototype.hasOwnProperty.call(obj, property)) { + return true; + } + + return hasProperty(getPrototype(obj), property); + } + + ObjectContaining.prototype.asymmetricMatch = function(other, customTesters) { + if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } + + for (var property in this.sample) { + if (!hasProperty(other, property) || + !j$.matchersUtil.equals(this.sample[property], other[property], customTesters)) { + return false; + } + } + + return true; + }; + + ObjectContaining.prototype.jasmineToString = function() { + return ''; + }; + + return ObjectContaining; +}; + +getJasmineRequireObj().StringMatching = function(j$) { + + function StringMatching(expected) { + if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { + throw new Error('Expected is not a String or a RegExp'); + } + + this.regexp = new RegExp(expected); + } + + StringMatching.prototype.asymmetricMatch = function(other) { + return this.regexp.test(other); + }; + + StringMatching.prototype.jasmineToString = function() { + return ''; + }; + + return StringMatching; +}; + +getJasmineRequireObj().CallTracker = function(j$) { + + /** + * @namespace Spy#calls + */ + function CallTracker() { + var calls = []; + var opts = {}; + + function argCloner(context) { + var clonedArgs = []; + var argsAsArray = j$.util.argsToArray(context.args); + for(var i = 0; i < argsAsArray.length; i++) { + if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) { + clonedArgs.push(j$.util.clone(argsAsArray[i])); + } else { + clonedArgs.push(argsAsArray[i]); + } + } + context.args = clonedArgs; + } + + this.track = function(context) { + if(opts.cloneArgs) { + argCloner(context); + } + calls.push(context); + }; + + /** + * Check whether this spy has been invoked. + * @name Spy#calls#any + * @function + * @return {Boolean} + */ + this.any = function() { + return !!calls.length; + }; + + /** + * Get the number of invocations of this spy. + * @name Spy#calls#count + * @function + * @return {Integer} + */ + this.count = function() { + return calls.length; + }; + + /** + * Get the arguments that were passed to a specific invocation of this spy. + * @name Spy#calls#argsFor + * @function + * @param {Integer} index The 0-based invocation index. + * @return {Array} + */ + this.argsFor = function(index) { + var call = calls[index]; + return call ? call.args : []; + }; + + /** + * Get the raw calls array for this spy. + * @name Spy#calls#all + * @function + * @return {Spy.callData[]} + */ + this.all = function() { + return calls; + }; + + /** + * Get all of the arguments for each invocation of this spy in the order they were received. + * @name Spy#calls#allArgs + * @function + * @return {Array} + */ + this.allArgs = function() { + var callArgs = []; + for(var i = 0; i < calls.length; i++){ + callArgs.push(calls[i].args); + } + + return callArgs; + }; + + /** + * Get the first invocation of this spy. + * @name Spy#calls#first + * @function + * @return {ObjecSpy.callData} + */ + this.first = function() { + return calls[0]; + }; + + /** + * Get the most recent invocation of this spy. + * @name Spy#calls#mostRecent + * @function + * @return {ObjecSpy.callData} + */ + this.mostRecent = function() { + return calls[calls.length - 1]; + }; + + /** + * Reset this spy as if it has never been called. + * @name Spy#calls#reset + * @function + */ + this.reset = function() { + calls = []; + }; + + /** + * Set this spy to do a shallow clone of arguments passed to each invocation. + * @name Spy#calls#saveArgumentsByValue + * @function + */ + this.saveArgumentsByValue = function() { + opts.cloneArgs = true; + }; + + } + + return CallTracker; +}; + +getJasmineRequireObj().clearStack = function(j$) { + var maxInlineCallCount = 10; + + function messageChannelImpl(global, setTimeout) { + var channel = new global.MessageChannel(), + head = {}, + tail = head; + + var taskRunning = false; + channel.port1.onmessage = function() { + head = head.next; + var task = head.task; + delete head.task; + + if (taskRunning) { + global.setTimeout(task, 0); + } else { + try { + taskRunning = true; + task(); + } finally { + taskRunning = false; + } + } + }; + + var currentCallCount = 0; + return function clearStack(fn) { + currentCallCount++; + + if (currentCallCount < maxInlineCallCount) { + tail = tail.next = { task: fn }; + channel.port2.postMessage(0); + } else { + currentCallCount = 0; + setTimeout(fn); + } + }; + } + + function getClearStack(global) { + var currentCallCount = 0; + var realSetTimeout = global.setTimeout; + var setTimeoutImpl = function clearStack(fn) { + Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]); + }; + + if (j$.isFunction_(global.setImmediate)) { + var realSetImmediate = global.setImmediate; + return function(fn) { + currentCallCount++; + + if (currentCallCount < maxInlineCallCount) { + realSetImmediate(fn); + } else { + currentCallCount = 0; + + setTimeoutImpl(fn); + } + }; + } else if (!j$.util.isUndefined(global.MessageChannel)) { + return messageChannelImpl(global, setTimeoutImpl); + } else { + return setTimeoutImpl; + } + } + + return getClearStack; +}; + +getJasmineRequireObj().Clock = function() { + /** + * _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}. + * @class Clock + * @classdesc Jasmine's mock clock is used when testing time dependent code. + */ + function Clock(global, delayedFunctionSchedulerFactory, mockDate) { + var self = this, + realTimingFunctions = { + setTimeout: global.setTimeout, + clearTimeout: global.clearTimeout, + setInterval: global.setInterval, + clearInterval: global.clearInterval + }, + fakeTimingFunctions = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setInterval: setInterval, + clearInterval: clearInterval + }, + installed = false, + delayedFunctionScheduler, + timer; + + + /** + * Install the mock clock over the built-in methods. + * @name Clock#install + * @function + * @return {Clock} + */ + self.install = function() { + if(!originalTimingFunctionsIntact()) { + throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?'); + } + replace(global, fakeTimingFunctions); + timer = fakeTimingFunctions; + delayedFunctionScheduler = delayedFunctionSchedulerFactory(); + installed = true; + + return self; + }; + + /** + * Uninstall the mock clock, returning the built-in methods to their places. + * @name Clock#uninstall + * @function + */ + self.uninstall = function() { + delayedFunctionScheduler = null; + mockDate.uninstall(); + replace(global, realTimingFunctions); + + timer = realTimingFunctions; + installed = false; + }; + + /** + * Execute a function with a mocked Clock + * + * The clock will be {@link Clock#install|install}ed before the function is called and {@link Clock#uninstall|uninstall}ed in a `finally` after the function completes. + * @name Clock#withMock + * @function + * @param {closure} Function The function to be called. + */ + self.withMock = function(closure) { + this.install(); + try { + closure(); + } finally { + this.uninstall(); + } + }; + + /** + * Instruct the installed Clock to also mock the date returned by `new Date()` + * @name Clock#mockDate + * @function + * @param {Date} [initialDate=now] The `Date` to provide. + */ + self.mockDate = function(initialDate) { + mockDate.install(initialDate); + }; + + self.setTimeout = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); + } + return timer.setTimeout(fn, delay); + } + return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); + }; + + self.setInterval = function(fn, delay, params) { + if (legacyIE()) { + if (arguments.length > 2) { + throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); + } + return timer.setInterval(fn, delay); + } + return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); + }; + + self.clearTimeout = function(id) { + return Function.prototype.call.apply(timer.clearTimeout, [global, id]); + }; + + self.clearInterval = function(id) { + return Function.prototype.call.apply(timer.clearInterval, [global, id]); + }; + + /** + * Tick the Clock forward, running any enqueued timeouts along the way + * @name Clock#tick + * @function + * @param {int} millis The number of milliseconds to tick. + */ + self.tick = function(millis) { + if (installed) { + delayedFunctionScheduler.tick(millis, function(millis) { mockDate.tick(millis); }); + } else { + throw new Error('Mock clock is not installed, use jasmine.clock().install()'); + } + }; + + return self; + + function originalTimingFunctionsIntact() { + return global.setTimeout === realTimingFunctions.setTimeout && + global.clearTimeout === realTimingFunctions.clearTimeout && + global.setInterval === realTimingFunctions.setInterval && + global.clearInterval === realTimingFunctions.clearInterval; + } + + function legacyIE() { + //if these methods are polyfilled, apply will be present + return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; + } + + function replace(dest, source) { + for (var prop in source) { + dest[prop] = source[prop]; + } + } + + function setTimeout(fn, delay) { + return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); + } + + function clearTimeout(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } + + function setInterval(fn, interval) { + return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); + } + + function clearInterval(id) { + return delayedFunctionScheduler.removeFunctionWithId(id); + } + + function argSlice(argsObj, n) { + return Array.prototype.slice.call(argsObj, n); + } + } + + return Clock; +}; + +getJasmineRequireObj().DelayedFunctionScheduler = function() { + function DelayedFunctionScheduler() { + var self = this; + var scheduledLookup = []; + var scheduledFunctions = {}; + var currentTime = 0; + var delayedFnCount = 0; + + self.tick = function(millis, tickDate) { + millis = millis || 0; + var endTime = currentTime + millis; + + runScheduledFunctions(endTime, tickDate); + currentTime = endTime; + }; + + self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { + var f; + if (typeof(funcToCall) === 'string') { + /* jshint evil: true */ + f = function() { return eval(funcToCall); }; + /* jshint evil: false */ + } else { + f = funcToCall; + } + + millis = millis || 0; + timeoutKey = timeoutKey || ++delayedFnCount; + runAtMillis = runAtMillis || (currentTime + millis); + + var funcToSchedule = { + runAtMillis: runAtMillis, + funcToCall: f, + recurring: recurring, + params: params, + timeoutKey: timeoutKey, + millis: millis + }; + + if (runAtMillis in scheduledFunctions) { + scheduledFunctions[runAtMillis].push(funcToSchedule); + } else { + scheduledFunctions[runAtMillis] = [funcToSchedule]; + scheduledLookup.push(runAtMillis); + scheduledLookup.sort(function (a, b) { + return a - b; + }); + } + + return timeoutKey; + }; + + self.removeFunctionWithId = function(timeoutKey) { + for (var runAtMillis in scheduledFunctions) { + var funcs = scheduledFunctions[runAtMillis]; + var i = indexOfFirstToPass(funcs, function (func) { + return func.timeoutKey === timeoutKey; + }); + + if (i > -1) { + if (funcs.length === 1) { + delete scheduledFunctions[runAtMillis]; + deleteFromLookup(runAtMillis); + } else { + funcs.splice(i, 1); + } + + // intervals get rescheduled when executed, so there's never more + // than a single scheduled function with a given timeoutKey + break; + } + } + }; + + return self; + + function indexOfFirstToPass(array, testFn) { + var index = -1; + + for (var i = 0; i < array.length; ++i) { + if (testFn(array[i])) { + index = i; + break; + } + } + + return index; + } + + function deleteFromLookup(key) { + var value = Number(key); + var i = indexOfFirstToPass(scheduledLookup, function (millis) { + return millis === value; + }); + + if (i > -1) { + scheduledLookup.splice(i, 1); + } + } + + function reschedule(scheduledFn) { + self.scheduleFunction(scheduledFn.funcToCall, + scheduledFn.millis, + scheduledFn.params, + true, + scheduledFn.timeoutKey, + scheduledFn.runAtMillis + scheduledFn.millis); + } + + function forEachFunction(funcsToRun, callback) { + for (var i = 0; i < funcsToRun.length; ++i) { + callback(funcsToRun[i]); + } + } + + function runScheduledFunctions(endTime, tickDate) { + tickDate = tickDate || function() {}; + if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { + tickDate(endTime - currentTime); + return; + } + + do { + var newCurrentTime = scheduledLookup.shift(); + tickDate(newCurrentTime - currentTime); + + currentTime = newCurrentTime; + + var funcsToRun = scheduledFunctions[currentTime]; + delete scheduledFunctions[currentTime]; + + forEachFunction(funcsToRun, function(funcToRun) { + if (funcToRun.recurring) { + reschedule(funcToRun); + } + }); + + forEachFunction(funcsToRun, function(funcToRun) { + funcToRun.funcToCall.apply(null, funcToRun.params || []); + }); + } while (scheduledLookup.length > 0 && + // checking first if we're out of time prevents setTimeout(0) + // scheduled in a funcToRun from forcing an extra iteration + currentTime !== endTime && + scheduledLookup[0] <= endTime); + + // ran out of functions to call, but still time left on the clock + if (currentTime !== endTime) { + tickDate(endTime - currentTime); + } + } + } + + return DelayedFunctionScheduler; +}; + +getJasmineRequireObj().errors = function() { + function ExpectationFailed() {} + + ExpectationFailed.prototype = new Error(); + ExpectationFailed.prototype.constructor = ExpectationFailed; + + return { + ExpectationFailed: ExpectationFailed + }; +}; +getJasmineRequireObj().ExceptionFormatter = function() { + function ExceptionFormatter() { + this.message = function(error) { + var message = ''; + + if (error.name && error.message) { + message += error.name + ': ' + error.message; + } else { + message += error.toString() + ' thrown'; + } + + if (error.fileName || error.sourceURL) { + message += ' in ' + (error.fileName || error.sourceURL); + } + + if (error.line || error.lineNumber) { + message += ' (line ' + (error.line || error.lineNumber) + ')'; + } + + return message; + }; + + this.stack = function(error) { + return error ? error.stack : null; + }; + } + + return ExceptionFormatter; +}; + +getJasmineRequireObj().Expectation = function() { + + /** + * Matchers that come with Jasmine out of the box. + * @namespace matchers + */ + function Expectation(options) { + this.util = options.util || { buildFailureMessage: function() {} }; + this.customEqualityTesters = options.customEqualityTesters || []; + this.actual = options.actual; + this.addExpectationResult = options.addExpectationResult || function(){}; + this.isNot = options.isNot; + + var customMatchers = options.customMatchers || {}; + for (var matcherName in customMatchers) { + this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]); + } + } + + Expectation.prototype.wrapCompare = function(name, matcherFactory) { + return function() { + var args = Array.prototype.slice.call(arguments, 0), + expected = args.slice(0), + message = ''; + + args.unshift(this.actual); + + var matcher = matcherFactory(this.util, this.customEqualityTesters), + matcherCompare = matcher.compare; + + function defaultNegativeCompare() { + var result = matcher.compare.apply(null, args); + result.pass = !result.pass; + return result; + } + + if (this.isNot) { + matcherCompare = matcher.negativeCompare || defaultNegativeCompare; + } + + var result = matcherCompare.apply(null, args); + + if (!result.pass) { + if (!result.message) { + args.unshift(this.isNot); + args.unshift(name); + message = this.util.buildFailureMessage.apply(null, args); + } else { + if (Object.prototype.toString.apply(result.message) === '[object Function]') { + message = result.message(); + } else { + message = result.message; + } + } + } + + if (expected.length == 1) { + expected = expected[0]; + } + + // TODO: how many of these params are needed? + this.addExpectationResult( + result.pass, + { + matcherName: name, + passed: result.pass, + message: message, + error: result.error, + actual: this.actual, + expected: expected // TODO: this may need to be arrayified/sliced + } + ); + }; + }; + + Expectation.addCoreMatchers = function(matchers) { + var prototype = Expectation.prototype; + for (var matcherName in matchers) { + var matcher = matchers[matcherName]; + prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); + } + }; + + Expectation.Factory = function(options) { + options = options || {}; + + var expect = new Expectation(options); + + // TODO: this would be nice as its own Object - NegativeExpectation + // TODO: copy instead of mutate options + options.isNot = true; + expect.not = new Expectation(options); + + return expect; + }; + + return Expectation; +}; + +//TODO: expectation result may make more sense as a presentation of an expectation. +getJasmineRequireObj().buildExpectationResult = function() { + function buildExpectationResult(options) { + var messageFormatter = options.messageFormatter || function() {}, + stackFormatter = options.stackFormatter || function() {}; + + var result = { + matcherName: options.matcherName, + message: message(), + stack: stack(), + passed: options.passed + }; + + if(!result.passed) { + result.expected = options.expected; + result.actual = options.actual; + } + + return result; + + function message() { + if (options.passed) { + return 'Passed.'; + } else if (options.message) { + return options.message; + } else if (options.error) { + return messageFormatter(options.error); + } + return ''; + } + + function stack() { + if (options.passed) { + return ''; + } + + var error = options.error; + if (!error) { + try { + throw new Error(message()); + } catch (e) { + error = e; + } + } + return stackFormatter(error); + } + } + + return buildExpectationResult; +}; + +getJasmineRequireObj().formatErrorMsg = function() { + function generateErrorMsg(domain, usage) { + var usageDefinition = usage ? '\nUsage: ' + usage : ''; + + return function errorMsg(msg) { + return domain + ' : ' + msg + usageDefinition; + }; + } + + return generateErrorMsg; +}; + +getJasmineRequireObj().GlobalErrors = function(j$) { + function GlobalErrors(global) { + var handlers = []; + global = global || j$.getGlobal(); + + var onerror = function onerror() { + var handler = handlers[handlers.length - 1]; + + if (handler) { + handler.apply(null, Array.prototype.slice.call(arguments, 0)); + } else { + throw arguments[0]; + } + }; + + this.uninstall = function noop() {}; + + this.install = function install() { + if (global.process && global.process.listeners && j$.isFunction_(global.process.on)) { + var originalHandlers = global.process.listeners('uncaughtException'); + global.process.removeAllListeners('uncaughtException'); + global.process.on('uncaughtException', onerror); + + this.uninstall = function uninstall() { + global.process.removeListener('uncaughtException', onerror); + for (var i = 0; i < originalHandlers.length; i++) { + global.process.on('uncaughtException', originalHandlers[i]); + } + }; + } else { + var originalHandler = global.onerror; + global.onerror = onerror; + + this.uninstall = function uninstall() { + global.onerror = originalHandler; + }; + } + }; + + this.pushListener = function pushListener(listener) { + handlers.push(listener); + }; + + this.popListener = function popListener() { + handlers.pop(); + }; + } + + return GlobalErrors; +}; + +getJasmineRequireObj().DiffBuilder = function(j$) { + return function DiffBuilder() { + var path = new j$.ObjectPath(), + mismatches = []; + + return { + record: function (actual, expected, formatter) { + formatter = formatter || defaultFormatter; + mismatches.push(formatter(actual, expected, path)); + }, + + getMessage: function () { + return mismatches.join('\n'); + }, + + withPath: function (pathComponent, block) { + var oldPath = path; + path = path.add(pathComponent); + block(); + path = oldPath; + } + }; + + function defaultFormatter (actual, expected, path) { + return 'Expected ' + + path + (path.depth() ? ' = ' : '') + + j$.pp(actual) + + ' to equal ' + + j$.pp(expected) + + '.'; + } + }; +}; + +getJasmineRequireObj().matchersUtil = function(j$) { + // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? + + return { + equals: equals, + + contains: function(haystack, needle, customTesters) { + customTesters = customTesters || []; + + if ((Object.prototype.toString.apply(haystack) === '[object Set]')) { + return haystack.has(needle); + } + + if ((Object.prototype.toString.apply(haystack) === '[object Array]') || + (!!haystack && !haystack.indexOf)) + { + for (var i = 0; i < haystack.length; i++) { + if (equals(haystack[i], needle, customTesters)) { + return true; + } + } + return false; + } + + return !!haystack && haystack.indexOf(needle) >= 0; + }, + + buildFailureMessage: function() { + var args = Array.prototype.slice.call(arguments, 0), + matcherName = args[0], + isNot = args[1], + actual = args[2], + expected = args.slice(3), + englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + + var message = 'Expected ' + + j$.pp(actual) + + (isNot ? ' not ' : ' ') + + englishyPredicate; + + if (expected.length > 0) { + for (var i = 0; i < expected.length; i++) { + if (i > 0) { + message += ','; + } + message += ' ' + j$.pp(expected[i]); + } + } + + return message + '.'; + } + }; + + function isAsymmetric(obj) { + return obj && j$.isA_('Function', obj.asymmetricMatch); + } + + function asymmetricMatch(a, b, customTesters, diffBuilder) { + var asymmetricA = isAsymmetric(a), + asymmetricB = isAsymmetric(b), + result; + + if (asymmetricA && asymmetricB) { + return undefined; + } + + if (asymmetricA) { + result = a.asymmetricMatch(b, customTesters); + diffBuilder.record(a, b); + return result; + } + + if (asymmetricB) { + result = b.asymmetricMatch(a, customTesters); + diffBuilder.record(a, b); + return result; + } + } + + function equals(a, b, customTesters, diffBuilder) { + customTesters = customTesters || []; + diffBuilder = diffBuilder || j$.NullDiffBuilder(); + + return eq(a, b, [], [], customTesters, diffBuilder); + } + + // Equality function lovingly adapted from isEqual in + // [Underscore](http://underscorejs.org) + function eq(a, b, aStack, bStack, customTesters, diffBuilder) { + var result = true, i; + + var asymmetricResult = asymmetricMatch(a, b, customTesters, diffBuilder); + if (!j$.util.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + + for (i = 0; i < customTesters.length; i++) { + var customTesterResult = customTesters[i](a, b); + if (!j$.util.isUndefined(customTesterResult)) { + if (!customTesterResult) { + diffBuilder.record(a, b); + } + return customTesterResult; + } + } + + if (a instanceof Error && b instanceof Error) { + result = a.message == b.message; + if (!result) { + diffBuilder.record(a, b); + } + return result; + } + + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) { + result = a !== 0 || 1 / a == 1 / b; + if (!result) { + diffBuilder.record(a, b); + } + return result; + } + // A strict comparison is necessary because `null == undefined`. + if (a === null || b === null) { + result = a === b; + if (!result) { + diffBuilder.record(a, b); + } + return result; + } + var className = Object.prototype.toString.call(a); + if (className != Object.prototype.toString.call(b)) { + diffBuilder.record(a, b); + return false; + } + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + result = a == String(b); + if (!result) { + diffBuilder.record(a, b); + } + return result; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + result = a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); + if (!result) { + diffBuilder.record(a, b); + } + return result; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + result = +a == +b; + if (!result) { + diffBuilder.record(a, b); + } + return result; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') { + diffBuilder.record(a, b); + return false; + } + + var aIsDomNode = j$.isDomNode(a); + var bIsDomNode = j$.isDomNode(b); + if (aIsDomNode && bIsDomNode) { + // At first try to use DOM3 method isEqualNode + if (a.isEqualNode) { + result = a.isEqualNode(b); + if (!result) { + diffBuilder.record(a, b); + } + return result; + } + // IE8 doesn't support isEqualNode, try to use outerHTML && innerText + var aIsElement = a instanceof Element; + var bIsElement = b instanceof Element; + if (aIsElement && bIsElement) { + result = a.outerHTML == b.outerHTML; + if (!result) { + diffBuilder.record(a, b); + } + return result; + } + if (aIsElement || bIsElement) { + diffBuilder.record(a, b); + return false; + } + result = a.innerText == b.innerText && a.textContent == b.textContent; + if (!result) { + diffBuilder.record(a, b); + } + return result; + } + if (aIsDomNode || bIsDomNode) { + diffBuilder.record(a, b); + return false; + } + + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) { return bStack[length] == b; } + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0; + // Recursively compare objects and arrays. + // Compare array lengths to determine if a deep comparison is necessary. + if (className == '[object Array]') { + size = a.length; + if (size !== b.length) { + diffBuilder.record(a, b); + return false; + } + + for (i = 0; i < size; i++) { + diffBuilder.withPath(i, function() { + result = eq(a[i], b[i], aStack, bStack, customTesters, diffBuilder) && result; + }); + } + if (!result) { + return false; + } + } else if (className == '[object Set]') { + if (a.size != b.size) { + diffBuilder.record(a, b); + return false; + } + var iterA = a.values(), iterB = b.values(); + var valA, valB; + do { + valA = iterA.next(); + valB = iterB.next(); + if (!eq(valA.value, valB.value, aStack, bStack, customTesters, j$.NullDiffBuilder())) { + diffBuilder.record(a, b); + return false; + } + } while (!valA.done && !valB.done); + } else { + + // Objects with different constructors are not equivalent, but `Object`s + // or `Array`s from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && + isFunction(aCtor) && isFunction(bCtor) && + a instanceof aCtor && b instanceof bCtor && + !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { + + diffBuilder.record(a, b, constructorsAreDifferentFormatter); + return false; + } + } + + // Deep compare objects. + var aKeys = keys(a, className == '[object Array]'), key; + size = aKeys.length; + + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (keys(b, className == '[object Array]').length !== size) { + diffBuilder.record(a, b, objectKeysAreDifferentFormatter); + return false; + } + + for (i = 0; i < size; i++) { + key = aKeys[i]; + // Deep compare each member + if (!j$.util.has(b, key)) { + diffBuilder.record(a, b, objectKeysAreDifferentFormatter); + result = false; + continue; + } + + diffBuilder.withPath(key, function() { + if(!eq(a[key], b[key], aStack, bStack, customTesters, diffBuilder)) { + result = false; + } + }); + } + + if (!result) { + return false; + } + + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + + return result; + } + + function keys(obj, isArray) { + var allKeys = Object.keys ? Object.keys(obj) : + (function(o) { + var keys = []; + for (var key in o) { + if (j$.util.has(o, key)) { + keys.push(key); + } + } + return keys; + })(obj); + + if (!isArray) { + return allKeys; + } + + if (allKeys.length === 0) { + return allKeys; + } + + var extraKeys = []; + for (var i = 0; i < allKeys.length; i++) { + if (!/^[0-9]+$/.test(allKeys[i])) { + extraKeys.push(allKeys[i]); + } + } + + return extraKeys; + } + + function has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + } + + function isFunction(obj) { + return typeof obj === 'function'; + } + + function objectKeysAreDifferentFormatter(actual, expected, path) { + var missingProperties = j$.util.objectDifference(expected, actual), + extraProperties = j$.util.objectDifference(actual, expected), + missingPropertiesMessage = formatKeyValuePairs(missingProperties), + extraPropertiesMessage = formatKeyValuePairs(extraProperties), + messages = []; + + if (!path.depth()) { + path = 'object'; + } + + if (missingPropertiesMessage.length) { + messages.push('Expected ' + path + ' to have properties' + missingPropertiesMessage); + } + + if (extraPropertiesMessage.length) { + messages.push('Expected ' + path + ' not to have properties' + extraPropertiesMessage); + } + + return messages.join('\n'); + } + + function constructorsAreDifferentFormatter(actual, expected, path) { + if (!path.depth()) { + path = 'object'; + } + + return 'Expected ' + + path + ' to be a kind of ' + + j$.fnNameFor(expected.constructor) + + ', but was ' + j$.pp(actual) + '.'; + } + + function formatKeyValuePairs(obj) { + var formatted = ''; + for (var key in obj) { + formatted += '\n ' + key + ': ' + j$.pp(obj[key]); + } + return formatted; + } +}; + +getJasmineRequireObj().NullDiffBuilder = function(j$) { + return function() { + return { + withPath: function(_, block) { + block(); + }, + record: function() {} + }; + }; +}; + +getJasmineRequireObj().ObjectPath = function(j$) { + function ObjectPath(components) { + this.components = components || []; + } + + ObjectPath.prototype.toString = function() { + if (this.components.length) { + return '$' + map(this.components, formatPropertyAccess).join(''); + } else { + return ''; + } + }; + + ObjectPath.prototype.add = function(component) { + return new ObjectPath(this.components.concat([component])); + }; + + ObjectPath.prototype.depth = function() { + return this.components.length; + }; + + function formatPropertyAccess(prop) { + if (typeof prop === 'number') { + return '[' + prop + ']'; + } + + if (isValidIdentifier(prop)) { + return '.' + prop; + } + + return '[\'' + prop + '\']'; + } + + function map(array, fn) { + var results = []; + for (var i = 0; i < array.length; i++) { + results.push(fn(array[i])); + } + return results; + } + + function isValidIdentifier(string) { + return /^[A-Za-z\$_][A-Za-z0-9\$_]*$/.test(string); + } + + return ObjectPath; +}; + +getJasmineRequireObj().toBe = function() { + /** + * {@link expect} the actual value to be `===` to the expected value. + * @function + * @name matchers#toBe + * @param {Object} expected - The expected value to compare against. + * @example + * expect(thing).toBe(realThing); + */ + function toBe() { + return { + compare: function(actual, expected) { + return { + pass: actual === expected + }; + } + }; + } + + return toBe; +}; + +getJasmineRequireObj().toBeCloseTo = function() { + /** + * {@link expect} the actual value to be within a specified precision of the expected value. + * @function + * @name matchers#toBeCloseTo + * @param {Object} expected - The expected value to compare against. + * @param {Number} [precision=2] - The number of decimal points to check. + * @example + * expect(number).toBeCloseTo(42.2, 3); + */ + function toBeCloseTo() { + return { + compare: function(actual, expected, precision) { + if (precision !== 0) { + precision = precision || 2; + } + + return { + pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) + }; + } + }; + } + + return toBeCloseTo; +}; + +getJasmineRequireObj().toBeDefined = function() { + /** + * {@link expect} the actual value to be defined. (Not `undefined`) + * @function + * @name matchers#toBeDefined + * @example + * expect(result).toBeDefined(); + */ + function toBeDefined() { + return { + compare: function(actual) { + return { + pass: (void 0 !== actual) + }; + } + }; + } + + return toBeDefined; +}; + +getJasmineRequireObj().toBeFalsy = function() { + /** + * {@link expect} the actual value to be falsy + * @function + * @name matchers#toBeFalsy + * @example + * expect(result).toBeFalsy(); + */ + function toBeFalsy() { + return { + compare: function(actual) { + return { + pass: !!!actual + }; + } + }; + } + + return toBeFalsy; +}; + +getJasmineRequireObj().toBeGreaterThan = function() { + /** + * {@link expect} the actual value to be greater than the expected value. + * @function + * @name matchers#toBeGreaterThan + * @param {Number} expected - The value to compare against. + * @example + * expect(result).toBeGreaterThan(3); + */ + function toBeGreaterThan() { + return { + compare: function(actual, expected) { + return { + pass: actual > expected + }; + } + }; + } + + return toBeGreaterThan; +}; + + +getJasmineRequireObj().toBeGreaterThanOrEqual = function() { + /** + * {@link expect} the actual value to be greater than or equal to the expected value. + * @function + * @name matchers#toBeGreaterThanOrEqual + * @param {Number} expected - The expected value to compare against. + * @example + * expect(result).toBeGreaterThanOrEqual(25); + */ + function toBeGreaterThanOrEqual() { + return { + compare: function(actual, expected) { + return { + pass: actual >= expected + }; + } + }; + } + + return toBeGreaterThanOrEqual; +}; + +getJasmineRequireObj().toBeLessThan = function() { + /** + * {@link expect} the actual value to be less than the expected value. + * @function + * @name matchers#toBeLessThan + * @param {Number} expected - The expected value to compare against. + * @example + * expect(result).toBeLessThan(0); + */ + function toBeLessThan() { + return { + + compare: function(actual, expected) { + return { + pass: actual < expected + }; + } + }; + } + + return toBeLessThan; +}; + +getJasmineRequireObj().toBeLessThanOrEqual = function() { + /** + * {@link expect} the actual value to be less than or equal to the expected value. + * @function + * @name matchers#toBeLessThanOrEqual + * @param {Number} expected - The expected value to compare against. + * @example + * expect(result).toBeLessThanOrEqual(123); + */ + function toBeLessThanOrEqual() { + return { + + compare: function(actual, expected) { + return { + pass: actual <= expected + }; + } + }; + } + + return toBeLessThanOrEqual; +}; + +getJasmineRequireObj().toBeNaN = function(j$) { + /** + * {@link expect} the actual value to be `NaN` (Not a Number). + * @function + * @name matchers#toBeNaN + * @example + * expect(thing).toBeNaN(); + */ + function toBeNaN() { + return { + compare: function(actual) { + var result = { + pass: (actual !== actual) + }; + + if (result.pass) { + result.message = 'Expected actual not to be NaN.'; + } else { + result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; + } + + return result; + } + }; + } + + return toBeNaN; +}; + +getJasmineRequireObj().toBeNegativeInfinity = function(j$) { + /** + * {@link expect} the actual value to be `-Infinity` (-infinity). + * @function + * @name matchers#toBeNegativeInfinity + * @example + * expect(thing).toBeNegativeInfinity(); + */ + function toBeNegativeInfinity() { + return { + compare: function(actual) { + var result = { + pass: (actual === Number.NEGATIVE_INFINITY) + }; + + if (result.pass) { + result.message = 'Expected actual to be -Infinity.'; + } else { + result.message = function() { return 'Expected ' + j$.pp(actual) + ' not to be -Infinity.'; }; + } + + return result; + } + }; + } + + return toBeNegativeInfinity; +}; + +getJasmineRequireObj().toBeNull = function() { + /** + * {@link expect} the actual value to be `null`. + * @function + * @name matchers#toBeNull + * @example + * expect(result).toBeNull(); + */ + function toBeNull() { + return { + compare: function(actual) { + return { + pass: actual === null + }; + } + }; + } + + return toBeNull; +}; + +getJasmineRequireObj().toBePositiveInfinity = function(j$) { + /** + * {@link expect} the actual value to be `Infinity` (infinity). + * @function + * @name matchers#toBePositiveInfinity + * @example + * expect(thing).toBePositiveInfinity(); + */ + function toBePositiveInfinity() { + return { + compare: function(actual) { + var result = { + pass: (actual === Number.POSITIVE_INFINITY) + }; + + if (result.pass) { + result.message = 'Expected actual to be Infinity.'; + } else { + result.message = function() { return 'Expected ' + j$.pp(actual) + ' not to be Infinity.'; }; + } + + return result; + } + }; + } + + return toBePositiveInfinity; +}; + +getJasmineRequireObj().toBeTruthy = function() { + /** + * {@link expect} the actual value to be truthy. + * @function + * @name matchers#toBeTruthy + * @example + * expect(thing).toBeTruthy(); + */ + function toBeTruthy() { + return { + compare: function(actual) { + return { + pass: !!actual + }; + } + }; + } + + return toBeTruthy; +}; + +getJasmineRequireObj().toBeUndefined = function() { + /** + * {@link expect} the actual value to be `undefined`. + * @function + * @name matchers#toBeUndefined + * @example + * expect(result).toBeUndefined(): + */ + function toBeUndefined() { + return { + compare: function(actual) { + return { + pass: void 0 === actual + }; + } + }; + } + + return toBeUndefined; +}; + +getJasmineRequireObj().toContain = function() { + /** + * {@link expect} the actual value to contain a specific value. + * @function + * @name matchers#toContain + * @param {Object} expected - The value to look for. + * @example + * expect(array).toContain(anElement); + * expect(string).toContain(substring); + */ + function toContain(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + + return { + pass: util.contains(actual, expected, customEqualityTesters) + }; + } + }; + } + + return toContain; +}; + +getJasmineRequireObj().toEqual = function(j$) { + /** + * {@link expect} the actual value to be equal to the expected, using deep equality comparison. + * @function + * @name matchers#toEqual + * @param {Object} expected - Expected value + * @example + * expect(bigObject).toEqual({"foo": ['bar', 'baz']}); + */ + function toEqual(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + var result = { + pass: false + }, + diffBuilder = j$.DiffBuilder(); + + result.pass = util.equals(actual, expected, customEqualityTesters, diffBuilder); + + // TODO: only set error message if test fails + result.message = diffBuilder.getMessage(); + + return result; + } + }; + } + + return toEqual; +}; + +getJasmineRequireObj().toHaveBeenCalled = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalled()'); + + /** + * {@link expect} the actual (a {@link Spy}) to have been called. + * @function + * @name matchers#toHaveBeenCalled + * @example + * expect(mySpy).toHaveBeenCalled(); + * expect(mySpy).not.toHaveBeenCalled(); + */ + function toHaveBeenCalled() { + return { + compare: function(actual) { + var result = {}; + + if (!j$.isSpy(actual)) { + throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); + } + + if (arguments.length > 1) { + throw new Error(getErrorMsg('Does not take arguments, use toHaveBeenCalledWith')); + } + + result.pass = actual.calls.any(); + + result.message = result.pass ? + 'Expected spy ' + actual.and.identity() + ' not to have been called.' : + 'Expected spy ' + actual.and.identity() + ' to have been called.'; + + return result; + } + }; + } + + return toHaveBeenCalled; +}; + +getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledBefore()'); + + /** + * {@link expect} the actual value (a {@link Spy}) to have been called before another {@link Spy}. + * @function + * @name matchers#toHaveBeenCalledBefore + * @param {Spy} expected - {@link Spy} that should have been called after the `actual` {@link Spy}. + * @example + * expect(mySpy).toHaveBeenCalledBefore(otherSpy); + */ + function toHaveBeenCalledBefore() { + return { + compare: function(firstSpy, latterSpy) { + if (!j$.isSpy(firstSpy)) { + throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(firstSpy) + '.')); + } + if (!j$.isSpy(latterSpy)) { + throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(latterSpy) + '.')); + } + + var result = { pass: false }; + + if (!firstSpy.calls.count()) { + result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called.'; + return result; + } + if (!latterSpy.calls.count()) { + result.message = 'Expected spy ' + latterSpy.and.identity() + ' to have been called.'; + return result; + } + + var latest1stSpyCall = firstSpy.calls.mostRecent().invocationOrder; + var first2ndSpyCall = latterSpy.calls.first().invocationOrder; + + result.pass = latest1stSpyCall < first2ndSpyCall; + + if (result.pass) { + result.message = 'Expected spy ' + firstSpy.and.identity() + ' to not have been called before spy ' + latterSpy.and.identity() + ', but it was'; + } else { + var first1stSpyCall = firstSpy.calls.first().invocationOrder; + var latest2ndSpyCall = latterSpy.calls.mostRecent().invocationOrder; + + if(first1stSpyCall < first2ndSpyCall) { + result.message = 'Expected latest call to spy ' + firstSpy.and.identity() + ' to have been called before first call to spy ' + latterSpy.and.identity() + ' (no interleaved calls)'; + } else if (latest2ndSpyCall > latest1stSpyCall) { + result.message = 'Expected first call to spy ' + latterSpy.and.identity() + ' to have been called after latest call to spy ' + firstSpy.and.identity() + ' (no interleaved calls)'; + } else { + result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called before spy ' + latterSpy.and.identity(); + } + } + + return result; + } + }; + } + + return toHaveBeenCalledBefore; +}; + +getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledTimes()'); + + /** + * {@link expect} the actual (a {@link Spy}) to have been called the specified number of times. + * @function + * @name matchers#toHaveBeenCalledTimes + * @param {Number} expected - The number of invocations to look for. + * @example + * expect(mySpy).toHaveBeenCalledTimes(3); + */ + function toHaveBeenCalledTimes() { + return { + compare: function(actual, expected) { + if (!j$.isSpy(actual)) { + throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); + } + + var args = Array.prototype.slice.call(arguments, 0), + result = { pass: false }; + + if (!j$.isNumber_(expected)){ + throw new Error(getErrorMsg('The expected times failed is a required argument and must be a number.')); + } + + actual = args[0]; + var calls = actual.calls.count(); + var timesMessage = expected === 1 ? 'once' : expected + ' times'; + result.pass = calls === expected; + result.message = result.pass ? + 'Expected spy ' + actual.and.identity() + ' not to have been called ' + timesMessage + '. It was called ' + calls + ' times.' : + 'Expected spy ' + actual.and.identity() + ' to have been called ' + timesMessage + '. It was called ' + calls + ' times.'; + return result; + } + }; + } + + return toHaveBeenCalledTimes; +}; + +getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledWith(...arguments)'); + + /** + * {@link expect} the actual (a {@link Spy}) to have been called with particular arguments at least once. + * @function + * @name matchers#toHaveBeenCalledWith + * @param {...Object} - The arguments to look for + * @example + * expect(mySpy).toHaveBeenCalledWith('foo', 'bar', 2); + */ + function toHaveBeenCalledWith(util, customEqualityTesters) { + return { + compare: function() { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1), + result = { pass: false }; + + if (!j$.isSpy(actual)) { + throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); + } + + if (!actual.calls.any()) { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; + return result; + } + + if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { + result.pass = true; + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; + } else { + result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; + } + + return result; + } + }; + } + + return toHaveBeenCalledWith; +}; + +getJasmineRequireObj().toMatch = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect().toMatch( || )'); + + /** + * {@link expect} the actual value to match a regular expression + * @function + * @name matchers#toMatch + * @param {RegExp|String} expected - Value to look for in the string. + * @example + * expect("my string").toMatch(/string$/); + * expect("other string").toMatch("her"); + */ + function toMatch() { + return { + compare: function(actual, expected) { + if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { + throw new Error(getErrorMsg('Expected is not a String or a RegExp')); + } + + var regexp = new RegExp(expected); + + return { + pass: regexp.test(actual) + }; + } + }; + } + + return toMatch; +}; + +getJasmineRequireObj().toThrow = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect(function() {}).toThrow()'); + + /** + * {@link expect} a function to `throw` something. + * @function + * @name matchers#toThrow + * @param {Object} [expected] - Value that should be thrown. If not provided, simply the fact that something was thrown will be checked. + * @example + * expect(function() { return 'things'; }).toThrow('foo'); + * expect(function() { return 'stuff'; }).toThrow(); + */ + function toThrow(util) { + return { + compare: function(actual, expected) { + var result = { pass: false }, + threw = false, + thrown; + + if (typeof actual != 'function') { + throw new Error(getErrorMsg('Actual is not a Function')); + } + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } + + if (!threw) { + result.message = 'Expected function to throw an exception.'; + return result; + } + + if (arguments.length == 1) { + result.pass = true; + result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; + + return result; + } + + if (util.equals(thrown, expected)) { + result.pass = true; + result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; + } else { + result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; + } + + return result; + } + }; + } + + return toThrow; +}; + +getJasmineRequireObj().toThrowError = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'expect(function() {}).toThrowError(, )'); + + /** + * {@link expect} a function to `throw` an `Error`. + * @function + * @name matchers#toThrowError + * @param {Error} [expected] - `Error` constructor the object that was thrown needs to be an instance of. If not provided, `Error` will be used. + * @param {RegExp|String} [message] - The message that should be set on the thrown `Error` + * @example + * expect(function() { return 'things'; }).toThrowError(MyCustomError, 'message'); + * expect(function() { return 'things'; }).toThrowError(MyCustomError, /bar/); + * expect(function() { return 'stuff'; }).toThrowError(MyCustomError); + * expect(function() { return 'other'; }).toThrowError(/foo/); + * expect(function() { return 'other'; }).toThrowError(); + */ + function toThrowError () { + return { + compare: function(actual) { + var threw = false, + pass = {pass: true}, + fail = {pass: false}, + thrown; + + if (typeof actual != 'function') { + throw new Error(getErrorMsg('Actual is not a Function')); + } + + var errorMatcher = getMatcher.apply(null, arguments); + + try { + actual(); + } catch (e) { + threw = true; + thrown = e; + } + + if (!threw) { + fail.message = 'Expected function to throw an Error.'; + return fail; + } + + // Get Error constructor of thrown + if (!isErrorObject(thrown)) { + fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; + return fail; + } + + if (errorMatcher.hasNoSpecifics()) { + pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.'; + return pass; + } + + if (errorMatcher.matches(thrown)) { + pass.message = function() { + return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.'; + }; + return pass; + } else { + fail.message = function() { + return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + + ', but it threw ' + errorMatcher.thrownDescription(thrown) + '.'; + }; + return fail; + } + } + }; + + function getMatcher() { + var expected = null, + errorType = null; + + if (arguments.length == 2) { + expected = arguments[1]; + if (isAnErrorType(expected)) { + errorType = expected; + expected = null; + } + } else if (arguments.length > 2) { + errorType = arguments[1]; + expected = arguments[2]; + if (!isAnErrorType(errorType)) { + throw new Error(getErrorMsg('Expected error type is not an Error.')); + } + } + + if (expected && !isStringOrRegExp(expected)) { + if (errorType) { + throw new Error(getErrorMsg('Expected error message is not a string or RegExp.')); + } else { + throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.')); + } + } + + function messageMatch(message) { + if (typeof expected == 'string') { + return expected == message; + } else { + return expected.test(message); + } + } + + return { + errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception', + thrownDescription: function(thrown) { + var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception', + thrownMessage = ''; + + if (expected) { + thrownMessage = ' with message ' + j$.pp(thrown.message); + } + + return thrownName + thrownMessage; + }, + messageDescription: function() { + if (expected === null) { + return ''; + } else if (expected instanceof RegExp) { + return ' with a message matching ' + j$.pp(expected); + } else { + return ' with message ' + j$.pp(expected); + } + }, + hasNoSpecifics: function() { + return expected === null && errorType === null; + }, + matches: function(error) { + return (errorType === null || error instanceof errorType) && + (expected === null || messageMatch(error.message)); + } + }; + } + + function isStringOrRegExp(potential) { + return potential instanceof RegExp || (typeof potential == 'string'); + } + + function isAnErrorType(type) { + if (typeof type !== 'function') { + return false; + } + + var Surrogate = function() {}; + Surrogate.prototype = type.prototype; + return isErrorObject(new Surrogate()); + } + + function isErrorObject(thrown) { + if (thrown instanceof Error) { + return true; + } + if (thrown && thrown.constructor && thrown.constructor.constructor && + (thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { + return true; + } + return false; + } + } + + return toThrowError; +}; + +getJasmineRequireObj().MockDate = function() { + function MockDate(global) { + var self = this; + var currentTime = 0; + + if (!global || !global.Date) { + self.install = function() {}; + self.tick = function() {}; + self.uninstall = function() {}; + return self; + } + + var GlobalDate = global.Date; + + self.install = function(mockDate) { + if (mockDate instanceof GlobalDate) { + currentTime = mockDate.getTime(); + } else { + currentTime = new GlobalDate().getTime(); + } + + global.Date = FakeDate; + }; + + self.tick = function(millis) { + millis = millis || 0; + currentTime = currentTime + millis; + }; + + self.uninstall = function() { + currentTime = 0; + global.Date = GlobalDate; + }; + + createDateProperties(); + + return self; + + function FakeDate() { + switch(arguments.length) { + case 0: + return new GlobalDate(currentTime); + case 1: + return new GlobalDate(arguments[0]); + case 2: + return new GlobalDate(arguments[0], arguments[1]); + case 3: + return new GlobalDate(arguments[0], arguments[1], arguments[2]); + case 4: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]); + case 5: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4]); + case 6: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4], arguments[5]); + default: + return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], + arguments[4], arguments[5], arguments[6]); + } + } + + function createDateProperties() { + FakeDate.prototype = GlobalDate.prototype; + + FakeDate.now = function() { + if (GlobalDate.now) { + return currentTime; + } else { + throw new Error('Browser does not support Date.now()'); + } + }; + + FakeDate.toSource = GlobalDate.toSource; + FakeDate.toString = GlobalDate.toString; + FakeDate.parse = GlobalDate.parse; + FakeDate.UTC = GlobalDate.UTC; + } + } + + return MockDate; +}; + +getJasmineRequireObj().pp = function(j$) { + + function PrettyPrinter() { + this.ppNestLevel_ = 0; + this.seen = []; + } + + function hasCustomToString(value) { + // value.toString !== Object.prototype.toString if value has no custom toString but is from another context (e.g. + // iframe, web worker) + return value.toString !== Object.prototype.toString && (value.toString() !== Object.prototype.toString.call(value)); + } + + PrettyPrinter.prototype.format = function(value) { + this.ppNestLevel_++; + try { + if (j$.util.isUndefined(value)) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === 0 && 1/value === -Infinity) { + this.emitScalar('-0'); + } else if (value === j$.getGlobal()) { + this.emitScalar(''); + } else if (value.jasmineToString) { + this.emitScalar(value.jasmineToString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (j$.isSpy(value)) { + this.emitScalar('spy on ' + value.and.identity()); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.toString && value.toString() == '[object Set]') { + this.emitSet(value); + } else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) { + this.emitScalar(value.toString()); + } else if (j$.util.arrayContains(this.seen, value)) { + this.emitScalar(''); + } else if (j$.isArray_(value) || j$.isA_('Object', value)) { + this.seen.push(value); + if (j$.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + this.seen.pop(); + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } + }; + + PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } + fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && + obj.__lookupGetter__(property) !== null) : false); + } + }; + + PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; + PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; + + function StringPrettyPrinter() { + PrettyPrinter.call(this); + + this.string = ''; + } + + j$.util.inherit(StringPrettyPrinter, PrettyPrinter); + + StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); + }; + + StringPrettyPrinter.prototype.emitString = function(value) { + this.append('\'' + value + '\''); + }; + + StringPrettyPrinter.prototype.emitArray = function(array) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Array'); + return; + } + var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + this.append('[ '); + for (var i = 0; i < length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + if(array.length > length){ + this.append(', ...'); + } + + var self = this; + var first = array.length === 0; + this.iterateObject(array, function(property, isGetter) { + if (property.match(/^\d+$/)) { + return; + } + + if (first) { + first = false; + } else { + self.append(', '); + } + + self.formatProperty(array, property, isGetter); + }); + + this.append(' ]'); + }; + + StringPrettyPrinter.prototype.emitSet = function(set) { + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + this.append('Set'); + return; + } + this.append('Set( '); + var size = Math.min(set.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); + var iter = set.values(); + for (var i = 0; i < size; i++) { + if (i > 0) { + this.append(', '); + } + this.format(iter.next().value); + } + if (set.size > size){ + this.append(', ...'); + } + this.append(' )'); + }; + + StringPrettyPrinter.prototype.emitObject = function(obj) { + var ctor = obj.constructor, + constructorName; + + constructorName = typeof ctor === 'function' && obj instanceof ctor ? + j$.fnNameFor(obj.constructor) : + 'null'; + + this.append(constructorName); + + if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { + return; + } + + var self = this; + this.append('({ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.formatProperty(obj, property, isGetter); + }); + + this.append(' })'); + }; + + StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) { + this.append(property); + this.append(': '); + if (isGetter) { + this.append(''); + } else { + this.format(obj[property]); + } + }; + + StringPrettyPrinter.prototype.append = function(value) { + this.string += value; + }; + + return function(value) { + var stringPrettyPrinter = new StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; + }; +}; + +getJasmineRequireObj().QueueRunner = function(j$) { + + function once(fn) { + var called = false; + return function() { + if (!called) { + called = true; + fn(); + } + return null; + }; + } + + function QueueRunner(attrs) { + this.queueableFns = attrs.queueableFns || []; + this.onComplete = attrs.onComplete || function() {}; + this.clearStack = attrs.clearStack || function(fn) {fn();}; + this.onException = attrs.onException || function() {}; + this.catchException = attrs.catchException || function() { return true; }; + this.userContext = attrs.userContext || {}; + this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; + this.fail = attrs.fail || function() {}; + this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} }; + } + + QueueRunner.prototype.execute = function() { + var self = this; + this.handleFinalError = function(error) { + self.onException(error); + }; + this.globalErrors.pushListener(this.handleFinalError); + this.run(this.queueableFns, 0); + }; + + QueueRunner.prototype.run = function(queueableFns, recursiveIndex) { + var length = queueableFns.length, + self = this, + iterativeIndex; + + + for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { + var queueableFn = queueableFns[iterativeIndex]; + if (queueableFn.fn.length > 0) { + attemptAsync(queueableFn); + return; + } else { + attemptSync(queueableFn); + } + } + + this.clearStack(function() { + self.globalErrors.popListener(self.handleFinalError); + self.onComplete(); + }); + + function attemptSync(queueableFn) { + try { + queueableFn.fn.call(self.userContext); + } catch (e) { + handleException(e, queueableFn); + } + } + + function attemptAsync(queueableFn) { + var clearTimeout = function () { + Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]); + }, + completedSynchronously = true, + setTimeout = function(delayedFn, delay) { + return Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [delayedFn, delay]]); + }, + handleError = function(error) { + onException(error); + next(); + }, + next = once(function () { + clearTimeout(timeoutId); + self.globalErrors.popListener(handleError); + if (completedSynchronously) { + setTimeout(function() { + self.run(queueableFns, iterativeIndex + 1); + }); + } else { + self.run(queueableFns, iterativeIndex + 1); + } + }), + timeoutId; + + next.fail = function() { + self.fail.apply(null, arguments); + next(); + }; + + self.globalErrors.pushListener(handleError); + + if (queueableFn.timeout) { + timeoutId = setTimeout(function() { + var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'); + onException(error); + next(); + }, queueableFn.timeout()); + } + + try { + queueableFn.fn.call(self.userContext, next); + completedSynchronously = false; + } catch (e) { + handleException(e, queueableFn); + next(); + } + } + + function onException(e) { + self.onException(e); + } + + function handleException(e, queueableFn) { + onException(e); + if (!self.catchException(e)) { + //TODO: set a var when we catch an exception and + //use a finally block to close the loop in a nice way.. + throw e; + } + } + }; + + return QueueRunner; +}; + +getJasmineRequireObj().ReportDispatcher = function() { + function ReportDispatcher(methods) { + + var dispatchedMethods = methods || []; + + for (var i = 0; i < dispatchedMethods.length; i++) { + var method = dispatchedMethods[i]; + this[method] = (function(m) { + return function() { + dispatch(m, arguments); + }; + }(method)); + } + + var reporters = []; + var fallbackReporter = null; + + this.addReporter = function(reporter) { + reporters.push(reporter); + }; + + this.provideFallbackReporter = function(reporter) { + fallbackReporter = reporter; + }; + + this.clearReporters = function() { + reporters = []; + }; + + return this; + + function dispatch(method, args) { + if (reporters.length === 0 && fallbackReporter !== null) { + reporters.push(fallbackReporter); + } + for (var i = 0; i < reporters.length; i++) { + var reporter = reporters[i]; + if (reporter[method]) { + reporter[method].apply(reporter, args); + } + } + } + } + + return ReportDispatcher; +}; + + +getJasmineRequireObj().interface = function(jasmine, env) { + var jasmineInterface = { + /** + * Create a group of specs (often called a suite). + * + * Calls to `describe` can be nested within other calls to compose your suite as a tree. + * @name describe + * @function + * @global + * @param {String} description Textual description of the group + * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs + */ + describe: function(description, specDefinitions) { + return env.describe(description, specDefinitions); + }, + + /** + * A temporarily disabled [`describe`]{@link describe} + * + * Specs within an `xdescribe` will be marked pending and not executed + * @name xdescribe + * @function + * @global + * @param {String} description Textual description of the group + * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs + */ + xdescribe: function(description, specDefinitions) { + return env.xdescribe(description, specDefinitions); + }, + + /** + * A focused [`describe`]{@link describe} + * + * If suites or specs are focused, only those that are focused will be executed + * @see fit + * @name fdescribe + * @function + * @global + * @param {String} description Textual description of the group + * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs + */ + fdescribe: function(description, specDefinitions) { + return env.fdescribe(description, specDefinitions); + }, + + /** + * Define a single spec. A spec should contain one or more {@link expect|expectations} that test the state of the code. + * + * A spec whose expectations all succeed will be passing and a spec with any failures will fail. + * @name it + * @function + * @global + * @param {String} description Textual description of what this spec is checking + * @param {Function} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`. + * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec. + */ + it: function() { + return env.it.apply(env, arguments); + }, + + /** + * A temporarily disabled [`it`]{@link it} + * + * The spec will report as `pending` and will not be executed. + * @name xit + * @function + * @global + * @param {String} description Textual description of what this spec is checking. + * @param {Function} [testFunction] Function that contains the code of your test. Will not be executed. + */ + xit: function() { + return env.xit.apply(env, arguments); + }, + + /** + * A focused [`it`]{@link it} + * + * If suites or specs are focused, only those that are focused will be executed. + * @name fit + * @function + * @global + * @param {String} description Textual description of what this spec is checking. + * @param {Function} testFunction Function that contains the code of your test. + * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec. + */ + fit: function() { + return env.fit.apply(env, arguments); + }, + + /** + * Run some shared setup before each of the specs in the {@link describe} in which it is called. + * @name beforeEach + * @function + * @global + * @param {Function} [function] Function that contains the code to setup your specs. + * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach. + */ + beforeEach: function() { + return env.beforeEach.apply(env, arguments); + }, + + /** + * Run some shared teardown after each of the specs in the {@link describe} in which it is called. + * @name afterEach + * @function + * @global + * @param {Function} [function] Function that contains the code to teardown your specs. + * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach. + */ + afterEach: function() { + return env.afterEach.apply(env, arguments); + }, + + /** + * Run some shared setup once before all of the specs in the {@link describe} are run. + * + * _Note:_ Be careful, sharing the setup from a beforeAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail. + * @name beforeAll + * @function + * @global + * @param {Function} [function] Function that contains the code to setup your specs. + * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll. + */ + beforeAll: function() { + return env.beforeAll.apply(env, arguments); + }, + + /** + * Run some shared teardown once before all of the specs in the {@link describe} are run. + * + * _Note:_ Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail. + * @name afterAll + * @function + * @global + * @param {Function} [function] Function that contains the code to teardown your specs. + * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll. + */ + afterAll: function() { + return env.afterAll.apply(env, arguments); + }, + + /** + * Create an expectation for a spec. + * @name expect + * @function + * @global + * @param {Object} actual - Actual computed value to test expectations against. + * @return {matchers} + */ + expect: function(actual) { + return env.expect(actual); + }, + + /** + * Mark a spec as pending, expectation results will be ignored. + * @name pending + * @function + * @global + * @param {String} [message] - Reason the spec is pending. + */ + pending: function() { + return env.pending.apply(env, arguments); + }, + + /** + * Explicitly mark a spec as failed. + * @name fail + * @function + * @global + * @param {String|Error} [error] - Reason for the failure. + */ + fail: function() { + return env.fail.apply(env, arguments); + }, + + /** + * Install a spy onto an existing object. + * @name spyOn + * @function + * @global + * @param {Object} obj - The object upon which to install the {@link Spy}. + * @param {String} methodName - The name of the method to replace with a {@link Spy}. + * @returns {Spy} + */ + spyOn: function(obj, methodName) { + return env.spyOn(obj, methodName); + }, + + /** + * Install a spy on a property onto an existing object. + * @name spyOnProperty + * @function + * @global + * @param {Object} obj - The object upon which to install the {@link Spy} + * @param {String} propertyName - The name of the property to replace with a {@link Spy}. + * @param {String} [accessType=get] - The access type (get|set) of the property to {@link Spy} on. + * @returns {Spy} + */ + spyOnProperty: function(obj, methodName, accessType) { + return env.spyOnProperty(obj, methodName, accessType); + }, + + jsApiReporter: new jasmine.JsApiReporter({ + timer: new jasmine.Timer() + }), + + /** + * @namespace jasmine + */ + jasmine: jasmine + }; + + /** + * Add a custom equality tester for the current scope of specs. + * + * _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. + * @name jasmine.addCustomEqualityTester + * @function + * @param {Function} tester - A function which takes two arguments to compare and returns a `true` or `false` comparison result if it knows how to compare them, and `undefined` otherwise. + * @see custom_equality + */ + jasmine.addCustomEqualityTester = function(tester) { + env.addCustomEqualityTester(tester); + }; + + /** + * Add custom matchers for the current scope of specs. + * + * _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. + * @name jasmine.addMatchers + * @function + * @param {Object} matchers - Keys from this object will be the new matcher names. + * @see custom_matcher + */ + jasmine.addMatchers = function(matchers) { + return env.addMatchers(matchers); + }; + + /** + * Get the currently booted mock {Clock} for this Jasmine environment. + * @name jasmine.clock + * @function + * @returns {Clock} + */ + jasmine.clock = function() { + return env.clock; + }; + + return jasmineInterface; +}; + +getJasmineRequireObj().Spy = function (j$) { + + var nextOrder = (function() { + var order = 0; + + return function() { + return order++; + }; + })(); + + /** + * _Note:_ Do not construct this directly, use {@link spyOn}, {@link spyOnProperty}, {@link jasmine.createSpy}, or {@link jasmine.createSpyObj} + * @constructor + * @name Spy + */ + function Spy(name, originalFn) { + var numArgs = (typeof originalFn === 'function' ? originalFn.length : 0), + wrapper = makeFunc(numArgs, function () { + return spy.apply(this, Array.prototype.slice.call(arguments)); + }), + spyStrategy = new j$.SpyStrategy({ + name: name, + fn: originalFn, + getSpy: function () { + return wrapper; + } + }), + callTracker = new j$.CallTracker(), + spy = function () { + /** + * @name Spy.callData + * @property {object} object - `this` context for the invocation. + * @property {number} invocationOrder - Order of the invocation. + * @property {Array} args - The arguments passed for this invocation. + */ + var callData = { + object: this, + invocationOrder: nextOrder(), + args: Array.prototype.slice.apply(arguments) + }; + + callTracker.track(callData); + var returnValue = spyStrategy.exec.apply(this, arguments); + callData.returnValue = returnValue; + + return returnValue; + }; + + function makeFunc(length, fn) { + switch (length) { + case 1 : return function (a) { return fn.apply(this, arguments); }; + case 2 : return function (a,b) { return fn.apply(this, arguments); }; + case 3 : return function (a,b,c) { return fn.apply(this, arguments); }; + case 4 : return function (a,b,c,d) { return fn.apply(this, arguments); }; + case 5 : return function (a,b,c,d,e) { return fn.apply(this, arguments); }; + case 6 : return function (a,b,c,d,e,f) { return fn.apply(this, arguments); }; + case 7 : return function (a,b,c,d,e,f,g) { return fn.apply(this, arguments); }; + case 8 : return function (a,b,c,d,e,f,g,h) { return fn.apply(this, arguments); }; + case 9 : return function (a,b,c,d,e,f,g,h,i) { return fn.apply(this, arguments); }; + default : return function () { return fn.apply(this, arguments); }; + } + } + + for (var prop in originalFn) { + if (prop === 'and' || prop === 'calls') { + throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); + } + + wrapper[prop] = originalFn[prop]; + } + + wrapper.and = spyStrategy; + wrapper.calls = callTracker; + + return wrapper; + } + + return Spy; +}; + +getJasmineRequireObj().SpyRegistry = function(j$) { + + var getErrorMsg = j$.formatErrorMsg('', 'spyOn(, )'); + + function SpyRegistry(options) { + options = options || {}; + var currentSpies = options.currentSpies || function() { return []; }; + + this.allowRespy = function(allow){ + this.respy = allow; + }; + + this.spyOn = function(obj, methodName) { + + if (j$.util.isUndefined(obj) || obj === null) { + throw new Error(getErrorMsg('could not find an object to spy upon for ' + methodName + '()')); + } + + if (j$.util.isUndefined(methodName) || methodName === null) { + throw new Error(getErrorMsg('No method name supplied')); + } + + if (j$.util.isUndefined(obj[methodName])) { + throw new Error(getErrorMsg(methodName + '() method does not exist')); + } + + if (obj[methodName] && j$.isSpy(obj[methodName]) ) { + if ( !!this.respy ){ + return obj[methodName]; + }else { + throw new Error(getErrorMsg(methodName + ' has already been spied upon')); + } + } + + var descriptor; + try { + descriptor = Object.getOwnPropertyDescriptor(obj, methodName); + } catch(e) { + // IE 8 doesn't support `definePropery` on non-DOM nodes + } + + if (descriptor && !(descriptor.writable || descriptor.set)) { + throw new Error(getErrorMsg(methodName + ' is not declared writable or has no setter')); + } + + var originalMethod = obj[methodName], + spiedMethod = j$.createSpy(methodName, originalMethod), + restoreStrategy; + + if (Object.prototype.hasOwnProperty.call(obj, methodName)) { + restoreStrategy = function() { + obj[methodName] = originalMethod; + }; + } else { + restoreStrategy = function() { + if (!delete obj[methodName]) { + obj[methodName] = originalMethod; + } + }; + } + + currentSpies().push({ + restoreObjectToOriginalState: restoreStrategy + }); + + obj[methodName] = spiedMethod; + + return spiedMethod; + }; + + this.spyOnProperty = function (obj, propertyName, accessType) { + accessType = accessType || 'get'; + + if (j$.util.isUndefined(obj)) { + throw new Error('spyOn could not find an object to spy upon for ' + propertyName + ''); + } + + if (j$.util.isUndefined(propertyName)) { + throw new Error('No property name supplied'); + } + + var descriptor; + try { + descriptor = j$.util.getPropertyDescriptor(obj, propertyName); + } catch(e) { + // IE 8 doesn't support `definePropery` on non-DOM nodes + } + + if (!descriptor) { + throw new Error(propertyName + ' property does not exist'); + } + + if (!descriptor.configurable) { + throw new Error(propertyName + ' is not declared configurable'); + } + + if(!descriptor[accessType]) { + throw new Error('Property ' + propertyName + ' does not have access type ' + accessType); + } + + if (j$.isSpy(descriptor[accessType])) { + //TODO?: should this return the current spy? Downside: may cause user confusion about spy state + throw new Error(propertyName + ' has already been spied upon'); + } + + var originalDescriptor = j$.util.clone(descriptor), + spy = j$.createSpy(propertyName, descriptor[accessType]), + restoreStrategy; + + if (Object.prototype.hasOwnProperty.call(obj, propertyName)) { + restoreStrategy = function() { + Object.defineProperty(obj, propertyName, originalDescriptor); + }; + } else { + restoreStrategy = function() { + delete obj[propertyName]; + }; + } + + currentSpies().push({ + restoreObjectToOriginalState: restoreStrategy + }); + + descriptor[accessType] = spy; + + Object.defineProperty(obj, propertyName, descriptor); + + return spy; + }; + + this.clearSpies = function() { + var spies = currentSpies(); + for (var i = spies.length - 1; i >= 0; i--) { + var spyEntry = spies[i]; + spyEntry.restoreObjectToOriginalState(); + } + }; + } + + return SpyRegistry; +}; + +getJasmineRequireObj().SpyStrategy = function(j$) { + + /** + * @namespace Spy#and + */ + function SpyStrategy(options) { + options = options || {}; + + var identity = options.name || 'unknown', + originalFn = options.fn || function() {}, + getSpy = options.getSpy || function() {}, + plan = function() {}; + + /** + * Return the identifying information for the spy. + * @name Spy#and#identity + * @function + * @returns {String} + */ + this.identity = function() { + return identity; + }; + + /** + * Execute the current spy strategy. + * @name Spy#and#exec + * @function + */ + this.exec = function() { + return plan.apply(this, arguments); + }; + + /** + * Tell the spy to call through to the real implementation when invoked. + * @name Spy#and#callThrough + * @function + */ + this.callThrough = function() { + plan = originalFn; + return getSpy(); + }; + + /** + * Tell the spy to return the value when invoked. + * @name Spy#and#returnValue + * @function + * @param {*} value The value to return. + */ + this.returnValue = function(value) { + plan = function() { + return value; + }; + return getSpy(); + }; + + /** + * Tell the spy to return one of the specified values (sequentially) each time the spy is invoked. + * @name Spy#and#returnValues + * @function + * @param {...*} values - Values to be returned on subsequent calls to the spy. + */ + this.returnValues = function() { + var values = Array.prototype.slice.call(arguments); + plan = function () { + return values.shift(); + }; + return getSpy(); + }; + + /** + * Tell the spy to throw an error when invoked. + * @name Spy#and#throwError + * @function + * @param {Error|String} something Thing to throw + */ + this.throwError = function(something) { + var error = (something instanceof Error) ? something : new Error(something); + plan = function() { + throw error; + }; + return getSpy(); + }; + + /** + * Tell the spy to call a fake implementation when invoked. + * @name Spy#and#callFake + * @function + * @param {Function} fn The function to invoke with the passed parameters. + */ + this.callFake = function(fn) { + if(!j$.isFunction_(fn)) { + throw new Error('Argument passed to callFake should be a function, got ' + fn); + } + plan = fn; + return getSpy(); + }; + + /** + * Tell the spy to do nothing when invoked. This is the default. + * @name Spy#and#stub + * @function + */ + this.stub = function(fn) { + plan = function() {}; + return getSpy(); + }; + } + + return SpyStrategy; +}; + +getJasmineRequireObj().Suite = function(j$) { + function Suite(attrs) { + this.env = attrs.env; + this.id = attrs.id; + this.parentSuite = attrs.parentSuite; + this.description = attrs.description; + this.expectationFactory = attrs.expectationFactory; + this.expectationResultFactory = attrs.expectationResultFactory; + this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; + + this.beforeFns = []; + this.afterFns = []; + this.beforeAllFns = []; + this.afterAllFns = []; + + this.children = []; + + this.result = { + id: this.id, + description: this.description, + fullName: this.getFullName(), + failedExpectations: [] + }; + } + + Suite.prototype.expect = function(actual) { + return this.expectationFactory(actual, this); + }; + + Suite.prototype.getFullName = function() { + var fullName = []; + for (var parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) { + if (parentSuite.parentSuite) { + fullName.unshift(parentSuite.description); + } + } + return fullName.join(' '); + }; + + Suite.prototype.pend = function() { + this.markedPending = true; + }; + + Suite.prototype.beforeEach = function(fn) { + this.beforeFns.unshift(fn); + }; + + Suite.prototype.beforeAll = function(fn) { + this.beforeAllFns.push(fn); + }; + + Suite.prototype.afterEach = function(fn) { + this.afterFns.unshift(fn); + }; + + Suite.prototype.afterAll = function(fn) { + this.afterAllFns.unshift(fn); + }; + + Suite.prototype.addChild = function(child) { + this.children.push(child); + }; + + Suite.prototype.status = function() { + if (this.markedPending) { + return 'pending'; + } + + if (this.result.failedExpectations.length > 0) { + return 'failed'; + } else { + return 'finished'; + } + }; + + Suite.prototype.isExecutable = function() { + return !this.markedPending; + }; + + Suite.prototype.canBeReentered = function() { + return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0; + }; + + Suite.prototype.getResult = function() { + this.result.status = this.status(); + return this.result; + }; + + Suite.prototype.sharedUserContext = function() { + if (!this.sharedContext) { + this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {}; + } + + return this.sharedContext; + }; + + Suite.prototype.clonedSharedUserContext = function() { + return clone(this.sharedUserContext()); + }; + + Suite.prototype.onException = function() { + if (arguments[0] instanceof j$.errors.ExpectationFailed) { + return; + } + + if(isAfterAll(this.children)) { + var data = { + matcherName: '', + passed: false, + expected: '', + actual: '', + error: arguments[0] + }; + this.result.failedExpectations.push(this.expectationResultFactory(data)); + } else { + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + child.onException.apply(child, arguments); + } + } + }; + + Suite.prototype.addExpectationResult = function () { + if(isAfterAll(this.children) && isFailure(arguments)){ + var data = arguments[1]; + this.result.failedExpectations.push(this.expectationResultFactory(data)); + if(this.throwOnExpectationFailure) { + throw new j$.errors.ExpectationFailed(); + } + } else { + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + try { + child.addExpectationResult.apply(child, arguments); + } catch(e) { + // keep going + } + } + } + }; + + function isAfterAll(children) { + return children && children[0].result.status; + } + + function isFailure(args) { + return !args[0]; + } + + function clone(obj) { + var clonedObj = {}; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + clonedObj[prop] = obj[prop]; + } + } + + return clonedObj; + } + + return Suite; +}; + +if (typeof window == void 0 && typeof exports == 'object') { + exports.Suite = jasmineRequire.Suite; +} + +getJasmineRequireObj().Timer = function() { + var defaultNow = (function(Date) { + return function() { return new Date().getTime(); }; + })(Date); + + function Timer(options) { + options = options || {}; + + var now = options.now || defaultNow, + startTime; + + this.start = function() { + startTime = now(); + }; + + this.elapsed = function() { + return now() - startTime; + }; + } + + return Timer; +}; + +getJasmineRequireObj().TreeProcessor = function() { + function TreeProcessor(attrs) { + var tree = attrs.tree, + runnableIds = attrs.runnableIds, + queueRunnerFactory = attrs.queueRunnerFactory, + nodeStart = attrs.nodeStart || function() {}, + nodeComplete = attrs.nodeComplete || function() {}, + orderChildren = attrs.orderChildren || function(node) { return node.children; }, + stats = { valid: true }, + processed = false, + defaultMin = Infinity, + defaultMax = 1 - Infinity; + + this.processTree = function() { + processNode(tree, false); + processed = true; + return stats; + }; + + this.execute = function(done) { + if (!processed) { + this.processTree(); + } + + if (!stats.valid) { + throw 'invalid order'; + } + + var childFns = wrapChildren(tree, 0); + + queueRunnerFactory({ + queueableFns: childFns, + userContext: tree.sharedUserContext(), + onException: function() { + tree.onException.apply(tree, arguments); + }, + onComplete: done + }); + }; + + function runnableIndex(id) { + for (var i = 0; i < runnableIds.length; i++) { + if (runnableIds[i] === id) { + return i; + } + } + } + + function processNode(node, parentEnabled) { + var executableIndex = runnableIndex(node.id); + + if (executableIndex !== undefined) { + parentEnabled = true; + } + + parentEnabled = parentEnabled && node.isExecutable(); + + if (!node.children) { + stats[node.id] = { + executable: parentEnabled && node.isExecutable(), + segments: [{ + index: 0, + owner: node, + nodes: [node], + min: startingMin(executableIndex), + max: startingMax(executableIndex) + }] + }; + } else { + var hasExecutableChild = false; + + var orderedChildren = orderChildren(node); + + for (var i = 0; i < orderedChildren.length; i++) { + var child = orderedChildren[i]; + + processNode(child, parentEnabled); + + if (!stats.valid) { + return; + } + + var childStats = stats[child.id]; + + hasExecutableChild = hasExecutableChild || childStats.executable; + } + + stats[node.id] = { + executable: hasExecutableChild + }; + + segmentChildren(node, orderedChildren, stats[node.id], executableIndex); + + if (!node.canBeReentered() && stats[node.id].segments.length > 1) { + stats = { valid: false }; + } + } + } + + function startingMin(executableIndex) { + return executableIndex === undefined ? defaultMin : executableIndex; + } + + function startingMax(executableIndex) { + return executableIndex === undefined ? defaultMax : executableIndex; + } + + function segmentChildren(node, orderedChildren, nodeStats, executableIndex) { + var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) }, + result = [currentSegment], + lastMax = defaultMax, + orderedChildSegments = orderChildSegments(orderedChildren); + + function isSegmentBoundary(minIndex) { + return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1; + } + + for (var i = 0; i < orderedChildSegments.length; i++) { + var childSegment = orderedChildSegments[i], + maxIndex = childSegment.max, + minIndex = childSegment.min; + + if (isSegmentBoundary(minIndex)) { + currentSegment = {index: result.length, owner: node, nodes: [], min: defaultMin, max: defaultMax}; + result.push(currentSegment); + } + + currentSegment.nodes.push(childSegment); + currentSegment.min = Math.min(currentSegment.min, minIndex); + currentSegment.max = Math.max(currentSegment.max, maxIndex); + lastMax = maxIndex; + } + + nodeStats.segments = result; + } + + function orderChildSegments(children) { + var specifiedOrder = [], + unspecifiedOrder = []; + + for (var i = 0; i < children.length; i++) { + var child = children[i], + segments = stats[child.id].segments; + + for (var j = 0; j < segments.length; j++) { + var seg = segments[j]; + + if (seg.min === defaultMin) { + unspecifiedOrder.push(seg); + } else { + specifiedOrder.push(seg); + } + } + } + + specifiedOrder.sort(function(a, b) { + return a.min - b.min; + }); + + return specifiedOrder.concat(unspecifiedOrder); + } + + function executeNode(node, segmentNumber) { + if (node.children) { + return { + fn: function(done) { + nodeStart(node); + + queueRunnerFactory({ + onComplete: function() { + nodeComplete(node, node.getResult()); + done(); + }, + queueableFns: wrapChildren(node, segmentNumber), + userContext: node.sharedUserContext(), + onException: function() { + node.onException.apply(node, arguments); + } + }); + } + }; + } else { + return { + fn: function(done) { node.execute(done, stats[node.id].executable); } + }; + } + } + + function wrapChildren(node, segmentNumber) { + var result = [], + segmentChildren = stats[node.id].segments[segmentNumber].nodes; + + for (var i = 0; i < segmentChildren.length; i++) { + result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index)); + } + + if (!stats[node.id].executable) { + return result; + } + + return node.beforeAllFns.concat(result).concat(node.afterAllFns); + } + } + + return TreeProcessor; +}; + +getJasmineRequireObj().version = function() { + return '2.6.4'; +}; diff --git a/CSF.Screenplay.WebTestWebsite/packages.config b/CSF.Screenplay.WebTestWebsite/packages.config index a9adfd21..a88b0327 100644 --- a/CSF.Screenplay.WebTestWebsite/packages.config +++ b/CSF.Screenplay.WebTestWebsite/packages.config @@ -14,6 +14,7 @@ + From 100b3d6ad307cbea9f324fbdbd339fa70daa66f4 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 21:19:37 +0000 Subject: [PATCH 082/213] WIP #36 - Add a simple script to be tested --- .../CSF.Screenplay.Selenium.csproj | 3 ++ .../ScriptResources/GetDocumentReadyState.cs | 42 +++++++++++++++++++ .../ScriptResources/GetDocumentReadyState.js | 1 + 3 files changed, 46 insertions(+) create mode 100644 CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs create mode 100644 CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 63ec1a43..9b67ff55 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -194,6 +194,7 @@ + @@ -215,6 +216,7 @@ + @@ -222,6 +224,7 @@ Javascripts.resources Javascripts.Designer.cs + diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs new file mode 100644 index 00000000..c11d5e6d --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs @@ -0,0 +1,42 @@ +// +// GetDocumentReadyState.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.ScriptResources +{ + /// + /// Script resource for getting the document ready state. + /// + public class GetDocumentReadyState : ScriptResource + { + /// + /// Gets the name of this script. + /// + /// The name. + public override string Name => "get the ready-state for the web page"; + } +} diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js new file mode 100644 index 00000000..34ad9290 --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js @@ -0,0 +1 @@ +function executeScript(argsArray) { return document.readyState; } \ No newline at end of file From 7cb313cc783ff7ce9ccb3e4e15bb4e7c381c150a Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 21:20:27 +0000 Subject: [PATCH 083/213] WIP #36 - Add a test harness for Jasmine-testing JavaScript resources --- .../CSF.Screenplay.WebTestWebsite.csproj | 12 +++++ .../Controllers/StoredScriptTestController.cs | 44 +++++++++++++++++++ .../Models/JavaScriptTestModel.cs | 37 ++++++++++++++++ .../Views/StoredScriptTest/Index.pt | 27 ++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 CSF.Screenplay.WebTestWebsite/Controllers/StoredScriptTestController.cs create mode 100644 CSF.Screenplay.WebTestWebsite/Models/JavaScriptTestModel.cs create mode 100644 CSF.Screenplay.WebTestWebsite/Views/StoredScriptTest/Index.pt diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index 81ccd0cb..8f6df0c4 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -128,6 +128,8 @@ + + @@ -138,7 +140,9 @@ + + @@ -154,6 +158,7 @@ + @@ -162,6 +167,13 @@ + + + + + {13E2170A-AF71-40FF-8D8C-44FE3D0BDF3B} + CSF.Screenplay.Selenium + diff --git a/CSF.Screenplay.WebTestWebsite/Controllers/StoredScriptTestController.cs b/CSF.Screenplay.WebTestWebsite/Controllers/StoredScriptTestController.cs new file mode 100644 index 00000000..bea5969f --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Controllers/StoredScriptTestController.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using CSF.Screenplay.Selenium.StoredScripts; +using CSF.Screenplay.WebTestWebsite.Models; + +namespace CSF.Screenplay.WebTestWebsite.Controllers +{ + public class StoredScriptTestController : Controller + { + public ActionResult Index(string id) + { + var provider = GetScriptProvider(id); + if(provider == null) return HttpNotFound(); + + var model = new JavaScriptTestModel { + ScriptProvider = provider, + BaseUri = new Uri($"http://localhost:8080/StoredScriptTest/Index/{id}"), + TestFilename = $"{id}.tests.js", + }; + + return View(model); + } + + IProvidesScript GetScriptProvider(string scriptName) + { + var providerType = GetScriptProviderType(scriptName); + if(providerType == null) return null; + return (IProvidesScript) Activator.CreateInstance(providerType); + } + + Type GetScriptProviderType(string scriptName) + { + var providerBaseType = typeof(IProvidesScript); + return providerBaseType + .Assembly + .GetExportedTypes() + .FirstOrDefault(x => providerBaseType.IsAssignableFrom(x) + && x.Name.Equals(scriptName, StringComparison.InvariantCultureIgnoreCase)); + } + } +} diff --git a/CSF.Screenplay.WebTestWebsite/Models/JavaScriptTestModel.cs b/CSF.Screenplay.WebTestWebsite/Models/JavaScriptTestModel.cs new file mode 100644 index 00000000..d7cd96bb --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Models/JavaScriptTestModel.cs @@ -0,0 +1,37 @@ +// +// JavaScriptTestModel.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.WebTestWebsite.Models +{ + public class JavaScriptTestModel : ModelBase + { + public IProvidesScript ScriptProvider { get; set; } + + public string TestFilename { get; set; } + } +} diff --git a/CSF.Screenplay.WebTestWebsite/Views/StoredScriptTest/Index.pt b/CSF.Screenplay.WebTestWebsite/Views/StoredScriptTest/Index.pt new file mode 100644 index 00000000..7f2b36c3 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Views/StoredScriptTest/Index.pt @@ -0,0 +1,27 @@ + + + +JavaScript tests: SampleScript + + + + + + + + + + + +
+ + \ No newline at end of file From fcab2a4c788873fd488417b56146e62beeae47d6 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Tue, 6 Mar 2018 21:20:50 +0000 Subject: [PATCH 084/213] WIP #36 - Add tests for the first of the tested scripts --- .../script-tests/GetDocumentReadyState.tests.js | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js new file mode 100644 index 00000000..5b25e960 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js @@ -0,0 +1,11 @@ +describe('The document ready-state retrieval script', function() { + it('should return a string', function() { + var result = executeScript(); + expect(typeof result).toBe('string'); + }); + + it('should be equal to \'complete\'', function() { + var result = executeScript(); + expect(result).toBe('complete'); + }); +}); \ No newline at end of file From a51567793c3229599a2ae6dbe3c7015abf1ce86f Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Wed, 7 Mar 2018 20:28:57 +0000 Subject: [PATCH 085/213] Trivial - remove redundant code --- .../CSF.Screenplay.Selenium.Tests.csproj | 1 - .../Pages/GoogleHomePage.cs | 12 ------------ 2 files changed, 13 deletions(-) delete mode 100644 CSF.Screenplay.Selenium.Tests/Pages/GoogleHomePage.cs diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index 01f0cc84..9ffea8a6 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -85,7 +85,6 @@ - diff --git a/CSF.Screenplay.Selenium.Tests/Pages/GoogleHomePage.cs b/CSF.Screenplay.Selenium.Tests/Pages/GoogleHomePage.cs deleted file mode 100644 index 7a3de601..00000000 --- a/CSF.Screenplay.Selenium.Tests/Pages/GoogleHomePage.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using CSF.Screenplay.Selenium.Models; - -namespace CSF.Screenplay.Selenium.Tests.Pages -{ - public class GoogleHomePage : Page - { - public override string GetName() => "Google's US home page"; - - public override IUriProvider GetUriProvider() => AppUri.Absolute("https://google.com/", "Google"); - } -} From b82c85c42283635dd412843b740d573e72c5a9dc Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Wed, 7 Mar 2018 20:29:36 +0000 Subject: [PATCH 086/213] WIP #36 - Add new test which runs the testing harness for all scripts --- .../CSF.Screenplay.Selenium.Tests.csproj | 8 ++ .../Pages/ScriptTestingHarness.cs | 61 ++++++++++++++ CSF.Screenplay.Selenium.Tests/Personas/Joe.cs | 41 +++++++++ .../ScreenplayConfig.cs | 1 - .../TestAllScriptsViaTestingHarness.cs | 53 ++++++++++++ .../Tasks/AllOfTheScriptTestResults.cs | 83 +++++++++++++++++++ .../Tasks/AllOfTheScriptTypes.cs | 53 ++++++++++++ .../Tasks/ScriptTestResult.cs | 46 ++++++++++ .../VerifyThatAllOfTheScriptTestsPassed.cs | 64 ++++++++++++++ 9 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs create mode 100644 CSF.Screenplay.Selenium.Tests/Personas/Joe.cs create mode 100644 CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs create mode 100644 CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs create mode 100644 CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs create mode 100644 CSF.Screenplay.Selenium.Tests/Tasks/ScriptTestResult.cs create mode 100644 CSF.Screenplay.Selenium.Tests/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index 9ffea8a6..c22cc5de 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -116,6 +116,13 @@ + + + + + + + @@ -125,6 +132,7 @@ + diff --git a/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs b/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs new file mode 100644 index 00000000..edca788a --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs @@ -0,0 +1,61 @@ +// +// ScriptTestingHarness.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.Models; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.Tests.Pages +{ + public class ScriptTestingHarness : Page + { + readonly IProvidesScript scriptProvider; + + public override string GetName() => $"the JavaScript testing harness for \"{scriptProvider.Name}\""; + + public override IUriProvider GetUriProvider() + => new AppUri($"StoredScriptTest/Index/{scriptProvider.GetType().Name}"); + + public static ILocatorBasedTarget TheResultsBar + => new CssSelector(".jasmine_html-reporter .jasmine-bar", "the Jasmine results bar"); + + public ScriptTestingHarness(IProvidesScript scriptProvider) + { + if(scriptProvider == null) + throw new ArgumentNullException(nameof(scriptProvider)); + + this.scriptProvider = scriptProvider; + } + + public static ScriptTestingHarness For() where TScript : IProvidesScript, new() + => new ScriptTestingHarness(new TScript()); + + public static ScriptTestingHarness For(Type scriptType) + => new ScriptTestingHarness((IProvidesScript) Activator.CreateInstance(scriptType)); + + public static ScriptTestingHarness For(IProvidesScript script) + => new ScriptTestingHarness(script); + } +} diff --git a/CSF.Screenplay.Selenium.Tests/Personas/Joe.cs b/CSF.Screenplay.Selenium.Tests/Personas/Joe.cs new file mode 100644 index 00000000..bfa62bba --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Personas/Joe.cs @@ -0,0 +1,41 @@ +// +// Joe.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.Abilities; + +namespace CSF.Screenplay.Selenium.Tests.Personas +{ + public class Joe : Persona + { + public override string Name => "Joe"; + + public override void GrantAbilities(Actors.ICanReceiveAbilities actor, FlexDi.IResolvesServices resolver) + { + var browseTheWeb = resolver.Resolve(); + actor.IsAbleTo(browseTheWeb); + } + } +} diff --git a/CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs b/CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs index 3fd5def4..7cb0e138 100644 --- a/CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs +++ b/CSF.Screenplay.Selenium.Tests/ScreenplayConfig.cs @@ -17,7 +17,6 @@ public class ScreenplayConfig : IIntegrationConfig { public void Configure(IIntegrationConfigBuilder builder) { - builder.UseCast(); builder.UseReporting(config => { config .SubscribeToActorsCreatedInCast() diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs new file mode 100644 index 00000000..e72bcdf1 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs @@ -0,0 +1,53 @@ +// +// TestAllScriptsViaTestingHarness.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Linq; +using CSF.Screenplay.NUnit; +using CSF.Screenplay.Selenium.Builders; +using CSF.Screenplay.Selenium.Tests.Pages; +using CSF.Screenplay.Selenium.Tests.Personas; +using CSF.Screenplay.Selenium.Tests.Tasks; +using NUnit.Framework; +using static CSF.Screenplay.StepComposer; + +namespace CSF.Screenplay.Selenium.Tests.StoredScripts +{ + [TestFixture] + [Description("A test for every stored script included in the main assembly, via the Jasmine testing harness.")] + public class TestAllScriptsViaTestingHarness + { + [Test,Screenplay] + [Description("Run every script in the main assembly through the Jasmine test harness and verify that they all pass")] + public void Every_script_in_the_main_assembly_must_pass_its_Jasmine_test_suite(ICast cast) + { + var joe = cast.Get(); + + var scriptTypes = Given(joe).Got(AllOfTheScriptTypes.FromTheMainAssembly()); + var results = When(joe).Gets(AllOfTheScriptTestResults.ForTheScriptTypes(scriptTypes)); + Then(joe).Should(VerifyThatAllOfTheScriptTestsPassed.ForTheResults(results)); + } + } +} diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs new file mode 100644 index 00000000..404151e7 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs @@ -0,0 +1,83 @@ +// +// GetAllOfTheScriptTestResults.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.Builders; +using CSF.Screenplay.Selenium.StoredScripts; +using CSF.Screenplay.Selenium.Tests.Pages; + +namespace CSF.Screenplay.Selenium.Tests.Tasks +{ + public class AllOfTheScriptTestResults : Question> + { + const string JasminePassedClassPattern = @"\bjasmine-passed\b"; + static readonly Regex PassMatcher = new Regex(JasminePassedClassPattern, RegexOptions.Compiled); + + readonly IReadOnlyCollection types; + + protected override string GetReport(INamed actor) => $"{actor.Name} runs all of the Jasmine script tests and gets their results"; + + protected override IReadOnlyCollection PerformAs(IPerformer actor) + => GetResults(actor).ToArray(); + + IEnumerable GetResults(IPerformer actor) + { + foreach(var type in types) + yield return GetSingleScriptTestResult(GetTheScript(type), actor); + } + + ScriptTestResult GetSingleScriptTestResult(IProvidesScript theScript, IPerformer actor) + { + var theTestPage = ScriptTestingHarness.For(theScript); + actor.Perform(OpenTheirBrowserOn.ThePage(theTestPage)); + + actor.Perform(Wait.ForAtMost(5).Seconds().OrUntil(ScriptTestingHarness.TheResultsBar).IsVisible()); + + var classAttribute = actor.Perform(TheAttribute.Named("class").From(ScriptTestingHarness.TheResultsBar)); + var testsPassed = PassMatcher.IsMatch(classAttribute); + + return new ScriptTestResult(theScript, testsPassed); + } + + IProvidesScript GetTheScript(Type theScriptType) + => (IProvidesScript) Activator.CreateInstance(theScriptType); + + public AllOfTheScriptTestResults(IReadOnlyCollection types) + { + if(types == null) + throw new ArgumentNullException(nameof(types)); + + this.types = types; + } + + public static IQuestion> ForTheScriptTypes(IReadOnlyCollection types) + => new AllOfTheScriptTestResults(types); + } +} diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs new file mode 100644 index 00000000..b0ab2762 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs @@ -0,0 +1,53 @@ +// +// GetAllOfTheScriptTypes.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.Tests.Tasks +{ + public class AllOfTheScriptTypes : Question> + { + protected override string GetReport(INamed actor) + => $"{actor.Name} gets all of the script providers from the main assembly."; + + protected override IReadOnlyCollection PerformAs(IPerformer actor) + { + var assembly = typeof(IProvidesScript).Assembly; + + return assembly + .GetExportedTypes() + .Where(x => typeof(IProvidesScript).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract) + .ToArray(); + } + + public static IQuestion> FromTheMainAssembly() + => new AllOfTheScriptTypes(); + } +} diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/ScriptTestResult.cs b/CSF.Screenplay.Selenium.Tests/Tasks/ScriptTestResult.cs new file mode 100644 index 00000000..46a4371f --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Tasks/ScriptTestResult.cs @@ -0,0 +1,46 @@ +// +// ScriptTestResult.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.Tests.Tasks +{ + public class ScriptTestResult + { + public IProvidesScript Script { get; } + + public bool Success { get; } + + public ScriptTestResult(IProvidesScript script, bool result) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + + Script = script; + Success = result; + } + } +} diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs b/CSF.Screenplay.Selenium.Tests/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs new file mode 100644 index 00000000..147ba33f --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs @@ -0,0 +1,64 @@ +// +// VerifyThatAllOfTheScriptTestsPassed.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; +using NUnit.Framework; + +namespace CSF.Screenplay.Selenium.Tests.Tasks +{ + public class VerifyThatAllOfTheScriptTestsPassed : Performable + { + readonly IReadOnlyCollection results; + + protected override string GetReport(INamed actor) + => $"{actor.Name} verifies that all of the script tests were successful"; + + protected override void PerformAs(IPerformer actor) + { + var failures = results.Where(x => !x.Success).ToArray(); + + Assert.That(failures, + Has.Length.Zero, + "The following scripts failed testing:{0} {1}", + Environment.NewLine, + String.Join($"{Environment.NewLine} ", failures.Select(x => x.Script.Name).ToArray())); + } + + public VerifyThatAllOfTheScriptTestsPassed(IReadOnlyCollection results) + { + if(results == null) + throw new ArgumentNullException(nameof(results)); + + this.results = results; + } + + public static IPerformable ForTheResults(IReadOnlyCollection results) + => new VerifyThatAllOfTheScriptTestsPassed(results); + } +} From 85979eda4d2768be8c385727c30558a8e8e8fbb6 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Wed, 7 Mar 2018 20:45:01 +0000 Subject: [PATCH 087/213] WIP #36 - Refactor to improve reporting --- .../CSF.Screenplay.Selenium.Tests.csproj | 1 + .../Tasks/AllOfTheScriptTestResults.cs | 21 +----- .../Tasks/TestTheStoredScript.cs | 73 +++++++++++++++++++ 3 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index c22cc5de..ea17900c 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -123,6 +123,7 @@ + diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs index 404151e7..7c0d21d5 100644 --- a/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs +++ b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTestResults.cs @@ -37,9 +37,6 @@ namespace CSF.Screenplay.Selenium.Tests.Tasks { public class AllOfTheScriptTestResults : Question> { - const string JasminePassedClassPattern = @"\bjasmine-passed\b"; - static readonly Regex PassMatcher = new Regex(JasminePassedClassPattern, RegexOptions.Compiled); - readonly IReadOnlyCollection types; protected override string GetReport(INamed actor) => $"{actor.Name} runs all of the Jasmine script tests and gets their results"; @@ -50,25 +47,9 @@ protected override IReadOnlyCollection PerformAs(IPerformer ac IEnumerable GetResults(IPerformer actor) { foreach(var type in types) - yield return GetSingleScriptTestResult(GetTheScript(type), actor); - } - - ScriptTestResult GetSingleScriptTestResult(IProvidesScript theScript, IPerformer actor) - { - var theTestPage = ScriptTestingHarness.For(theScript); - actor.Perform(OpenTheirBrowserOn.ThePage(theTestPage)); - - actor.Perform(Wait.ForAtMost(5).Seconds().OrUntil(ScriptTestingHarness.TheResultsBar).IsVisible()); - - var classAttribute = actor.Perform(TheAttribute.Named("class").From(ScriptTestingHarness.TheResultsBar)); - var testsPassed = PassMatcher.IsMatch(classAttribute); - - return new ScriptTestResult(theScript, testsPassed); + yield return actor.Perform(TestTheStoredScript.OfType(type)); } - IProvidesScript GetTheScript(Type theScriptType) - => (IProvidesScript) Activator.CreateInstance(theScriptType); - public AllOfTheScriptTestResults(IReadOnlyCollection types) { if(types == null) diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs b/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs new file mode 100644 index 00000000..1aaffd68 --- /dev/null +++ b/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs @@ -0,0 +1,73 @@ +// +// TestTheStoredScript.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Text.RegularExpressions; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.Builders; +using CSF.Screenplay.Selenium.StoredScripts; +using CSF.Screenplay.Selenium.Tests.Pages; + +namespace CSF.Screenplay.Selenium.Tests.Tasks +{ + public class TestTheStoredScript : Question + { + const string JasminePassedClassPattern = @"\bjasmine-passed\b"; + static readonly Regex PassMatcher = new Regex(JasminePassedClassPattern, RegexOptions.Compiled); + + readonly IProvidesScript script; + + protected override string GetReport(INamed actor) + => $"{actor.Name} gets the result for the script \"{script.Name}\""; + + protected override ScriptTestResult PerformAs(IPerformer actor) + { + var theTestPage = ScriptTestingHarness.For(script); + actor.Perform(OpenTheirBrowserOn.ThePage(theTestPage)); + + actor.Perform(Wait.ForAtMost(5).Seconds().OrUntil(ScriptTestingHarness.TheResultsBar).IsVisible()); + + var classAttribute = actor.Perform(TheAttribute.Named("class").From(ScriptTestingHarness.TheResultsBar)); + var testsPassed = PassMatcher.IsMatch(classAttribute); + + return new ScriptTestResult(script, testsPassed); + } + + public TestTheStoredScript(IProvidesScript script) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + + this.script = script; + } + + public static IQuestion OfType(Type scriptType) + => new TestTheStoredScript(GetTheScript(scriptType)); + + static IProvidesScript GetTheScript(Type theScriptType) + => (IProvidesScript) Activator.CreateInstance(theScriptType); + } +} From f985996954b81fad1541d8885a66ea8e75fc29b5 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Wed, 7 Mar 2018 21:21:25 +0000 Subject: [PATCH 088/213] WIP #36 - Improve existing tests and add new script (localised date) --- .../CSF.Screenplay.Selenium.csproj | 2 + .../Resources/Javascripts.Designer.cs | 12 ----- .../Resources/Javascripts.resx | 9 ---- .../ScriptResources/GetALocalisedDate.cs | 42 +++++++++++++++++ .../ScriptResources/GetALocalisedDate.js | 15 ++++++ .../ScriptResources/GetDocumentReadyState.js | 5 +- .../Tasks/GetTheLocaleFormattedDate.cs | 23 +++++----- .../Waits/WaitUntilThePageLoads.cs | 4 +- .../CSF.Screenplay.WebTestWebsite.csproj | 1 + .../script-tests/GetALocalisedDate.tests.js | 46 +++++++++++++++++++ .../GetDocumentReadyState.tests.js | 2 +- 11 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs create mode 100644 CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 9b67ff55..230f735d 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -195,6 +195,7 @@ + @@ -225,6 +226,7 @@ Javascripts.Designer.cs + diff --git a/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs b/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs index 174a05eb..28005134 100644 --- a/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs +++ b/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs @@ -47,18 +47,6 @@ internal static System.Globalization.CultureInfo Culture { } } - internal static string GetDocumentReadyState { - get { - return ResourceManager.GetString("GetDocumentReadyState", resourceCulture); - } - } - - internal static string GetLocalisedDate { - get { - return ResourceManager.GetString("GetLocalisedDate", resourceCulture); - } - } - internal static string SetValueById { get { return ResourceManager.GetString("SetValueById", resourceCulture); diff --git a/CSF.Screenplay.Selenium/Resources/Javascripts.resx b/CSF.Screenplay.Selenium/Resources/Javascripts.resx index 50840412..6cefb85a 100644 --- a/CSF.Screenplay.Selenium/Resources/Javascripts.resx +++ b/CSF.Screenplay.Selenium/Resources/Javascripts.resx @@ -12,15 +12,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - return document.readyState; - - - return (function(argsArray) { - var y = argsArray[0], m = argsArray[1], d = argsArray[2]; - return new Date(y,m,d).toLocaleDateString(); -}(arguments)); - return (function(window, argsArray) { var diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs new file mode 100644 index 00000000..92213691 --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs @@ -0,0 +1,42 @@ +// +// GetALocalisedDate.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.ScriptResources +{ + /// + /// Script resource for getting a localised date string + /// + public class GetALocalisedDate : ScriptResource + { + /// + /// Gets the name of this script. + /// + /// The name. + public override string Name => "get a localised date string"; + } +} diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js new file mode 100644 index 00000000..8b370cb8 --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js @@ -0,0 +1,15 @@ +function executeScript(argsArray) { + 'use strict'; + + if(!argsArray) throw new Error('Arguments must be a non-null array.'); + if(!(argsArray instanceof Array)) throw new Error('Arguments must be an array.'); + if(argsArray.length != 3) throw new Error('Arguments must contain precisely three elements (Y/M/D).'); + + var year = argsArray[0], month = argsArray[1], day = argsArray[2], theDate; + + if(isNaN(year) || isNaN(month) || isNaN(day)) + throw new Error('The supplied year, month and day must all be numbers.'); + + theDate = new Date(year, month, day); + return theDate.toLocaleDateString(); +} \ No newline at end of file diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js index 34ad9290..b8953856 100644 --- a/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js +++ b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.js @@ -1 +1,4 @@ -function executeScript(argsArray) { return document.readyState; } \ No newline at end of file +function executeScript(argsArray) { + 'use strict'; + return document.readyState; +} \ No newline at end of file diff --git a/CSF.Screenplay.Selenium/Tasks/GetTheLocaleFormattedDate.cs b/CSF.Screenplay.Selenium/Tasks/GetTheLocaleFormattedDate.cs index 97c20f47..2a57f6ea 100644 --- a/CSF.Screenplay.Selenium/Tasks/GetTheLocaleFormattedDate.cs +++ b/CSF.Screenplay.Selenium/Tasks/GetTheLocaleFormattedDate.cs @@ -2,6 +2,7 @@ using CSF.Screenplay.Actors; using CSF.Screenplay.Performables; using CSF.Screenplay.Selenium.Builders; +using CSF.Screenplay.Selenium.ScriptResources; namespace CSF.Screenplay.Selenium.Tasks { @@ -13,25 +14,25 @@ public class GetTheLocaleFormattedDate : Question { readonly DateTime date; - /// - /// Gets the report of the current instance, for the given actor. - /// - /// The human-readable report text. - /// An actor for whom to write the report. + /// + /// Gets the report of the current instance, for the given actor. + /// + /// The human-readable report text. + /// An actor for whom to write the report. protected override string GetReport(INamed actor) => $"{actor.Name} gets the locale-formatted representation of the date {date.ToString("yyyy-MM-dd")}"; - /// - /// Performs this operation, as the given actor. - /// - /// The response or result. - /// The actor performing this task. + /// + /// Performs this operation, as the given actor. + /// + /// The response or result. + /// The actor performing this task. protected override string PerformAs(IPerformer actor) { // Months in JavaScript start with zero, because reasons var month = date.Month - 1; - return (string) actor.Perform(Execute.TheJavaScript(Resources.Javascripts.GetLocalisedDate) + return (string) actor.Perform(Execute.TheJavaScript() .WithTheParameters(date.Year, month, date.Day) .AndGetTheResult()); } diff --git a/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs b/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs index 72d9a91a..66b6f752 100644 --- a/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs +++ b/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs @@ -6,6 +6,7 @@ using CSF.Screenplay.Selenium.Builders; using CSF.Screenplay.Selenium.Models; using CSF.Screenplay.Selenium.Resources; +using CSF.Screenplay.Selenium.ScriptResources; using CSF.Screenplay.Stopwatch; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; @@ -55,8 +56,7 @@ protected override void PerformAs(IPerformer actor) IPerformableJavaScriptWithResult GetAction() { - var script = Javascripts.GetDocumentReadyState; - return Execute.TheJavaScript(script).AndGetTheResult(); + return Execute.TheJavaScript().AndGetTheResult(); } /// diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index 8f6df0c4..78b1c219 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -159,6 +159,7 @@ + diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js new file mode 100644 index 00000000..82a3ca46 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js @@ -0,0 +1,46 @@ +describe('The script which gets a localised date', function() { + describe('should raise errors if the input', function() { + it('is not provided', function() { + expect(function() { + executeScript(); + }).toThrowError(Error, /non-null/); + }); + + it('is null', function() { + expect(function() { + executeScript(null); + }).toThrowError(Error, /non-null/); + }); + + it('is not an array', function() { + expect(function() { + executeScript("Not an array"); + }).toThrowError(Error, /must be an array/); + }); + + it('has only two elements', function() { + expect(function() { + executeScript([1, 2]); + }).toThrowError(Error, /must contain precisely three elements/); + }); + + it('has four elements', function() { + expect(function() { + executeScript([1, 2, 3, 4]); + }).toThrowError(Error, /must contain precisely three elements/); + }); + + it('contains elements which are not numbers', function() { + expect(function() { + executeScript([1, 'not a number', 3]); + }).toThrowError(Error, /must all be numbers/); + }); + }); + + it('should return a string which matches the locale-formatted date', function() { + var expectedResult = new Date(2001, 2, 3).toLocaleDateString(); + var actualResult = executeScript([2001, 2, 3]); + + expect(actualResult).toBe(expectedResult); + }); +}); \ No newline at end of file diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js index 5b25e960..8ad9a97a 100644 --- a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js @@ -1,4 +1,4 @@ -describe('The document ready-state retrieval script', function() { +describe('The script which gets the document ready-state', function() { it('should return a string', function() { var result = executeScript(); expect(typeof result).toBe('string'); From 2b59abdeec4b1b626221a2652e608a189280dd8c Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Thu, 8 Mar 2018 12:58:12 +0000 Subject: [PATCH 089/213] WIP #36 - Update test for the script runner (expected script) --- .../StoredScripts/ScriptRunnerTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs index 47e27415..4f64d539 100644 --- a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs @@ -47,7 +47,8 @@ public void ExecuteScript_passes_correct_script_to_webdriver() Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar"); var expectedExecutedScript = @"function fooBar(argsArray) {} -fooBar(arguments);"; +var argsArray = Array.prototype.slice.call(arguments); +return fooBar(argsArray);"; // Act sut.ExecuteScript(script, driver.Object); From 55b63afa8b3224269650375ab9daa9294a06c76a Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Thu, 8 Mar 2018 13:00:39 +0000 Subject: [PATCH 090/213] WIP #36 - Fix two mistakes in the script runner * It was not converting the arguments object to an array. * It was not returning the result of the function. --- .../StoredScripts/ScriptRunner.cs | 146 +++++++++--------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs index c2eb4db6..7b7b6237 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs @@ -1,38 +1,38 @@ -// -// ScriptRunner.cs -// -// Author: -// Craig Fowler -// -// Copyright (c) 2018 Craig Fowler -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using OpenQA.Selenium; - -namespace CSF.Screenplay.Selenium.StoredScripts -{ - /// - /// Default implementation of - /// - public class ScriptRunner : IRunsScripts - { +// +// ScriptRunner.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.StoredScripts +{ + /// + /// Default implementation of + /// + public class ScriptRunner : IRunsScripts + { /// /// Executes the script and returns the result. /// @@ -40,17 +40,17 @@ public class ScriptRunner : IRunsScripts /// A JavaScript. /// A web driver. /// The script arguments. - public object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments) - { - if(script == null) - throw new ArgumentNullException(nameof(script)); - if(webDriver == null) - throw new ArgumentNullException(nameof(webDriver)); - - var javaScriptRunner = GetJavaScriptExecutor(webDriver); - return javaScriptRunner.ExecuteScript(script, arguments); - } - + public object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + if(webDriver == null) + throw new ArgumentNullException(nameof(webDriver)); + + var javaScriptRunner = GetJavaScriptExecutor(webDriver); + return javaScriptRunner.ExecuteScript(script, arguments); + } + /// /// Executes the script exposed by the given script provider and returns the result. /// @@ -58,28 +58,32 @@ public object ExecuteScript(string script, IWebDriver webDriver, params object[] /// A JavaScript provider. /// A web driver. /// The script arguments. - public object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments) - { - if(script == null) - throw new ArgumentNullException(nameof(script)); - if(webDriver == null) - throw new ArgumentNullException(nameof(webDriver)); - - var runnableScript = GetRunnableScript(script); - return ExecuteScript(runnableScript, webDriver, arguments); - } - - string GetRunnableScript(IProvidesScript script) - => String.Concat(script.GetScript(), Environment.NewLine, $"{script.GetEntryPointName()}(arguments);"); - - IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver) - { - var jsDriver = driver as IJavaScriptExecutor; - - if(jsDriver == null) - throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver)); - - return jsDriver; - } - } -} + public object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + if(webDriver == null) + throw new ArgumentNullException(nameof(webDriver)); + + var runnableScript = GetRunnableScript(script); + return ExecuteScript(runnableScript, webDriver, arguments); + } + + string GetRunnableScript(IProvidesScript script) + => String.Concat(script.GetScript(), + Environment.NewLine, + $"var argsArray = Array.prototype.slice.call(arguments);", + Environment.NewLine, + $"return {script.GetEntryPointName()}(arguments);"); + + IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver) + { + var jsDriver = driver as IJavaScriptExecutor; + + if(jsDriver == null) + throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver)); + + return jsDriver; + } + } +} From 61e33cc87c2ffa049811ae0a75d264a7c6ef562c Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Thu, 8 Mar 2018 13:01:53 +0000 Subject: [PATCH 091/213] WIP #36 - Fix mistake in script runner --- CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs index 7b7b6237..eced4463 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs @@ -74,7 +74,7 @@ string GetRunnableScript(IProvidesScript script) Environment.NewLine, $"var argsArray = Array.prototype.slice.call(arguments);", Environment.NewLine, - $"return {script.GetEntryPointName()}(arguments);"); + $"return {script.GetEntryPointName()}(argsArray);"); IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver) { From 6ad44d8460b5aa2c25f8046be0660936aeb6e465 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Thu, 8 Mar 2018 20:36:24 +0000 Subject: [PATCH 092/213] WIP #36 - Many improvements to the way that scripts execute This includes: * Shared code to validate arguments arrays (with improvements & tests) * Moving the invocation code to a script of its own * Improving the test runner * Improving the names of the test scenarios * Improving the names of the scripts --- .../CSF.Screenplay.Selenium.Tests.csproj | 2 +- .../Pages/ScriptTestingHarness.cs | 2 +- .../StoredScripts/ScriptRunnerTests.cs | 11 +- .../TestAllScriptsViaTestingHarness.cs | 2 +- ...es.cs => AllOfTheExecutableScriptTypes.cs} | 19 +- .../Tasks/TestTheStoredScript.cs | 2 +- .../CSF.Screenplay.Selenium.csproj | 5 + .../ArgumentsArrayValidator.cs | 41 ++++ .../ArgumentsArrayValidator.js | 87 ++++++++ .../ScriptResources/GetALocalisedDate.cs | 22 ++- .../ScriptResources/GetALocalisedDate.js | 12 +- .../ScriptResources/GetDocumentReadyState.cs | 10 +- .../ScriptResources/ScriptInvoker.cs | 59 ++++++ .../ScriptResources/ScriptInvoker.js | 24 +++ .../StoredScripts/IInvokesScripts.cs | 33 ++++ .../StoredScripts/ScriptResource.cs | 30 +-- .../StoredScripts/ScriptRunner.cs | 186 +++++++++--------- .../CSF.Screenplay.WebTestWebsite.csproj | 1 + .../ArgumentsArrayValidator.tests.js | 56 ++++++ .../script-tests/GetALocalisedDate.tests.js | 49 ++--- .../GetDocumentReadyState.tests.js | 2 +- 21 files changed, 484 insertions(+), 171 deletions(-) rename CSF.Screenplay.Selenium.Tests/Tasks/{AllOfTheScriptTypes.cs => AllOfTheExecutableScriptTypes.cs} (73%) create mode 100644 CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.cs create mode 100644 CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.js create mode 100644 CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.cs create mode 100644 CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.js create mode 100644 CSF.Screenplay.Selenium/StoredScripts/IInvokesScripts.cs create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/script-tests/ArgumentsArrayValidator.tests.js diff --git a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj index ea17900c..f18ad1ca 100644 --- a/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj +++ b/CSF.Screenplay.Selenium.Tests/CSF.Screenplay.Selenium.Tests.csproj @@ -119,7 +119,7 @@ - + diff --git a/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs b/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs index edca788a..7881c6af 100644 --- a/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs +++ b/CSF.Screenplay.Selenium.Tests/Pages/ScriptTestingHarness.cs @@ -33,7 +33,7 @@ public class ScriptTestingHarness : Page { readonly IProvidesScript scriptProvider; - public override string GetName() => $"the JavaScript testing harness for \"{scriptProvider.Name}\""; + public override string GetName() => $"the Jasmine test harness for {scriptProvider.Name}"; public override IUriProvider GetUriProvider() => new AppUri($"StoredScriptTest/Index/{scriptProvider.GetType().Name}"); diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs index 4f64d539..0c71c1d5 100644 --- a/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/ScriptRunnerTests.cs @@ -41,13 +41,13 @@ public void ExecuteScript_passes_correct_script_to_webdriver() var script = Mock.Of(); var driver = new Mock(); driver.As(); - var sut = new ScriptRunner(); + var invoker = Mock.Of(x => x.GetScript(It.IsAny()) == "return fooBar(argsArray);"); + var sut = new ScriptRunner(invoker); Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}"); Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar"); var expectedExecutedScript = @"function fooBar(argsArray) {} -var argsArray = Array.prototype.slice.call(arguments); return fooBar(argsArray);"; // Act @@ -66,10 +66,11 @@ public void ExecuteScript_passes_correct_script_arguments_to_webdriver() var script = Mock.Of(); var driver = new Mock(); driver.As(); - var sut = new ScriptRunner(); + var invoker = Mock.Of(x => x.GetScript(It.IsAny()) == String.Empty); + var sut = new ScriptRunner(invoker); - Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}"); - Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar"); + Mock.Get(script).Setup(x => x.GetScript()).Returns(String.Empty); + Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns(String.Empty); // Act sut.ExecuteScript(script, driver.Object, 1, 2, "three"); diff --git a/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs b/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs index e72bcdf1..03d410b4 100644 --- a/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs +++ b/CSF.Screenplay.Selenium.Tests/StoredScripts/TestAllScriptsViaTestingHarness.cs @@ -45,7 +45,7 @@ public void Every_script_in_the_main_assembly_must_pass_its_Jasmine_test_suite(I { var joe = cast.Get(); - var scriptTypes = Given(joe).Got(AllOfTheScriptTypes.FromTheMainAssembly()); + var scriptTypes = Given(joe).Got(AllOfTheExecutableScriptTypes.FromTheMainAssembly()); var results = When(joe).Gets(AllOfTheScriptTestResults.ForTheScriptTypes(scriptTypes)); Then(joe).Should(VerifyThatAllOfTheScriptTestsPassed.ForTheResults(results)); } diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheExecutableScriptTypes.cs similarity index 73% rename from CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs rename to CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheExecutableScriptTypes.cs index b0ab2762..a9531e64 100644 --- a/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheScriptTypes.cs +++ b/CSF.Screenplay.Selenium.Tests/Tasks/AllOfTheExecutableScriptTypes.cs @@ -28,26 +28,31 @@ using System.Linq; using CSF.Screenplay.Actors; using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.ScriptResources; using CSF.Screenplay.Selenium.StoredScripts; namespace CSF.Screenplay.Selenium.Tests.Tasks { - public class AllOfTheScriptTypes : Question> + public class AllOfTheExecutableScriptTypes : Question> { protected override string GetReport(INamed actor) - => $"{actor.Name} gets all of the script providers from the main assembly."; + => $"{actor.Name} gets all of the executable script provider types from the main assembly."; protected override IReadOnlyCollection PerformAs(IPerformer actor) { var assembly = typeof(IProvidesScript).Assembly; + return assembly.GetExportedTypes().Where(IsExecutableScriptType).ToArray(); + } - return assembly - .GetExportedTypes() - .Where(x => typeof(IProvidesScript).IsAssignableFrom(x) && x.IsClass && !x.IsAbstract) - .ToArray(); + bool IsExecutableScriptType(Type type) + { + if(!typeof(IProvidesScript).IsAssignableFrom(type)) return false; + if(!type.IsClass || type.IsAbstract) return false; + if(typeof(IInvokesScripts).IsAssignableFrom(type)) return false; + return true; } public static IQuestion> FromTheMainAssembly() - => new AllOfTheScriptTypes(); + => new AllOfTheExecutableScriptTypes(); } } diff --git a/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs b/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs index 1aaffd68..7f4ef0a8 100644 --- a/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs +++ b/CSF.Screenplay.Selenium.Tests/Tasks/TestTheStoredScript.cs @@ -41,7 +41,7 @@ public class TestTheStoredScript : Question readonly IProvidesScript script; protected override string GetReport(INamed actor) - => $"{actor.Name} gets the result for the script \"{script.Name}\""; + => $"{actor.Name} gets the result for {script.Name}"; protected override ScriptTestResult PerformAs(IPerformer actor) { diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 230f735d..035d64a1 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -196,6 +196,9 @@ + + + @@ -227,6 +230,8 @@ + + diff --git a/CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.cs b/CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.cs new file mode 100644 index 00000000..4cf3ab43 --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.cs @@ -0,0 +1,41 @@ +// +// ArgumentsArrayValidator.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.ScriptResources +{ + public class ArgumentsArrayValidator : ScriptResource + { + const string EntryPointNameConst = "validateArgumentsArray"; + + public static string EntryPointName => EntryPointNameConst; + + public override string Name => "the arguments-array validator"; + + public override string GetEntryPointName() => EntryPointName; + } +} diff --git a/CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.js b/CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.js new file mode 100644 index 00000000..6b653445 --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/ArgumentsArrayValidator.js @@ -0,0 +1,87 @@ +var argumentsArrayValidator = function() +{ + 'use strict'; + + function getLengthParams(min, max) + { + if(typeof min === 'number' && max === undefined) + { + return { + count: min, + validateCount: true, + }; + } + + var minCount, validateMinCount = false, maxCount, validateMaxCount = false; + + if(typeof min === 'number') + { + minCount = min; + validateMinCount = true; + } + + if(typeof max === 'number') + { + maxCount = max; + validateMaxCount = true; + } + + return { + min: minCount, + validateMin: validateMinCount, + max: maxCount, + validateMax: validateMaxCount, + validateCount: false, + }; + } + + function validateType(argsArray) + { + if(!argsArray) throw new Error('Arguments must be a non-null array.'); + if(!(argsArray instanceof Array)) throw new Error('Arguments must be an array.'); + } + + function validateLength(argsArray, lengthParams) + { + if(lengthParams.validateCount && argsArray.length !== lengthParams.count) + throw new Error('Arguments array must contain precisely ' + lengthParams.count + ' item(s).'); + + if(lengthParams.validateMin && argsArray.length < lengthParams.min) + throw new Error('Arguments array must contain at least ' + lengthParams.min + ' item(s).'); + + if(lengthParams.validateMax && argsArray.length > lengthParams.max) + throw new Error('Arguments array must contain no more than ' + lengthParams.max + ' item(s).'); + } + + function validate(argsArray, min, max) + { + validateType(argsArray); + var lengthParams = getLengthParams(min, max); + validateLength(argsArray, lengthParams); + + return true; + } + + function selfValidate(argsArray, min, max) + { + try + { + return validate(argsArray, min, max); + } + catch(e) { throw new Error('The call to \'validateArgumentsArray\' raised an error: ' + e.message); } + } + + return { + validate: validate, + selfValidate: selfValidate, + }; +}(); + +function validateArgumentsArray(argsArray) +{ + 'use strict'; + + validator.selfValidate(argsArray, 1, 3); + var arrayToValidate = argsArray[0], min = argsArray[1], max = argsArray[2]; + return validator.validate(arrayToValidate, min, max); +} \ No newline at end of file diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs index 92213691..b4cd1a7b 100644 --- a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs +++ b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs @@ -33,10 +33,22 @@ namespace CSF.Screenplay.Selenium.ScriptResources /// public class GetALocalisedDate : ScriptResource { - /// - /// Gets the name of this script. - /// - /// The name. - public override string Name => "get a localised date string"; + readonly IProvidesScript argsValidator; + + /// + /// Gets the name of this script. + /// + /// The name. + public override string Name => "a service to get a formatted date using the current browser's locale"; + + public override string GetScript() + => String.Concat(argsValidator.GetScript(), Environment.NewLine, base.GetScript()); + + public GetALocalisedDate() : this(null) {} + + public GetALocalisedDate(IProvidesScript argsValidator) + { + this.argsValidator = argsValidator ?? new ArgumentsArrayValidator(); + } } } diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js index 8b370cb8..9456b68c 100644 --- a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js +++ b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.js @@ -1,13 +1,15 @@ function executeScript(argsArray) { 'use strict'; - if(!argsArray) throw new Error('Arguments must be a non-null array.'); - if(!(argsArray instanceof Array)) throw new Error('Arguments must be an array.'); - if(argsArray.length != 3) throw new Error('Arguments must contain precisely three elements (Y/M/D).'); + argumentsArrayValidator.validate(argsArray, 3); - var year = argsArray[0], month = argsArray[1], day = argsArray[2], theDate; + var + year = argsArray[0], + month = argsArray[1], + day = argsArray[2], + theDate; - if(isNaN(year) || isNaN(month) || isNaN(day)) + if(typeof year !== 'number' || typeof month !== 'number' || typeof day !== 'number') throw new Error('The supplied year, month and day must all be numbers.'); theDate = new Date(year, month, day); diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs index c11d5e6d..f5d8f493 100644 --- a/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs +++ b/CSF.Screenplay.Selenium/ScriptResources/GetDocumentReadyState.cs @@ -33,10 +33,10 @@ namespace CSF.Screenplay.Selenium.ScriptResources /// public class GetDocumentReadyState : ScriptResource { - /// - /// Gets the name of this script. - /// - /// The name. - public override string Name => "get the ready-state for the web page"; + /// + /// Gets the name of this script. + /// + /// The name. + public override string Name => "a service which gets the current web page's ready-state"; } } diff --git a/CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.cs b/CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.cs new file mode 100644 index 00000000..e0fdd00a --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.cs @@ -0,0 +1,59 @@ +// +// ArgumentsArrayConverter.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.ScriptResources +{ + public class ScriptInvoker : ScriptResource, IInvokesScripts + { + readonly string entryPointName; + + public override string Name => "invoker for named entry-points"; + + public override string GetEntryPointName() => null; + + public override string GetScript() => GetScript(entryPointName); + + string IInvokesScripts.GetScript(string entryPoint) => GetScript(entryPoint); + + string GetScript(string entryPoint) + { + var invocationScript = GetInvocationScript(entryPoint); + return String.Concat(base.GetScript(), Environment.NewLine, invocationScript); + } + + string GetInvocationScript(string entryPoint) + => $"return invoker.invoke({entryPoint}, arguments);"; + + public ScriptInvoker() : this(null) {} + + public ScriptInvoker(string entryPointName) + { + this.entryPointName = entryPointName ?? DefaultEntryPointName; + } + } +} diff --git a/CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.js b/CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.js new file mode 100644 index 00000000..689a2f9b --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/ScriptInvoker.js @@ -0,0 +1,24 @@ +var invoker = function() +{ + 'use strict'; + + function validateEntryPoint(entryPoint) + { + if(!entryPoint || typeof entryPoint !== 'function') + throw new Error('The script entry-point must be a function'); + } + + function getArgumentsObjectAsArray(argumentsObject) + { + return Array.prototype.slice.call(argumentsObject); + } + + function invoke(entryPoint, argumentsObject) + { + validateEntryPoint(entryPoint); + var args = getArgumentsObjectAsArray(argumentsObject); + return entryPoint(args); + } + + return { invoke: invoke }; +}(); diff --git a/CSF.Screenplay.Selenium/StoredScripts/IInvokesScripts.cs b/CSF.Screenplay.Selenium/StoredScripts/IInvokesScripts.cs new file mode 100644 index 00000000..e947010f --- /dev/null +++ b/CSF.Screenplay.Selenium/StoredScripts/IInvokesScripts.cs @@ -0,0 +1,33 @@ +// +// IInvokesScripts.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace CSF.Screenplay.Selenium.StoredScripts +{ + public interface IInvokesScripts + { + string GetScript(string entryPoint); + } +} diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs index 4418bcbb..555075ae 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs @@ -34,28 +34,28 @@ namespace CSF.Screenplay.Selenium.StoredScripts /// public abstract class ScriptResource : IProvidesScript { - const string + internal const string DefaultEntryPointName = "executeScript"; - /// - /// Gets the name of this script. - /// - /// The name. + /// + /// Gets the name of this script. + /// + /// The name. public virtual string Name => GetType().Name; - /// + /// /// Gets the name of the entry point to the script - this is the function exposed by - /// . - /// - /// The name of the entry point function. + /// . + /// + /// The name of the entry point function. public virtual string GetEntryPointName() => DefaultEntryPointName; - /// - /// Gets the script fragment as a named function. The name of that function is exposed via - /// . - /// - /// The script. - public string GetScript() + /// + /// Gets the script fragment as a named function. The name of that function is exposed via + /// . + /// + /// The script. + public virtual string GetScript() { var thisType = GetType(); var scriptAssembly = thisType.Assembly; diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs index eced4463..dd41f91d 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptRunner.cs @@ -1,89 +1,97 @@ -// -// ScriptRunner.cs -// -// Author: -// Craig Fowler -// -// Copyright (c) 2018 Craig Fowler -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using OpenQA.Selenium; - -namespace CSF.Screenplay.Selenium.StoredScripts -{ - /// - /// Default implementation of - /// - public class ScriptRunner : IRunsScripts - { - /// - /// Executes the script and returns the result. - /// - /// The script result. - /// A JavaScript. - /// A web driver. - /// The script arguments. - public object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments) - { - if(script == null) - throw new ArgumentNullException(nameof(script)); - if(webDriver == null) - throw new ArgumentNullException(nameof(webDriver)); - - var javaScriptRunner = GetJavaScriptExecutor(webDriver); - return javaScriptRunner.ExecuteScript(script, arguments); - } - - /// - /// Executes the script exposed by the given script provider and returns the result. - /// - /// The script result. - /// A JavaScript provider. - /// A web driver. - /// The script arguments. - public object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments) - { - if(script == null) - throw new ArgumentNullException(nameof(script)); - if(webDriver == null) - throw new ArgumentNullException(nameof(webDriver)); - - var runnableScript = GetRunnableScript(script); - return ExecuteScript(runnableScript, webDriver, arguments); - } - - string GetRunnableScript(IProvidesScript script) - => String.Concat(script.GetScript(), - Environment.NewLine, - $"var argsArray = Array.prototype.slice.call(arguments);", - Environment.NewLine, - $"return {script.GetEntryPointName()}(argsArray);"); - - IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver) - { - var jsDriver = driver as IJavaScriptExecutor; - - if(jsDriver == null) - throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver)); - - return jsDriver; - } - } -} +// +// ScriptRunner.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.ScriptResources; +using OpenQA.Selenium; + +namespace CSF.Screenplay.Selenium.StoredScripts +{ + /// + /// Default implementation of + /// + public class ScriptRunner : IRunsScripts + { + readonly IInvokesScripts invoker; + + /// + /// Executes the script and returns the result. + /// + /// The script result. + /// A JavaScript. + /// A web driver. + /// The script arguments. + public object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + if(webDriver == null) + throw new ArgumentNullException(nameof(webDriver)); + + var javaScriptRunner = GetJavaScriptExecutor(webDriver); + return javaScriptRunner.ExecuteScript(script, arguments); + } + + /// + /// Executes the script exposed by the given script provider and returns the result. + /// + /// The script result. + /// A JavaScript provider. + /// A web driver. + /// The script arguments. + public object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments) + { + if(script == null) + throw new ArgumentNullException(nameof(script)); + if(webDriver == null) + throw new ArgumentNullException(nameof(webDriver)); + + var runnableScript = GetRunnableScript(script); + return ExecuteScript(runnableScript, webDriver, arguments); + } + + string GetRunnableScript(IProvidesScript script) + { + return String.Concat(script.GetScript(), Environment.NewLine, invoker.GetScript(script.GetEntryPointName())); + } + + IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver) + { + var jsDriver = driver as IJavaScriptExecutor; + + if(jsDriver == null) + throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver)); + + return jsDriver; + } + + public ScriptRunner() : this(null) {} + + public ScriptRunner(IInvokesScripts invoker) + { + this.invoker = invoker ?? new ScriptInvoker(); + } + } +} diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index 78b1c219..4ff999d4 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -160,6 +160,7 @@ + diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/ArgumentsArrayValidator.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/ArgumentsArrayValidator.tests.js new file mode 100644 index 00000000..af887d53 --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/ArgumentsArrayValidator.tests.js @@ -0,0 +1,56 @@ +describe('The ArgumentsArrayValidator object', function() { + + describe('should raise errors when', function() { + it('the array is not provided', function() { + expect(function() { + argumentsArrayValidator.validate(); + }).toThrowError(Error, /non-null/); + }); + + it('the array is null', function() { + expect(function() { + argumentsArrayValidator.validate(null); + }).toThrowError(Error, /non-null/); + }); + + it('the array is not an array', function() { + expect(function() { + argumentsArrayValidator.validate("Not an array"); + }).toThrowError(Error, /must be an array/); + }); + + it('the array does not have the correct count of elements', function() { + expect(function() { + argumentsArrayValidator.validate([1, 2], 5); + }).toThrowError(Error, /must contain precisely 5/); + }); + + it('the array has too few elements', function() { + expect(function() { + argumentsArrayValidator.validate([1, 2], 4, null); + }).toThrowError(Error, /must contain at least 4/); + }); + + it('the array has too many elements', function() { + expect(function() { + argumentsArrayValidator.validate([1, 2, 3, 4], null, 2); + }).toThrowError(Error, /must contain no more than 2/); + }); + }); + + it('should return true when the array has the correct count of elements', function() { + expect(argumentsArrayValidator.validate([1, 2], 2)) + .toEqual(true); + }); + + it('should return true when the array has at least the minimum number of elements', function() { + expect(argumentsArrayValidator.validate([1, 2, 3], 2, null)) + .toEqual(true); + }); + + it('should return true when the array has no more than the maximum number of elements', function() { + expect(argumentsArrayValidator.validate([1, 2], null, 4)) + .toEqual(true); + }); + +}); \ No newline at end of file diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js index 82a3ca46..8fb01d70 100644 --- a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetALocalisedDate.tests.js @@ -1,40 +1,18 @@ -describe('The script which gets a localised date', function() { - describe('should raise errors if the input', function() { - it('is not provided', function() { - expect(function() { - executeScript(); - }).toThrowError(Error, /non-null/); - }); +describe('The GetALocalisedDate service', function() { - it('is null', function() { - expect(function() { - executeScript(null); - }).toThrowError(Error, /non-null/); - }); - - it('is not an array', function() { - expect(function() { - executeScript("Not an array"); - }).toThrowError(Error, /must be an array/); - }); - - it('has only two elements', function() { - expect(function() { - executeScript([1, 2]); - }).toThrowError(Error, /must contain precisely three elements/); - }); - - it('has four elements', function() { - expect(function() { - executeScript([1, 2, 3, 4]); - }).toThrowError(Error, /must contain precisely three elements/); - }); + it('should use the arguments-array validator', function() { + spyOn(argumentsArrayValidator, 'validate') + .and + .returnValue(true); + + executeScript([1, 2, 3]); + expect(argumentsArrayValidator.validate).toHaveBeenCalledWith([1, 2, 3], 3); + }); - it('contains elements which are not numbers', function() { - expect(function() { - executeScript([1, 'not a number', 3]); - }).toThrowError(Error, /must all be numbers/); - }); + it('should throw an error when the argument array contains elements which are not numbers', function() { + expect(function() { + executeScript([1, 'not a number', 3]); + }).toThrowError(Error, /must all be numbers/); }); it('should return a string which matches the locale-formatted date', function() { @@ -43,4 +21,5 @@ expect(actualResult).toBe(expectedResult); }); + }); \ No newline at end of file diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js index 8ad9a97a..dc175da8 100644 --- a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/GetDocumentReadyState.tests.js @@ -1,4 +1,4 @@ -describe('The script which gets the document ready-state', function() { +describe('The GetDocumentReadyState service', function() { it('should return a string', function() { var result = executeScript(); expect(typeof result).toBe('string'); From 3449205611a7cbdc89011530e62431384bc8a296 Mon Sep 17 00:00:00 2001 From: Craig Fowler Date: Thu, 8 Mar 2018 22:37:36 +0000 Subject: [PATCH 093/213] Provisionally resolve #36 - Migrate the last script to the new architecture --- .../CSF.Screenplay.Selenium.csproj | 11 +-- .../Resources/Javascripts.Designer.cs | 56 ------------- .../Resources/Javascripts.resx | 32 -------- .../ScriptResources/GetALocalisedDate.cs | 3 +- .../ScriptResources/SetAnElementValue.cs | 46 +++++++++++ .../ScriptResources/SetAnElementValue.js | 36 +++++++++ .../StoredScripts/ScriptResource.cs | 17 ++++ .../Tasks/EnterADateBySettingTheValue.cs | 30 ++++--- .../Waits/WaitUntilThePageLoads.cs | 1 - .../CSF.Screenplay.WebTestWebsite.csproj | 1 + .../script-tests/SetAnElementValue.tests.js | 80 +++++++++++++++++++ .../Views/StoredScriptTest/Index.pt | 2 +- 12 files changed, 201 insertions(+), 114 deletions(-) delete mode 100644 CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs delete mode 100644 CSF.Screenplay.Selenium/Resources/Javascripts.resx create mode 100644 CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.cs create mode 100644 CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.js create mode 100644 CSF.Screenplay.WebTestWebsite/Scripts/script-tests/SetAnElementValue.tests.js diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj index 035d64a1..418e17d1 100644 --- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj +++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj @@ -160,9 +160,6 @@ - - Javascripts.resx - @@ -199,6 +196,7 @@ + @@ -215,7 +213,6 @@ - @@ -223,15 +220,11 @@ - - ResXFileCodeGenerator - Javascripts.resources - Javascripts.Designer.cs - + diff --git a/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs b/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs deleted file mode 100644 index 28005134..00000000 --- a/CSF.Screenplay.Selenium/Resources/Javascripts.Designer.cs +++ /dev/null @@ -1,56 +0,0 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Mono Runtime Version: 4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ - -namespace CSF.Screenplay.Selenium.Resources { - using System; - using System.Reflection; - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Javascripts { - - private static System.Resources.ResourceManager resourceMan; - - private static System.Globalization.CultureInfo resourceCulture; - - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Javascripts() { - } - - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Resources.ResourceManager ResourceManager { - get { - if (object.Equals(null, resourceMan)) { - System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Javascripts", typeof(Javascripts).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - internal static string SetValueById { - get { - return ResourceManager.GetString("SetValueById", resourceCulture); - } - } - } -} diff --git a/CSF.Screenplay.Selenium/Resources/Javascripts.resx b/CSF.Screenplay.Selenium/Resources/Javascripts.resx deleted file mode 100644 index 6cefb85a..00000000 --- a/CSF.Screenplay.Selenium/Resources/Javascripts.resx +++ /dev/null @@ -1,32 +0,0 @@ - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - return (function(window, argsArray) { - var - date = argsArray[1], - id = argsArray[0], - element = window.document.getElementById(id); - if(!element) return false; - - element.setAttribute('value', date); - - var ev = window.document.createEvent('Event'); - ev.initEvent('change', true, true); - element.dispatchEvent(ev); - - return true; -}(window, arguments)); - - diff --git a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs index b4cd1a7b..a1d562fa 100644 --- a/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs +++ b/CSF.Screenplay.Selenium/ScriptResources/GetALocalisedDate.cs @@ -41,8 +41,7 @@ public class GetALocalisedDate : ScriptResource /// The name. public override string Name => "a service to get a formatted date using the current browser's locale"; - public override string GetScript() - => String.Concat(argsValidator.GetScript(), Environment.NewLine, base.GetScript()); + public override string GetScript() => CombineScripts(base.GetScript(), argsValidator); public GetALocalisedDate() : this(null) {} diff --git a/CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.cs b/CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.cs new file mode 100644 index 00000000..ca36a1fd --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.cs @@ -0,0 +1,46 @@ +// +// SetAnElementValue.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using CSF.Screenplay.Selenium.StoredScripts; + +namespace CSF.Screenplay.Selenium.ScriptResources +{ + public class SetAnElementValue : ScriptResource + { + readonly IProvidesScript argsValidator; + + public override string Name => "a service which sets the value of an HTML element"; + + public override string GetScript() => CombineScripts(base.GetScript(), argsValidator); + + public SetAnElementValue() : this(null) {} + + public SetAnElementValue(IProvidesScript argsValidator) + { + this.argsValidator = argsValidator ?? new ArgumentsArrayValidator(); + } + } +} diff --git a/CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.js b/CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.js new file mode 100644 index 00000000..d93f5b4f --- /dev/null +++ b/CSF.Screenplay.Selenium/ScriptResources/SetAnElementValue.js @@ -0,0 +1,36 @@ +function executeScript(argsArray) +{ + 'use strict'; + + argumentsArrayValidator.validate(argsArray, 2); + + var htmlElement = argsArray[0], newValue = argsArray[1]; + + function validateElement(element) + { + if(element === null || element === undefined) + throw new Error('You must provide an HTML element object.'); + if(!(element instanceof HTMLElement)) + throw new Error('The element must be an HTML element.'); + if(element.value === undefined) + throw new Error('The element must have a \'value\' property.'); + } + + function setValue(element, val) + { + element.value = val; + } + + function triggerChangeEvent(element) + { + var ev = document.createEvent('Event'); + ev.initEvent('change', true, true); + element.dispatchEvent(ev); + } + + validateElement(htmlElement); + setValue(htmlElement, newValue); + triggerChangeEvent(htmlElement); + + return true; +} diff --git a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs index 555075ae..1ace3c62 100644 --- a/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs +++ b/CSF.Screenplay.Selenium/StoredScripts/ScriptResource.cs @@ -24,6 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; +using System.Linq; using System.Reflection; using CSF.Reflection; @@ -62,5 +63,21 @@ public virtual string GetScript() return scriptAssembly.GetManifestResourceText(thisType, $"{thisType.Name}.js"); } + + protected string CombineScripts(string entryPointProvider, params IProvidesScript[] scripts) + { + if(entryPointProvider == null) + throw new ArgumentNullException(nameof(entryPointProvider)); + if(scripts == null) + throw new ArgumentNullException(nameof(scripts)); + if(scripts.Length == 0) + throw new ArgumentException("You must provide at least one script.", nameof(scripts)); + + var scriptsToCombine = scripts.Select(x => x.GetScript()) + .Union(new [] { entryPointProvider }) + .ToArray(); + + return String.Join(Environment.NewLine, scriptsToCombine); + } } } diff --git a/CSF.Screenplay.Selenium/Tasks/EnterADateBySettingTheValue.cs b/CSF.Screenplay.Selenium/Tasks/EnterADateBySettingTheValue.cs index 24eb0e21..c7680e8c 100644 --- a/CSF.Screenplay.Selenium/Tasks/EnterADateBySettingTheValue.cs +++ b/CSF.Screenplay.Selenium/Tasks/EnterADateBySettingTheValue.cs @@ -1,8 +1,10 @@ using System; using CSF.Screenplay.Actors; using CSF.Screenplay.Performables; +using CSF.Screenplay.Selenium.Abilities; using CSF.Screenplay.Selenium.Builders; using CSF.Screenplay.Selenium.Models; +using CSF.Screenplay.Selenium.ScriptResources; namespace CSF.Screenplay.Selenium.Tasks { @@ -13,9 +15,7 @@ namespace CSF.Screenplay.Selenium.Tasks public class EnterADateBySettingTheValue : Performable { readonly DateTime date; - readonly ElementId target; - - ITarget Target => target; + readonly ITarget target; /// /// Gets the report of the current instance, for the given actor. @@ -23,19 +23,23 @@ public class EnterADateBySettingTheValue : Performable /// The human-readable report text. /// An actor for whom to write the report. protected override string GetReport(INamed actor) - => $"{actor.Name} enters the date {date.ToString("yyyy-MM-dd")} into {Target.GetName()} by setting the value directly via JavaScript"; + => $"{actor.Name} enters the date {date.ToString("yyyy-MM-dd")} into {target.GetName()} by setting the value directly via JavaScript"; - /// - /// Performs this operation, as the given actor. - /// - /// The actor performing this task. + /// + /// Performs this operation, as the given actor. + /// + /// The actor performing this task. protected override void PerformAs(IPerformer actor) { - var result = (bool) actor.Perform(Execute.TheJavaScript(Resources.Javascripts.SetValueById) - .WithTheParameters(target.IdentifierValue, date.ToString("yyyy-MM-dd")) + var browseTheWeb = actor.GetAbility(); + var webElement = target.GetWebElementAdapter(browseTheWeb); + + if(webElement == null) + throw new TargetNotFoundException($"{target.GetName()} was not found"); + + var result = (bool) actor.Perform(Execute.TheJavaScript() + .WithTheParameters(webElement, date.ToString("yyyy-MM-dd")) .AndGetTheResult()); - if(!result) - throw new TargetNotFoundException($"No element with the id '{target.IdentifierValue}' could be found by JavaScript"); } /// @@ -43,7 +47,7 @@ protected override void PerformAs(IPerformer actor) /// /// Date. /// Target. - public EnterADateBySettingTheValue(DateTime date, ElementId target) + public EnterADateBySettingTheValue(DateTime date, ITarget target) { if(target == null) throw new ArgumentNullException(nameof(target)); diff --git a/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs b/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs index 66b6f752..87c7757b 100644 --- a/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs +++ b/CSF.Screenplay.Selenium/Waits/WaitUntilThePageLoads.cs @@ -5,7 +5,6 @@ using CSF.Screenplay.Selenium.Actions; using CSF.Screenplay.Selenium.Builders; using CSF.Screenplay.Selenium.Models; -using CSF.Screenplay.Selenium.Resources; using CSF.Screenplay.Selenium.ScriptResources; using CSF.Screenplay.Stopwatch; using OpenQA.Selenium; diff --git a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj index 4ff999d4..302bf92d 100644 --- a/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj +++ b/CSF.Screenplay.WebTestWebsite/CSF.Screenplay.WebTestWebsite.csproj @@ -161,6 +161,7 @@ + diff --git a/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/SetAnElementValue.tests.js b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/SetAnElementValue.tests.js new file mode 100644 index 00000000..ba4bbb1a --- /dev/null +++ b/CSF.Screenplay.WebTestWebsite/Scripts/script-tests/SetAnElementValue.tests.js @@ -0,0 +1,80 @@ +describe('The SetAnElementValue service', function() { + + var scratchArea; + + function clearNodes(element) + { + while(element.firstChild) + element.removeChild(element.firstChild); + } + + function addScratchElement(name) + { + var element = document.createElement(name); + scratchArea.appendChild(element); + return element; + } + + beforeEach(function() { + scratchArea = document.getElementById('test_scratch_area'); + }); + + afterEach(function() { + clearNodes(scratchArea); + }); + + it('should use the arguments-array validator', function() { + spyOn(argumentsArrayValidator, 'validate') + .and + .returnValue(true); + var element = addScratchElement('input'); + + executeScript([element, 3]); + expect(argumentsArrayValidator.validate).toHaveBeenCalledWith([element, 3], 2); + }); + + it('should throw an error when the element is null', function() { + expect(function() { + executeScript([null, 'value']); + }).toThrowError(Error, /must provide an HTML element/); + }); + + it('should throw an error when used with an object which is not an HTMLElement', function() { + expect(function() { + executeScript([{ not: 'an', html: 'element' }, 'value']); + }).toThrowError(Error, /must be an HTML element/); + }); + + it('should throw an error when used with an HTML element that does not have a value', function() { + var element = addScratchElement('div'); + expect(function() { + executeScript([element, 'value']); + }).toThrowError(Error, /must have a 'value' property/); + }); + + it('should be able to set the value of an HTML element', function() { + var element = addScratchElement('input'); + + executeScript([element, 'newVal']); + + expect(element.value).toEqual('newVal'); + }); + + it('should be able to set the value of an HTML