- Fix #257 - fixed issue when generating a step with a '$' sign in
- Fix #256 - Ensure all exceptions generated when running a step are logged - Fix #253 - Ensure features with descriptions that span more than one line are parsed correctly - Fix #252 - Ensure all async code is awaited - When taking a screenshot on the web use the render element rather than relying on native code that does not work
This commit is contained in:
parent
4378a2447d
commit
eff82509c7
|
@ -1,3 +1,10 @@
|
|||
## [3.0.0-rc.17] - 25/07/2022
|
||||
- Fix #257 - fixed issue when generating a step with a '$' sign in
|
||||
- Fix #256 - Ensure all exceptions generated when running a step are logged
|
||||
- Fix #253 - Ensure features with descriptions that span more than one line are parsed correctly
|
||||
- Fix #252 - Ensure all async code is awaited
|
||||
- When taking a screenshot on the web use the render element rather than relying on native code that does not work
|
||||
|
||||
## [3.0.0-rc.16] - 01/07/2022
|
||||
- Fix #231 - using local coordinate system when taking a screenshot on Android (thanks to @youssef-t for the solution)
|
||||
- Fix #216 - ensure step exceptions and `expect` failure results are added as errors to the json report
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
@debug
|
||||
Feature: Expect failure
|
||||
Feature: Expect failures
|
||||
Ensure that when a test fails the exception or test failure is reported
|
||||
|
||||
@failure-expected
|
||||
Scenario: Exception should be added to json report
|
||||
Given I expect the todo list
|
||||
| Todo |
|
||||
| Buy blueberries |
|
||||
When I tap the "add" button
|
||||
And I fill the "todo" field with "Buy hannah's apples"
|
||||
When I tap the "button is not here but exception should be logged in report" button
|
||||
|
||||
@failure-expected
|
||||
Scenario: Failed expect() should be added to json report
|
||||
Description for this scenario!
|
||||
When I tap the "add" button
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
@debug
|
||||
Feature: Parsing
|
||||
Complex description:
|
||||
- Line "one".
|
||||
- Line two, more text
|
||||
- Line three
|
||||
|
||||
Scenario: Parsing a
|
||||
Given the text "^[A-Z]{3}\\d{5}\$"
|
|
@ -1,7 +1,6 @@
|
|||
@tag
|
||||
Feature: Swiping
|
||||
|
||||
@debug
|
||||
Scenario: User can swipe cards left and right
|
||||
Given I swipe right by 250 pixels on the "scrollable cards"`
|
||||
Then I expect the text "Page 2" to be present
|
||||
|
|
|
@ -8,18 +8,20 @@ import 'package:gherkin/gherkin.dart';
|
|||
import 'hooks/reset_app_hook.dart';
|
||||
import 'steps/expect_failure.dart';
|
||||
import 'steps/expect_todos_step.dart';
|
||||
import 'steps/given_text.dart';
|
||||
import 'steps/multiline_string_with_formatted_json.dart';
|
||||
import 'steps/when_await_animation.dart';
|
||||
import 'steps/when_step_has_timeout.dart';
|
||||
import 'world/custom_world.dart';
|
||||
|
||||
FlutterTestConfiguration gherkinTestConfiguration = FlutterTestConfiguration(
|
||||
// tagExpression: '@debug', // can be used to limit the tests that are run
|
||||
tagExpression: '@debug2', // can be used to limit the tests that are run
|
||||
stepDefinitions: [
|
||||
thenIExpectTheTodos,
|
||||
whenAnAnimationIsAwaited,
|
||||
whenStepHasTimeout,
|
||||
givenTheData,
|
||||
givenTheText,
|
||||
thenIExpectFailure,
|
||||
],
|
||||
hooks: [
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,4 +2,4 @@ call npm init -y
|
|||
|
||||
call npm install --save-dev cucumber-html-reporter
|
||||
|
||||
node -e "require('cucumber-html-reporter').generate({theme: 'bootstrap', jsonFile: 'REPORT_NAME.json', output: 'report.html', reportSuiteAsScenarios: true, launchReport: false});"
|
||||
node -e "require('cucumber-html-reporter').generate({theme: 'bootstrap', jsonFile: '{REPORT_NAME}.json', output: 'report.html', reportSuiteAsScenarios: true, launchReport: false});"
|
|
@ -0,0 +1,9 @@
|
|||
import 'package:flutter_gherkin/flutter_gherkin.dart';
|
||||
import 'package:gherkin/gherkin.dart';
|
||||
|
||||
final givenTheText = given1<String, FlutterWidgetTesterWorld>(
|
||||
'the text {String}',
|
||||
(text, world) async {
|
||||
print(text);
|
||||
},
|
||||
);
|
|
@ -13,5 +13,14 @@ void main() {
|
|||
executeTestSuite(
|
||||
appMainFunction: appInitializationFn,
|
||||
configuration: gherkinTestConfiguration,
|
||||
// if you have lots of test you might need to increase the default timeout
|
||||
// scenarioExecutionTimeout: Timeout(const Duration(minutes: 30)),
|
||||
// if your app has lots of endless animations you might need to
|
||||
// provide your own app lifecycle pump handler that doesn't pump
|
||||
// at certain lifecycle stages
|
||||
// appLifecyclePumpHandler: (appPhase, widgetTester) async => {},
|
||||
// you can increase the performance of your tests at the cost of
|
||||
// not drawing some frames but it might lead to unexpected consequences
|
||||
// framePolicy: LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
testFeature1();
|
||||
testFeature2();
|
||||
testFeature3();
|
||||
testFeature4();
|
||||
}
|
||||
|
||||
void testFeature0() {
|
||||
|
@ -91,7 +92,7 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
],
|
||||
onBefore: () async => onBeforeRunFeature(
|
||||
name: 'Creating todos',
|
||||
path: r'.\\integration_test\\features\\create.feature',
|
||||
path: '.\\integration_test\\features\\create.feature',
|
||||
description: null,
|
||||
tags: <String>['@tag'],
|
||||
),
|
||||
|
@ -101,7 +102,7 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
name: 'User can create multiple new todo items',
|
||||
description: null,
|
||||
path: '.\\integration_test\\features\\create.feature',
|
||||
tags: <String>['@tag'],
|
||||
tags: <String>['@tag', '@debug2'],
|
||||
steps: [
|
||||
(
|
||||
TestDependencies dependencies,
|
||||
|
@ -241,7 +242,7 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
],
|
||||
onAfter: () async => onAfterRunFeature(
|
||||
name: 'Creating todos',
|
||||
path: r'.\\integration_test\\features\\create.feature',
|
||||
path: '.\\integration_test\\features\\create.feature',
|
||||
description: null,
|
||||
tags: <String>['@tag'],
|
||||
),
|
||||
|
@ -302,13 +303,13 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
],
|
||||
onBefore: () async => onBeforeRunFeature(
|
||||
name: 'Checking data',
|
||||
path: r'.\\integration_test\\features\\check.feature',
|
||||
path: '.\\integration_test\\features\\check.feature',
|
||||
description: null,
|
||||
tags: <String>['@tag'],
|
||||
),
|
||||
onAfter: () async => onAfterRunFeature(
|
||||
name: 'Checking data',
|
||||
path: r'.\\integration_test\\features\\check.feature',
|
||||
path: '.\\integration_test\\features\\check.feature',
|
||||
description: null,
|
||||
tags: <String>['@tag'],
|
||||
),
|
||||
|
@ -326,7 +327,7 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
name: 'User can swipe cards left and right',
|
||||
description: null,
|
||||
path: '.\\integration_test\\features\\swiping.feature',
|
||||
tags: <String>['@tag', '@debug'],
|
||||
tags: <String>['@tag'],
|
||||
steps: [
|
||||
(
|
||||
TestDependencies dependencies,
|
||||
|
@ -381,13 +382,13 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
],
|
||||
onBefore: () async => onBeforeRunFeature(
|
||||
name: 'Swiping',
|
||||
path: r'.\\integration_test\\features\\swiping.feature',
|
||||
path: '.\\integration_test\\features\\swiping.feature',
|
||||
description: null,
|
||||
tags: <String>['@tag'],
|
||||
),
|
||||
onAfter: () async => onAfterRunFeature(
|
||||
name: 'Swiping',
|
||||
path: r'.\\integration_test\\features\\swiping.feature',
|
||||
path: '.\\integration_test\\features\\swiping.feature',
|
||||
description: null,
|
||||
tags: <String>['@tag'],
|
||||
),
|
||||
|
@ -398,13 +399,13 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
|
||||
void testFeature3() {
|
||||
runFeature(
|
||||
name: 'Expect failure:',
|
||||
name: 'Parsing:',
|
||||
tags: <String>['@debug'],
|
||||
run: () {
|
||||
runScenario(
|
||||
name: 'Exception should be added to json report',
|
||||
name: 'Parsing a',
|
||||
description: null,
|
||||
path: '.\\integration_test\\features\\failure.feature',
|
||||
path: '.\\integration_test\\features\\parsing.feature',
|
||||
tags: <String>['@debug'],
|
||||
steps: [
|
||||
(
|
||||
|
@ -412,31 +413,7 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
bool skip,
|
||||
) async {
|
||||
return await runStep(
|
||||
name: 'Given I expect the todo list',
|
||||
multiLineStrings: <String>[],
|
||||
table: GherkinTable.fromJson('[{"Todo":"Buy blueberries"}]'),
|
||||
dependencies: dependencies,
|
||||
skip: skip,
|
||||
);
|
||||
},
|
||||
(
|
||||
TestDependencies dependencies,
|
||||
bool skip,
|
||||
) async {
|
||||
return await runStep(
|
||||
name: 'When I tap the "add" button',
|
||||
multiLineStrings: <String>[],
|
||||
table: null,
|
||||
dependencies: dependencies,
|
||||
skip: skip,
|
||||
);
|
||||
},
|
||||
(
|
||||
TestDependencies dependencies,
|
||||
bool skip,
|
||||
) async {
|
||||
return await runStep(
|
||||
name: 'And I fill the "todo" field with "Buy hannah\'s apples"',
|
||||
name: 'Given the text "^[A-Z]{3}\\\\d{5}\\\$"',
|
||||
multiLineStrings: <String>[],
|
||||
table: null,
|
||||
dependencies: dependencies,
|
||||
|
@ -445,19 +422,67 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
},
|
||||
],
|
||||
onBefore: () async => onBeforeRunFeature(
|
||||
name: 'Expect failure',
|
||||
path: r'.\\integration_test\\features\\failure.feature',
|
||||
description:
|
||||
"Ensure that when a test fails the exception or test failure is reported",
|
||||
name: 'Parsing',
|
||||
path: '.\\integration_test\\features\\parsing.feature',
|
||||
description: """Complex description:
|
||||
- Line "one".
|
||||
- Line two, more text
|
||||
- Line three""",
|
||||
tags: <String>['@debug'],
|
||||
),
|
||||
onAfter: () async => onAfterRunFeature(
|
||||
name: 'Parsing',
|
||||
path: '.\\integration_test\\features\\parsing.feature',
|
||||
description: """Complex description:
|
||||
- Line "one".
|
||||
- Line two, more text
|
||||
- Line three""",
|
||||
tags: <String>['@debug'],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void testFeature4() {
|
||||
runFeature(
|
||||
name: 'Expect failures:',
|
||||
tags: <String>[],
|
||||
run: () {
|
||||
runScenario(
|
||||
name: 'Exception should be added to json report',
|
||||
description: null,
|
||||
path: '.\\integration_test\\features\\failure.feature',
|
||||
tags: <String>['@failure-expected'],
|
||||
steps: [
|
||||
(
|
||||
TestDependencies dependencies,
|
||||
bool skip,
|
||||
) async {
|
||||
return await runStep(
|
||||
name:
|
||||
'When I tap the "button is not here but exception should be logged in report" button',
|
||||
multiLineStrings: <String>[],
|
||||
table: null,
|
||||
dependencies: dependencies,
|
||||
skip: skip,
|
||||
);
|
||||
},
|
||||
],
|
||||
onBefore: () async => onBeforeRunFeature(
|
||||
name: 'Expect failures',
|
||||
path: '.\\integration_test\\features\\failure.feature',
|
||||
description:
|
||||
"""Ensure that when a test fails the exception or test failure is reported""",
|
||||
tags: <String>[],
|
||||
),
|
||||
);
|
||||
|
||||
runScenario(
|
||||
name: 'Failed expect() should be added to json report',
|
||||
description: "Description for this scenario!",
|
||||
path: '.\\integration_test\\features\\failure.feature',
|
||||
tags: <String>['@debug'],
|
||||
tags: <String>['@failure-expected'],
|
||||
steps: [
|
||||
(
|
||||
TestDependencies dependencies,
|
||||
|
@ -497,11 +522,11 @@ class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
|
|||
},
|
||||
],
|
||||
onAfter: () async => onAfterRunFeature(
|
||||
name: 'Expect failure',
|
||||
path: r'.\\integration_test\\features\\failure.feature',
|
||||
name: 'Expect failures',
|
||||
path: '.\\integration_test\\features\\failure.feature',
|
||||
description:
|
||||
"Ensure that when a test fails the exception or test failure is reported",
|
||||
tags: <String>['@debug'],
|
||||
"""Ensure that when a test fails the exception or test failure is reported""",
|
||||
tags: <String>[],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -213,7 +213,7 @@ packages:
|
|||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "3.0.0-rc.16"
|
||||
version: "3.0.0-rc.17"
|
||||
flutter_simple_dependency_injection:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -72,7 +72,7 @@ class WidgetTesterAppDriverAdapter
|
|||
}
|
||||
}
|
||||
|
||||
Future<List<int>> screenshotOnAndroid() async {
|
||||
Future<List<int>> takeScreenshotUsingRenderElement() async {
|
||||
RenderObject? renderObject = binding.renderViewElement?.renderObject;
|
||||
if (renderObject != null) {
|
||||
while (!renderObject!.isRepaintBoundary) {
|
||||
|
@ -99,22 +99,18 @@ class WidgetTesterAppDriverAdapter
|
|||
Future<List<int>> screenshot({String? screenshotName}) async {
|
||||
final name =
|
||||
screenshotName ?? 'screenshot_${DateTime.now().millisecondsSinceEpoch}';
|
||||
if (kIsWeb) {
|
||||
return binding.takeScreenshot(name);
|
||||
} else {
|
||||
if (Platform.isAndroid) {
|
||||
// try {
|
||||
// // TODO: See https://github.com/flutter/flutter/issues/92381
|
||||
// // we need to call `revertFlutterImage` once it has been implemented
|
||||
// await binding.convertFlutterSurfaceToImage();
|
||||
// await binding.pump();
|
||||
// // ignore: no_leading_underscores_for_local_identifiers
|
||||
// } catch (_, __) {}
|
||||
if (kIsWeb || Platform.isAndroid) {
|
||||
// try {
|
||||
// // TODO: See https://github.com/flutter/flutter/issues/92381
|
||||
// // we need to call `revertFlutterImage` once it has been implemented
|
||||
// await binding.convertFlutterSurfaceToImage();
|
||||
// await binding.pump();
|
||||
// // ignore: no_leading_underscores_for_local_identifiers
|
||||
// } catch (_, __) {}
|
||||
|
||||
return await screenshotOnAndroid();
|
||||
} else {
|
||||
return await binding.takeScreenshot(name);
|
||||
}
|
||||
return await takeScreenshotUsingRenderElement();
|
||||
} else {
|
||||
return await binding.takeScreenshot(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -183,10 +183,18 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
|
|||
);}
|
||||
''';
|
||||
static const String onBeforeScenarioRun = '''
|
||||
onBefore: () async => onBeforeRunFeature(name:'{{feature_name}}', path:'{{path}}', description: {{feature_description}}, tags:{{feature_tags}},),
|
||||
onBefore: () async => onBeforeRunFeature(
|
||||
name:'{{feature_name}}',
|
||||
path:'{{path}}',
|
||||
description: {{feature_description}},
|
||||
tags:{{feature_tags}},),
|
||||
''';
|
||||
static const String onAfterScenarioRun = '''
|
||||
onAfter: () async => onAfterRunFeature(name:'{{feature_name}}', path:'{{path}}', description: {{feature_description}}, tags:{{feature_tags}},),
|
||||
onAfter: () async => onAfterRunFeature(
|
||||
name:'{{feature_name}}',
|
||||
path:'{{path}}',
|
||||
description: {{feature_description}},
|
||||
tags:{{feature_tags}},),
|
||||
''';
|
||||
|
||||
final StringBuffer _buffer = StringBuffer();
|
||||
|
@ -275,7 +283,9 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
|
|||
_currentScenarioCode = _replaceVariable(
|
||||
_currentScenarioCode!,
|
||||
'feature_description',
|
||||
_escapeText(featureDescription == null ? null : '"$featureDescription"'),
|
||||
_escapeText(
|
||||
featureDescription == null ? null : '"""$featureDescription"""',
|
||||
),
|
||||
);
|
||||
_currentScenarioCode = _replaceVariable(
|
||||
_currentScenarioCode!,
|
||||
|
@ -370,6 +380,8 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
|
|||
return content.replaceAll('{{$property}}', value ?? 'null');
|
||||
}
|
||||
|
||||
String? _escapeText(String? text) =>
|
||||
text?.replaceAll("\\", "\\\\").replaceAll("'", "\\'");
|
||||
String? _escapeText(String? text) => text
|
||||
?.replaceAll("\\", "\\\\")
|
||||
.replaceAll("'", "\\'")
|
||||
.replaceAll(r"$", r"\$");
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'package:flutter_gherkin/flutter_gherkin_with_driver.dart';
|
||||
import 'package:flutter_gherkin/src/flutter/parameters/existence_parameter.dart';
|
||||
import 'package:flutter_gherkin/src/flutter/parameters/swipe_direction_parameter.dart';
|
||||
|
|
|
@ -83,24 +83,24 @@ abstract class GherkinIntegrationTestRunner {
|
|||
_binding.framePolicy = framePolicy ?? _binding.framePolicy;
|
||||
|
||||
tearDownAll(
|
||||
() {
|
||||
onRunComplete();
|
||||
() async {
|
||||
await onRunComplete();
|
||||
},
|
||||
);
|
||||
|
||||
_safeInvokeFuture(() async => await hook.onBeforeRun(configuration));
|
||||
_safeInvokeFuture(() async => await reporter.test.onStarted.invoke());
|
||||
await hook.onBeforeRun(configuration);
|
||||
await reporter.test.onStarted.invoke();
|
||||
|
||||
onRun();
|
||||
}
|
||||
|
||||
void onRun();
|
||||
|
||||
void onRunComplete() {
|
||||
_safeInvokeFuture(() async => await reporter.test.onFinished.invoke());
|
||||
_safeInvokeFuture(() async => await hook.onAfterRun(configuration));
|
||||
Future<void> onRunComplete() async {
|
||||
await reporter.test.onFinished.invoke();
|
||||
await hook.onAfterRun(configuration);
|
||||
setTestResultData(_binding);
|
||||
_safeInvokeFuture(() async => await reporter.dispose());
|
||||
() async => await reporter.dispose();
|
||||
}
|
||||
|
||||
void setTestResultData(IntegrationTestWidgetsFlutterBinding binding) {
|
||||
|
@ -226,9 +226,11 @@ abstract class GherkinIntegrationTestRunner {
|
|||
failed = true;
|
||||
hasToSkip = true;
|
||||
}
|
||||
} catch (e) {
|
||||
} catch (err, st) {
|
||||
failed = true;
|
||||
hasToSkip = true;
|
||||
|
||||
await reporter.onException(err, st);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -258,18 +260,16 @@ abstract class GherkinIntegrationTestRunner {
|
|||
tester,
|
||||
);
|
||||
|
||||
cleanUpScenarioRun(dependencies);
|
||||
await cleanUpScenarioRun(dependencies);
|
||||
}
|
||||
},
|
||||
timeout: scenarioExecutionTimeout,
|
||||
semanticsEnabled: configuration.semanticsEnabled,
|
||||
);
|
||||
} else {
|
||||
_safeInvokeFuture(
|
||||
() async => reporter.message(
|
||||
'Ignoring scenario `$name` as tag expression `${configuration.tagExpression}` not satisfied',
|
||||
MessageLevel.info,
|
||||
),
|
||||
reporter.message(
|
||||
'Ignoring scenario `$name` as tag expression `${configuration.tagExpression}` not satisfied',
|
||||
MessageLevel.info,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -325,52 +325,62 @@ abstract class GherkinIntegrationTestRunner {
|
|||
required TestDependencies dependencies,
|
||||
required bool skip,
|
||||
}) async {
|
||||
final executable = _executableSteps!.firstWhereOrNull(
|
||||
(s) => s.expression.isMatch(name),
|
||||
);
|
||||
|
||||
if (executable == null) {
|
||||
final message = 'Step definition not found for text: `$name`';
|
||||
throw GherkinStepNotDefinedException(message);
|
||||
}
|
||||
|
||||
var parameters = _getStepParameters(
|
||||
step: name,
|
||||
multiLineStrings: multiLineStrings,
|
||||
table: table,
|
||||
code: executable,
|
||||
);
|
||||
|
||||
await _onBeforeStepRun(
|
||||
world: dependencies.world,
|
||||
step: name,
|
||||
table: table,
|
||||
multiLineStrings: multiLineStrings,
|
||||
);
|
||||
|
||||
StepResult? result;
|
||||
|
||||
if (skip) {
|
||||
result = StepResult(
|
||||
0,
|
||||
StepExecutionResult.skipped,
|
||||
resultReason: 'Previous step(s) failed',
|
||||
try {
|
||||
final executable = _executableSteps!.firstWhereOrNull(
|
||||
(s) => s.expression.isMatch(name),
|
||||
);
|
||||
} else {
|
||||
for (int i = 0; i < configuration.stepMaxRetries + 1; i++) {
|
||||
result = await executable.step.run(
|
||||
dependencies.world,
|
||||
reporter,
|
||||
configuration.defaultTimeout,
|
||||
parameters,
|
||||
|
||||
if (executable == null) {
|
||||
final message = 'Step definition not found for text: `$name`';
|
||||
throw GherkinStepNotDefinedException(message);
|
||||
}
|
||||
|
||||
var parameters = _getStepParameters(
|
||||
step: name,
|
||||
multiLineStrings: multiLineStrings,
|
||||
table: table,
|
||||
code: executable,
|
||||
);
|
||||
|
||||
await _onBeforeStepRun(
|
||||
world: dependencies.world,
|
||||
step: name,
|
||||
table: table,
|
||||
multiLineStrings: multiLineStrings,
|
||||
);
|
||||
|
||||
if (skip) {
|
||||
result = StepResult(
|
||||
0,
|
||||
StepExecutionResult.skipped,
|
||||
resultReason: 'Previous step(s) failed',
|
||||
);
|
||||
if (!_isNegativeResult(result.result) ||
|
||||
configuration.stepMaxRetries == 0) {
|
||||
break;
|
||||
} else {
|
||||
await Future.delayed(configuration.retryDelay);
|
||||
} else {
|
||||
for (int i = 0; i < configuration.stepMaxRetries + 1; i++) {
|
||||
result = await executable.step.run(
|
||||
dependencies.world,
|
||||
reporter,
|
||||
configuration.defaultTimeout,
|
||||
parameters,
|
||||
);
|
||||
|
||||
if (!_isNegativeResult(result.result) ||
|
||||
configuration.stepMaxRetries == 0) {
|
||||
break;
|
||||
} else {
|
||||
await Future.delayed(configuration.retryDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err, st) {
|
||||
result = ErroredStepResult(
|
||||
0,
|
||||
StepExecutionResult.error,
|
||||
err,
|
||||
st,
|
||||
);
|
||||
}
|
||||
|
||||
await _onAfterStepRun(
|
||||
|
@ -383,13 +393,9 @@ abstract class GherkinIntegrationTestRunner {
|
|||
}
|
||||
|
||||
@protected
|
||||
void cleanUpScenarioRun(TestDependencies dependencies) {
|
||||
_safeInvokeFuture(
|
||||
() async => dependencies.attachmentManager.dispose(),
|
||||
);
|
||||
_safeInvokeFuture(
|
||||
() async => dependencies.world.dispose(),
|
||||
);
|
||||
Future<void> cleanUpScenarioRun(TestDependencies dependencies) async {
|
||||
dependencies.attachmentManager.dispose();
|
||||
dependencies.world.dispose();
|
||||
}
|
||||
|
||||
void _registerReporters(Iterable<Reporter>? reporters) {
|
||||
|
@ -505,12 +511,6 @@ abstract class GherkinIntegrationTestRunner {
|
|||
);
|
||||
}
|
||||
|
||||
void _safeInvokeFuture(Future<void> Function() fn) async {
|
||||
try {
|
||||
await fn().catchError((_, __) {});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
bool _evaluateTagFilterExpression(
|
||||
String? tagExpression,
|
||||
Iterable<String>? tags,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: flutter_gherkin
|
||||
description: A Gherkin / Cucumber parser and test runner for Dart and Flutter
|
||||
version: 3.0.0-rc.16
|
||||
version: 3.0.0-rc.17
|
||||
homepage: https://github.com/jonsamwell/flutter_gherkin
|
||||
|
||||
environment:
|
||||
|
|
Loading…
Reference in New Issue