diff --git a/.gitignore b/.gitignore index 55e2d6c..5019a52 100644 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,4 @@ pubspec.lock !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -coverage/lcov.info +/coverage/ diff --git a/example/test/songs.feature b/example/test/songs.feature new file mode 100644 index 0000000..b47c28c --- /dev/null +++ b/example/test/songs.feature @@ -0,0 +1,7 @@ +Feature: Songs + + Scenario: Available songs + Given the following songs + | 'artist' | 'title' | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | diff --git a/example/test/songs_test.dart b/example/test/songs_test.dart new file mode 100644 index 0000000..6589104 --- /dev/null +++ b/example/test/songs_test.dart @@ -0,0 +1,16 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_import, directives_ordering + +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './step/the_following_songs.dart'; + +void main() { + group('''Songs''', () { + testWidgets('''Available songs''', (tester) async { + await theFollowingSongs(tester, const bdd.DataTable([['artist', 'title'], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + }); + }); +} diff --git a/example/test/step/the_following_songs.dart b/example/test/step/the_following_songs.dart new file mode 100644 index 0000000..1f85dfb --- /dev/null +++ b/example/test/step/the_following_songs.dart @@ -0,0 +1,7 @@ +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter_test/flutter_test.dart'; + +/// Usage: the following songs +Future theFollowingSongs(WidgetTester tester, bdd.DataTable dataTable) async { + throw UnimplementedError(); +} diff --git a/lib/data_table.dart b/lib/data_table.dart new file mode 100644 index 0000000..9977522 --- /dev/null +++ b/lib/data_table.dart @@ -0,0 +1,20 @@ +import 'package:collection/collection.dart'; + +class DataTable { + const DataTable(this._data); + + final List> _data; + + List> asLists() => _data; + + List> asMaps() { + final headers = _data.first; + return _data.skip(1).map((row) { + final map = {}; + headers.forEachIndexed((index, header) { + map[header] = row[index]; + }); + return map; + }).toList(); + } +} diff --git a/lib/src/bdd_line.dart b/lib/src/bdd_line.dart index c585967..d04c3cd 100644 --- a/lib/src/bdd_line.dart +++ b/lib/src/bdd_line.dart @@ -4,6 +4,8 @@ class BddLine { value = _removeLinePrefix(rawLine); BddLine.fromValue(this.type, this.value) : rawLine = ''; + BddLine.fromRawValue(this.type, this.rawLine) + : value = _removeLinePrefix(rawLine); final String rawLine; final String value; @@ -17,6 +19,7 @@ enum LineType { scenario, scenarioOutline, step, + dataTableStep, after, examples, exampleTitle, diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index c0af78e..41eeaae 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -1,37 +1,86 @@ import 'package:bdd_widget_test/src/bdd_line.dart'; +import 'package:bdd_widget_test/src/regex.dart'; import 'package:bdd_widget_test/src/scenario_generator.dart'; -Iterable replaceDataTables(List lines) sync* { - var reachedExamples = false; - var i = 0; - while (i < lines.length) { - if (lines[i].type == LineType.exampleTitle) { - reachedExamples = true; - } - if (reachedExamples) { - yield lines[i++]; - continue; +bool hasBddDataTable(List lines) { + for (var index = 0; index < lines.length; index++) { + final isStep = lines[index].type == LineType.step || + lines[index].type == LineType.dataTableStep; + final isNextLineTable = isTable(lines: lines, index: index + 1); + final isExamplesFormatted = hasExamplesFormat(bddLine: lines[index]); + if (isStep && isNextLineTable && !isExamplesFormatted) { + return true; } - if (i + 1 < lines.length && _foundDataTable(lines, i)) { - final dataTable = [ - lines[i], - ...lines.skip(i + 1).takeWhile((l) => l.type == LineType.examples), - ]; - final data = generateScenariosFromScenaioOutline([ - // pretend to be an Example section to re-use some logic - BddLine.fromValue(LineType.exampleTitle, ''), - ...dataTable, - ]); - for (final item in data) { - yield item[1]; + } + return false; +} + +Iterable replaceDataTables(List lines) sync* { + for (var index = 0; index < lines.length; index++) { + final isStep = lines[index].type == LineType.step || + lines[index].type == LineType.dataTableStep; + final isNextLineTable = isTable(lines: lines, index: index + 1); + if (isStep && isNextLineTable) { + if (!hasExamplesFormat(bddLine: lines[index])) { + yield* _createCucumberDataTable(lines: lines, index: index); + } else { + yield* _createDataTableFromExamples(lines: lines, index: index); } - i += dataTable.length; - continue; + } else { + yield lines[index]; } - yield lines[i++]; } } -bool _foundDataTable(List lines, int index) => - lines[index].type == LineType.step && - lines[index + 1].type == LineType.examples; +bool isTable({ + required List lines, + required int index, +}) => + index < lines.length && lines[index].type == LineType.examples; + +bool hasExamplesFormat({required BddLine bddLine}) => + examplesRegExp.firstMatch(bddLine.rawLine) != null; + +List _createRow({ + required BddLine bddLine, +}) => + bddLine.value + .split('|') + .map((example) => example.trim()) + .takeWhile((value) => value.isNotEmpty) + .toList(); + +Iterable _createCucumberDataTable({ + required List lines, + required int index, +}) sync* { + final text = lines[index].value; + final table = >[]; + do { + table.add(_createRow(bddLine: lines[++index])); + } while (isTable(lines: lines, index: index + 1)); + yield BddLine.fromValue( + LineType.dataTableStep, + '$text {const bdd.DataTable($table)}', + ); +} + +Iterable _createDataTableFromExamples({ + required List lines, + required int index, +}) sync* { + final dataTable = [lines[index]]; + do { + dataTable.add(lines[++index]); + } while ( + index + 1 < lines.length && lines[index + 1].type == LineType.examples); + final data = generateScenariosFromScenaioOutline([ + // pretend to be an Example section to re-use some logic + BddLine.fromValue(LineType.exampleTitle, ''), + ...dataTable, + ]); + + for (final item in data) { + yield item[1]; + } +} diff --git a/lib/src/feature_file.dart b/lib/src/feature_file.dart index 50b1f9d..26894c7 100644 --- a/lib/src/feature_file.dart +++ b/lib/src/feature_file.dart @@ -1,9 +1,12 @@ import 'package:bdd_widget_test/src/bdd_line.dart'; +import 'package:bdd_widget_test/src/data_table_parser.dart' + as data_table_parser; import 'package:bdd_widget_test/src/feature_generator.dart'; import 'package:bdd_widget_test/src/generator_options.dart'; import 'package:bdd_widget_test/src/step_file.dart'; import 'package:bdd_widget_test/src/util/common.dart'; import 'package:bdd_widget_test/src/util/constants.dart'; +import 'package:collection/collection.dart'; class FeatureFile { FeatureFile({ @@ -29,12 +32,15 @@ class FeatureFile { ); _stepFiles = _lines - .where((line) => line.type == LineType.step) + .where( + (line) => + line.type == LineType.step || line.type == LineType.dataTableStep, + ) .map( - (e) => StepFile.create( + (bddLine) => StepFile.create( featureDir, package, - e.value, + bddLine, existingSteps, generatorOptions, _testerType, @@ -67,10 +73,28 @@ class FeatureFile { List getStepFiles() => _stepFiles; static List _prepareLines(Iterable input) { - final headers = input.takeWhile((value) => value.type == LineType.unknown); - final lines = input + final lines = input.mapIndexed( + (index, bddLine) { + final isStep = bddLine.type == LineType.step; + final hasExamplesFormat = data_table_parser.hasExamplesFormat( + bddLine: bddLine, + ); + final isNextTable = data_table_parser.isTable( + lines: input.toList(), + index: index + 1, + ); + if (isStep && !hasExamplesFormat && isNextTable) { + return BddLine.fromRawValue(LineType.dataTableStep, bddLine.rawLine); + } else { + return bddLine; + } + }, + ); + + final headers = lines.takeWhile((value) => value.type == LineType.unknown); + final steps = lines .skip(headers.length) .where((value) => value.type != LineType.unknown); - return [...headers, ...lines]; + return [...headers, ...steps]; } } diff --git a/lib/src/feature_generator.dart b/lib/src/feature_generator.dart index 648b0dc..1b3bf59 100644 --- a/lib/src/feature_generator.dart +++ b/lib/src/feature_generator.dart @@ -48,6 +48,9 @@ String generateFeatureDart( if (tags.isNotEmpty) { sb.writeln("@Tags(['${tags.join("', '")}'])"); } + if (hasBddDataTable(lines)) { + sb.writeln("import 'package:bdd_widget_test/data_table.dart' as bdd;"); + } sb.writeln("import 'package:flutter/material.dart';"); sb.writeln("import 'package:flutter_test/flutter_test.dart';"); if (isIntegrationTest) { @@ -138,7 +141,8 @@ bool _parseSetup( if (offset != -1) { sb.writeln(' Future $title($testerType $testerName) async {'); offset++; - while (lines[offset].type == LineType.step) { + while (lines[offset].type == LineType.step || + lines[offset].type == LineType.dataTableStep) { sb.writeln( ' await ${getStepMethodCall(lines[offset].value, testerName)};', ); @@ -186,7 +190,12 @@ void _parseFeature( parseScenario( sb, s.first.value, - s.where((e) => e.type == LineType.step).toList(), + s + .where( + (e) => + e.type == LineType.step || e.type == LineType.dataTableStep, + ) + .toList(), hasSetUp, hasTearDown, scenarioTestMethodName, @@ -236,7 +245,7 @@ Iterable> _splitScenarios(List lines) sync* { Iterable _parseScenario(List lines) sync* { var isNewScenario = true; for (final line in lines) { - if (line.type == LineType.step) { + if (line.type == LineType.step || line.type == LineType.dataTableStep) { isNewScenario = false; } if (!isNewScenario && _isNewScenario(line.type)) { diff --git a/lib/src/step/generic_step.dart b/lib/src/step/generic_step.dart index 9bb7a5c..df2f61f 100644 --- a/lib/src/step/generic_step.dart +++ b/lib/src/step/generic_step.dart @@ -9,24 +9,32 @@ class GenericStep implements BddStep { this.rawLine, this.testerType, this.customTesterName, + this.hasDataTable, ); final String rawLine; final String methodName; final String testerType; final String customTesterName; + final bool hasDataTable; @override - String get content => ''' + String get content => + '${hasDataTable ? "import 'package:bdd_widget_test/data_table.dart' as bdd;\n" : ''}' + ''' import 'package:flutter_test/flutter_test.dart'; /// Usage: $rawLine -Future $methodName($testerType $customTesterName${_getMethodParameters(rawLine)}) async { +Future $methodName($testerType $customTesterName${_getMethodParameters(rawLine, hasDataTable)}) async { throw UnimplementedError(); } '''; - String _getMethodParameters(String stepLine) { + String _getMethodParameters(String stepLine, bool hadDataTable) { + if (hadDataTable) { + return ', bdd.DataTable dataTable'; + } + final params = parseRawStepLine(stepLine).skip(1); if (params.isNotEmpty) { return params diff --git a/lib/src/step_file.dart b/lib/src/step_file.dart index 441441b..a790eb9 100644 --- a/lib/src/step_file.dart +++ b/lib/src/step_file.dart @@ -1,3 +1,4 @@ +import 'package:bdd_widget_test/src/bdd_line.dart'; import 'package:bdd_widget_test/src/generator_options.dart'; import 'package:bdd_widget_test/src/step_generator.dart'; import 'package:bdd_widget_test/src/util/constants.dart'; @@ -10,13 +11,13 @@ abstract class StepFile { static StepFile create( String featureDir, String package, - String line, + BddLine bddLine, Map existingSteps, GeneratorOptions generatorOptions, String testerTypeTagValue, String testerNameTagValue, ) { - final file = '${getStepFilename(line)}.dart'; + final file = '${getStepFilename(bddLine.value)}.dart'; if (existingSteps.containsKey(file)) { final import = @@ -39,9 +40,10 @@ abstract class StepFile { import, filename, package, - line, + bddLine.value, testerTypeTagValue, testerNameTagValue, + bddLine.type == LineType.dataTableStep, ); } @@ -54,9 +56,10 @@ abstract class StepFile { import, filename, package, - line, + bddLine.value, testerTypeTagValue, testerNameTagValue, + bddLine.type == LineType.dataTableStep, ); } } @@ -69,6 +72,7 @@ class NewStepFile extends StepFile { this.line, this.testerType, this.testerName, + this.hasDataTable, ) : super._(); final String package; @@ -76,9 +80,14 @@ class NewStepFile extends StepFile { final String filename; final String testerType; final String testerName; - - String get dartContent => - generateStepDart(package, line, testerType, testerName); + final bool hasDataTable; + String get dartContent => generateStepDart( + package, + line, + testerType, + testerName, + hasDataTable, + ); } class ExistingStepFile extends StepFile { diff --git a/lib/src/step_generator.dart b/lib/src/step_generator.dart index fb5a25e..4fc604f 100644 --- a/lib/src/step_generator.dart +++ b/lib/src/step_generator.dart @@ -51,11 +51,18 @@ String generateStepDart( String line, String testerType, String customTesterName, + bool hasDataTable, ) { final methodName = getStepMethodName(line); - final bddStep = - _getStep(methodName, package, line, testerType, customTesterName); + final bddStep = _getStep( + methodName, + package, + line, + testerType, + customTesterName, + hasDataTable, + ); return bddStep.content; } @@ -65,10 +72,17 @@ BddStep _getStep( String line, String testerType, String testerName, + bool hasDataTable, ) { //for now, predefined steps don't support testerType final factory = predefinedSteps[methodName] ?? - (_, __) => GenericStep(methodName, line, testerType, testerName); + (_, __) => GenericStep( + methodName, + line, + testerType, + testerName, + hasDataTable, + ); return factory(package, line); } diff --git a/test/data_table_test.dart b/test/data_table_test.dart new file mode 100644 index 0000000..6dd7ed6 --- /dev/null +++ b/test/data_table_test.dart @@ -0,0 +1,34 @@ +import 'package:bdd_widget_test/data_table.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('asLists', () { + final data = [ + ['Country', 'City'], + ['England', 'London'], + ['England', 'Manchester'], + ]; + final dataTable = DataTable(data); + + final result = dataTable.asLists(); + + expect(result, data); + }); + + test('asMaps', () { + final data = [ + ['id', 'isValid'], + [1, false], + [2, true], + ]; + final expected = [ + {'id': 1, 'isValid': false}, + {'id': 2, 'isValid': true}, + ]; + final dataTable = DataTable(data); + + final result = dataTable.asMaps(); + + expect(result, expected); + }); +} diff --git a/test/data_tables_test.dart b/test/data_tables_test.dart index 04f0280..6db852a 100644 --- a/test/data_tables_test.dart +++ b/test/data_tables_test.dart @@ -46,4 +46,275 @@ void main() { ); expect(feature.dartContent, expectedFeatureDart); }); + + test('Data table with any cucumber keyword', () { + const featureFile = ''' +Feature: Testing feature + Scenario: Testing scenario + Given the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + And the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + But the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + When the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + And I wait + Then the following songs + | 'The Beatles' | 'Let It Be' | +'''; + + const expectedFeatureDart = ''' +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_import, directives_ordering + +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './step/the_following_songs.dart'; +import './step/i_wait.dart'; + +void main() { + group(\'\'\'Testing feature\'\'\', () { + testWidgets(\'\'\'Testing scenario\'\'\', (tester) async { + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await iWait(tester); + await theFollowingSongs(tester, const bdd.DataTable([['The Beatles', 'Let It Be']])); + }); + }); +} +'''; + + final feature = FeatureFile( + featureDir: 'test.feature', + package: 'test', + input: featureFile, + ); + expect(feature.dartContent, expectedFeatureDart); + }); + + test('Cucumber data table before example table', () { + const featureFile = ''' +Feature: Testing feature + Scenario: Testing scenario + Given the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + And I wait + And the following users exist + | name | twitter | + | 'Oleksandr' | '@olexale' | + | 'Flutter' | '@FlutterDev' | +'''; + + const expectedFeatureDart = ''' +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_import, directives_ordering + +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './step/the_following_songs.dart'; +import './step/i_wait.dart'; +import './step/the_following_users_exist.dart'; + +void main() { + group(\'\'\'Testing feature\'\'\', () { + testWidgets(\'\'\'Testing scenario\'\'\', (tester) async { + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await iWait(tester); + await theFollowingUsersExist(tester, 'Oleksandr', '@olexale'); + await theFollowingUsersExist(tester, 'Flutter', '@FlutterDev'); + }); + }); +} +'''; + + final feature = FeatureFile( + featureDir: 'test.feature', + package: 'test', + input: featureFile, + ); + + expect(feature.dartContent, expectedFeatureDart); + }); + + test('Cucumber data table after example table', () { + const featureFile = ''' +Feature: Testing feature + Scenario: Testing scenario + Given the following users exist + | name | twitter | + | 'Oleksandr' | '@olexale' | + | 'Flutter' | '@FlutterDev' | + And I wait + And the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | +'''; + + const expectedFeatureDart = ''' +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_import, directives_ordering + +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './step/the_following_users_exist.dart'; +import './step/i_wait.dart'; +import './step/the_following_songs.dart'; + +void main() { + group(\'\'\'Testing feature\'\'\', () { + testWidgets(\'\'\'Testing scenario\'\'\', (tester) async { + await theFollowingUsersExist(tester, 'Oleksandr', '@olexale'); + await theFollowingUsersExist(tester, 'Flutter', '@FlutterDev'); + await iWait(tester); + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + }); + }); +} +'''; + + final feature = FeatureFile( + featureDir: 'test.feature', + package: 'test', + input: featureFile, + ); + + expect(feature.dartContent, expectedFeatureDart); + }); + + test('Mixed data tables with a single example outline', () { + const featureFile = ''' +Feature: Testing feature + Scenario Outline: Testing scenario + Given the following users exist + | name | twitter | + | 'Oleksandr' | '@olexale' | + | 'Flutter' | '@FlutterDev' | + And band is on tour + And I wait + And the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + Examples: + | band | + | 'Camel' | +'''; + + const expectedFeatureDart = ''' +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_import, directives_ordering + +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './step/the_following_users_exist.dart'; +import './step/band_is_on_tour.dart'; +import './step/i_wait.dart'; +import './step/the_following_songs.dart'; + +void main() { + group(\'\'\'Testing feature\'\'\', () { + testWidgets(\'\'\'Outline: Testing scenario ('Camel')\'\'\', (tester) async { + await theFollowingUsersExist(tester, 'Oleksandr', '@olexale'); + await theFollowingUsersExist(tester, 'Flutter', '@FlutterDev'); + await bandIsOnTour(tester, 'Camel'); + await iWait(tester); + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + }); + }); +} +'''; + + final feature = FeatureFile( + featureDir: 'test.feature', + package: 'test', + input: featureFile, + ); + + expect(feature.dartContent, expectedFeatureDart); + }); + + test('Mixed data tables with multiple examples outline', () { + const featureFile = ''' +Feature: Testing feature + Scenario Outline: Testing scenario + Given the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + And band is on tour + And I wait + Given the following users exist + | name | twitter | + | 'Oleksandr' | '@olexale' | + | 'Flutter' | '@FlutterDev' | + + Examples: + | band | + | 'Camel' | + | 'Pearl Jam' | +'''; + + const expectedFeatureDart = ''' +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_import, directives_ordering + +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './step/the_following_songs.dart'; +import './step/band_is_on_tour.dart'; +import './step/i_wait.dart'; +import './step/the_following_users_exist.dart'; + +void main() { + group(\'\'\'Testing feature\'\'\', () { + testWidgets(\'\'\'Outline: Testing scenario ('Camel')\'\'\', (tester) async { + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await bandIsOnTour(tester, 'Camel'); + await iWait(tester); + await theFollowingUsersExist(tester, 'Oleksandr', '@olexale'); + await theFollowingUsersExist(tester, 'Flutter', '@FlutterDev'); + }); + testWidgets(\'\'\'Outline: Testing scenario ('Pearl Jam')\'\'\', (tester) async { + await theFollowingSongs(tester, const bdd.DataTable([[artist, title], ['The Beatles', 'Let It Be'], ['Camel', 'Slow yourself down']])); + await bandIsOnTour(tester, 'Pearl Jam'); + await iWait(tester); + await theFollowingUsersExist(tester, 'Oleksandr', '@olexale'); + await theFollowingUsersExist(tester, 'Flutter', '@FlutterDev'); + }); + }); +} +'''; + + final feature = FeatureFile( + featureDir: 'test.feature', + package: 'test', + input: featureFile, + ); + + expect(feature.dartContent, expectedFeatureDart); + }); } diff --git a/test/step/generic_step_test.dart b/test/step/generic_step_test.dart index 77f20f5..1706a16 100644 --- a/test/step/generic_step_test.dart +++ b/test/step/generic_step_test.dart @@ -89,4 +89,37 @@ Future iInvokeTest(WidgetTester tester) async { expectedSteps, ); }); + + test('Generic step with cucumber data table', () { + const path = 'test'; + const featureFile = ''' +Feature: Testing feature + Scenario: Testing scenario + Given the following songs + | artist | title | + | 'The Beatles' | 'Let It Be' | + | 'Camel' | 'Slow yourself down' | + '''; + + const expectedSteps = ''' +import 'package:bdd_widget_test/data_table.dart' as bdd; +import 'package:flutter_test/flutter_test.dart'; + +/// Usage: the following songs +Future theFollowingSongs(WidgetTester tester, bdd.DataTable dataTable) async { + throw UnimplementedError(); +} +'''; + + final feature = FeatureFile( + featureDir: '$path.feature', + package: path, + input: featureFile, + ); + + expect( + feature.getStepFiles().whereType().single.dartContent, + expectedSteps, + ); + }); }