diff --git a/README.md b/README.md index ebb0b2d..b1fc934 100644 --- a/README.md +++ b/README.md @@ -24,47 +24,7 @@ Available as a Dart package https://pub.dartlang.org/packages/flutter_gherkin ## Table of Contents - - -- [flutter_gherkin](#fluttergherkin) - - [Table of Contents](#table-of-contents) - - [Getting Started](#getting-started) - - [Configuration](#configuration) - - [features](#features) - - [tagExpression](#tagexpression) - - [order](#order) - - [stepDefinitions](#stepdefinitions) - - [customStepParameterDefinitions](#customstepparameterdefinitions) - - [hooks](#hooks) - - [reporters](#reporters) - - [createWorld](#createworld) - - [exitAfterTestRun](#exitaftertestrun) - - [Flutter specific configuration options](#flutter-specific-configuration-options) - - [restartAppBetweenScenarios](#restartappbetweenscenarios) - - [targetAppPath](#targetapppath) - - [Features Files](#features-files) - - [Steps Definitions](#steps-definitions) - - [Given](#given) - - [Then](#then) - - [Step Timeout](#step-timeout) - - [Multiline Strings](#multiline-strings) - - [Data tables](#data-tables) - - [Well known step parameters](#well-known-step-parameters) - - [Pluralisation](#pluralisation) - - [Custom Parameters](#custom-parameters) - - [World Context (per test scenario shared state)](#world-context-per-test-scenario-shared-state) - - [Assertions](#assertions) - - [Tags](#tags) - - [Hooks](#hooks) - - [Reporting](#reporting) - - [Flutter](#flutter) - - [Restarting the app before each test](#restarting-the-app-before-each-test) - - [Flutter World](#flutter-world) - - [Pre-defined Steps](#pre-defined-steps) - - [Flutter Driver Utilities](#flutter-driver-utilities) - - [Debugging](#debugging) - - +autoauto- [flutter_gherkin](#flutter_gherkin)auto - [Table of Contents](#table-of-contents)auto - [Getting Started](#getting-started)auto - [Configuration](#configuration)auto - [features](#features)auto - [tagExpression](#tagexpression)auto - [order](#order)auto - [stepDefinitions](#stepdefinitions)auto - [customStepParameterDefinitions](#customstepparameterdefinitions)auto - [hooks](#hooks)auto - [reporters](#reporters)auto - [createWorld](#createworld)auto - [exitAfterTestRun](#exitaftertestrun)auto - [Flutter specific configuration options](#flutter-specific-configuration-options)auto - [restartAppBetweenScenarios](#restartappbetweenscenarios)auto - [targetAppPath](#targetapppath)auto - [Features Files](#features-files)auto - [Steps Definitions](#steps-definitions)auto - [Given](#given)auto - [Then](#then)auto - [Step Timeout](#step-timeout)auto - [Multiline Strings](#multiline-strings)auto - [Data tables](#data-tables)auto - [Well known step parameters](#well-known-step-parameters)auto - [Pluralisation](#pluralisation)auto - [Custom Parameters](#custom-parameters)auto - [World Context (per test scenario shared state)](#world-context-per-test-scenario-shared-state)auto - [Assertions](#assertions)auto - [Tags](#tags)auto - [Hooks](#hooks)auto - [Reporting](#reporting)auto - [Flutter](#flutter)auto - [Restarting the app before each test](#restarting-the-app-before-each-test)auto - [Flutter World](#flutter-world)auto - [Pre-defined Steps](#pre-defined-steps)auto - [Flutter Driver Utilities](#flutter-driver-utilities)auto - [Debugging](#debugging)autoauto ## Getting Started @@ -635,6 +595,13 @@ class HookExample extends Hook { print("running hook before scenario '$scenario'"); } + @override + /// Run after the scenario world is created but run before a scenario and its steps are executed + /// Might not be invoked if there is not a world object + Future onAfterScenarioWorldCreated(World world, String scenario) { + print("running hook after world scenario created'$scenario'"); + } + @override /// Run after a scenario has executed Future onAfterScenario( diff --git a/lib/src/feature_file_runner.dart b/lib/src/feature_file_runner.dart index 86f8c35..bec8f2d 100644 --- a/lib/src/feature_file_runner.dart +++ b/lib/src/feature_file_runner.dart @@ -76,13 +76,14 @@ class FeatureFileRunner { ScenarioRunnable scenario, BackgroundRunnable background) async { World world; bool scenarioPassed = true; + await _hook.onBeforeScenario(_config, scenario.name); + if (_config.createWorld != null) { await _log("Creating new world for scenerio '${scenario.name}'", scenario.debug, MessageLevel.debug); world = await _config.createWorld(_config); + await _hook.onAfterScenarioWorldCreated(world, scenario.name); } - await _hook.onAfterScenarioWorldCreated(world, scenario.name); - await _hook.onBeforeScenario(_config, scenario.name); _reporter.onScenarioStarted( StartedMessage(Target.scenario, scenario.name, scenario.debug)); @@ -114,7 +115,6 @@ class FeatureFileRunner { } } -// hookWorld?.dispose(); world?.dispose(); await _reporter.onScenarioFinished( @@ -218,7 +218,7 @@ class FeatureFileRunner { if (step.multilineStrings.length > 0) { parameters = parameters.toList()..addAll(step.multilineStrings); } - + if (step.table != null) { parameters = parameters.toList()..add(step.table); } diff --git a/lib/src/hooks/hook.dart b/lib/src/hooks/hook.dart index cd5d4cb..2d94d06 100644 --- a/lib/src/hooks/hook.dart +++ b/lib/src/hooks/hook.dart @@ -13,7 +13,8 @@ abstract class Hook { /// Run after all scenarios in a test run have completed Future onAfterRun(TestConfiguration config) => Future.value(null); - /// Run before a scenario and it steps are executed + /// Run after the scenario world is created but run before a scenario and its steps are executed + /// Might not be invoked if there is not a world object Future onAfterScenarioWorldCreated(World world, String scenario) => Future.value(null); diff --git a/test/feature_file_runner_test.dart b/test/feature_file_runner_test.dart index 446448c..e520944 100644 --- a/test/feature_file_runner_test.dart +++ b/test/feature_file_runner_test.dart @@ -165,6 +165,38 @@ void main() { }); }); + group("step parameters", () { + test("table parameters are given to the step", () async { + bool tableParameterProvided = false; + final stepDefiniton = + MockStepDefinition((Iterable parameters) async { + tableParameterProvided = parameters.first is Table; + }, 1); + final executableStep = new ExectuableStep( + MockGherkinExpression((_) => true), stepDefiniton); + final runner = new FeatureFileRunner( + TestConfiguration(), + MockTagExpressionEvaluator(), + [executableStep], + ReporterMock(), + HookMock()); + + final step = new StepRunnable( + "Step 1", RunnableDebugInformation("", 0, "Given I do a")); + step.table = new Table(null, null); + final scenario = new ScenarioRunnable("Scenario: 1", emptyDebuggable) + ..steps.add(step); + final feature = new FeatureRunnable("1", emptyDebuggable) + ..scenarios.add(scenario); + final featureFile = new FeatureFile(emptyDebuggable) + ..features.add(feature); + await runner.run(featureFile); + expect(stepDefiniton.hasRun, true); + expect(stepDefiniton.runCount, 1); + expect(tableParameterProvided, true); + }); + }); + group("hooks", () { test("hook is called when starting and finishing scenarios", () async { final hookMock = HookMock(); diff --git a/test/hooks/aggregated_hook_test.dart b/test/hooks/aggregated_hook_test.dart index 26c4904..fdd6c93 100644 --- a/test/hooks/aggregated_hook_test.dart +++ b/test/hooks/aggregated_hook_test.dart @@ -33,6 +33,11 @@ void main() { expect(hookTwo.onBeforeScenarioInvocationCount, 1); expect(hookThree.onBeforeScenarioInvocationCount, 1); expect(hookFour.onBeforeScenarioInvocationCount, 1); + await aggregatedHook.onAfterScenarioWorldCreated(null, null); + expect(hookOne.onAfterScenarioWorldCreatedInvocationCount, 1); + expect(hookTwo.onAfterScenarioWorldCreatedInvocationCount, 1); + expect(hookThree.onAfterScenarioWorldCreatedInvocationCount, 1); + expect(hookFour.onAfterScenarioWorldCreatedInvocationCount, 1); await aggregatedHook.onAfterScenario(null, null); expect(hookOne.onAfterScenarioInvocationCount, 1); expect(hookTwo.onAfterScenarioInvocationCount, 1); diff --git a/test/mocks/hook_mock.dart b/test/mocks/hook_mock.dart index 3fafa95..ed3a2f5 100644 --- a/test/mocks/hook_mock.dart +++ b/test/mocks/hook_mock.dart @@ -7,6 +7,7 @@ class HookMock extends Hook { int onAfterRunInvocationCount = 0; int onBeforeScenarioInvocationCount = 0; int onAfterScenarioInvocationCount = 0; + int onAfterScenarioWorldCreatedInvocationCount = 0; final int providedPriority; final OnBeforeRunCode onBeforeRunCode; @@ -33,4 +34,8 @@ class HookMock extends Hook { Future onAfterScenario( TestConfiguration config, String scenario) async => onAfterScenarioInvocationCount += 1; + + Future onAfterScenarioWorldCreated( + World world, String scenario) async => + onAfterScenarioWorldCreatedInvocationCount += 1; } diff --git a/test/mocks/step_definition_mock.dart b/test/mocks/step_definition_mock.dart index 088d106..58f2e36 100644 --- a/test/mocks/step_definition_mock.dart +++ b/test/mocks/step_definition_mock.dart @@ -8,7 +8,7 @@ class MockStepDefinition extends StepDefinitionBase { int runCount = 0; final OnRunCode code; - MockStepDefinition([this.code]) : super(null, 0); + MockStepDefinition([this.code, int expectedParameterCount = 0]) : super(null, expectedParameterCount); @override Future onRun(Iterable parameters) async {