From 960a1142a6f75ba7b38415102a9784deeb386fb6 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Fri, 12 Jan 2024 10:30:36 +0000 Subject: [PATCH 01/20] Added data table parsing logic --- example/test/songs.feature | 7 + example/test/songs_test.dart | 16 ++ example/test/step/the_following_songs.dart | 7 + lib/src/bdd_line.dart | 4 + lib/src/data_table.dart | 5 + lib/src/data_table_parser.dart | 100 +++++--- lib/src/feature_file.dart | 27 +- lib/src/feature_generator.dart | 5 +- lib/src/step/generic_step.dart | 19 +- lib/src/step_file.dart | 15 +- lib/src/step_generator.dart | 20 +- test/data_tables_test.dart | 271 +++++++++++++++++++++ test/step/generic_step_test.dart | 33 +++ 13 files changed, 487 insertions(+), 42 deletions(-) create mode 100644 example/test/songs.feature create mode 100644 example/test/songs_test.dart create mode 100644 example/test/step/the_following_songs.dart create mode 100644 lib/src/data_table.dart 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..5033417 --- /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/src/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..dba6f83 --- /dev/null +++ b/example/test/step/the_following_songs.dart @@ -0,0 +1,7 @@ +import 'package:bdd_widget_test/src/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/src/bdd_line.dart b/lib/src/bdd_line.dart index c585967..b315a54 100644 --- a/lib/src/bdd_line.dart +++ b/lib/src/bdd_line.dart @@ -10,6 +10,10 @@ class BddLine { final LineType type; } +class DataTableBddLine extends BddLine { + DataTableBddLine(super.rawLine); +} + enum LineType { feature, background, diff --git a/lib/src/data_table.dart b/lib/src/data_table.dart new file mode 100644 index 0000000..dedd574 --- /dev/null +++ b/lib/src/data_table.dart @@ -0,0 +1,5 @@ +class DataTable { + const DataTable(this._data); + + final List> _data; +} diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index c0af78e..e12c8ab 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -1,37 +1,79 @@ 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; +abstract class DataTableParser { + static bool hasBddDataTable(List lines) { + for (var index = 0; index < lines.length; index++) { + final isStep = lines[index].type == LineType.step; + final isNextLineTable = isNextTable(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; + } + + static Iterable replaceDataTables(List lines) sync* { + for (var index = 0; index < lines.length; index++) { + final isStep = lines[index].type == LineType.step; + final isNextLineTable = isNextTable(lines: lines, index: index + 1); + if (isStep && isNextLineTable) { + if (!hasExamplesFormat(bddLine: lines[index])) { + // Cucumber data table + final text = lines[index].value; + final table = List>.empty(growable: true); + do { + table.add(_createRow(bddLine: lines[++index])); + } while (isNextTable(lines: lines, index: index + 1)); + yield BddLine.fromValue( + LineType.step, + '$text {const bdd.DataTable($table)}', + ); + } else { + // Data table formatted as examples + 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]; + } + } + } else { + yield lines[index]; } - i += dataTable.length; - continue; } - yield lines[i++]; } -} -bool _foundDataTable(List lines, int index) => - lines[index].type == LineType.step && - lines[index + 1].type == LineType.examples; + static bool isNextTable({ + required List lines, + required int index, + }) => + index < lines.length && _isTable(bddLine: lines[index]); + + static bool _isTable({required BddLine bddLine}) => + bddLine.type == LineType.examples; + + static bool hasExamplesFormat({required BddLine bddLine}) => + examplesRegExp.allMatches(bddLine.rawLine).isNotEmpty; + + static List _createRow({ + required BddLine bddLine, + }) => + List.unmodifiable( + bddLine.value + .split('|') + .map((example) => example.trim()) + .takeWhile((value) => value.isNotEmpty) + .toList(), + ); +} diff --git a/lib/src/feature_file.dart b/lib/src/feature_file.dart index 50b1f9d..f9249cc 100644 --- a/lib/src/feature_file.dart +++ b/lib/src/feature_file.dart @@ -1,9 +1,11 @@ import 'package:bdd_widget_test/src/bdd_line.dart'; +import 'package:bdd_widget_test/src/data_table_parser.dart'; 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({ @@ -39,6 +41,7 @@ class FeatureFile { generatorOptions, _testerType, _testerName, + e is DataTableBddLine, ), ) .toList(); @@ -67,10 +70,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 = DataTableParser.hasExamplesFormat( + bddLine: bddLine, + ); + final isNextTable = DataTableParser.isNextTable( + lines: input.toList(), + index: index + 1, + ); + if (isStep && !hasExamplesFormat && isNextTable) { + return DataTableBddLine(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..5cc6f7a 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 (DataTableParser.hasBddDataTable(lines)) { + sb.writeln("import 'package:bdd_widget_test/src/data_table.dart' as bdd;"); + } sb.writeln("import 'package:flutter/material.dart';"); sb.writeln("import 'package:flutter_test/flutter_test.dart';"); if (isIntegrationTest) { @@ -175,7 +178,7 @@ void _parseFeature( scenarioParamsTag, ); - final flattenDataTables = replaceDataTables( + final flattenDataTables = DataTableParser.replaceDataTables( scenario.skipWhile((line) => line.type == LineType.tag).toList(), ).toList(); final scenariosToParse = flattenDataTables.first.type == LineType.scenario diff --git a/lib/src/step/generic_step.dart b/lib/src/step/generic_step.dart index 9bb7a5c..04303d6 100644 --- a/lib/src/step/generic_step.dart +++ b/lib/src/step/generic_step.dart @@ -9,24 +9,37 @@ class GenericStep implements BddStep { this.rawLine, this.testerType, this.customTesterName, + this.hadDataTable, ); final String rawLine; final String methodName; final String testerType; final String customTesterName; + final bool hadDataTable; @override - String get content => ''' + String get content { + var result = ''; + if (hadDataTable) { + result += + "import 'package:bdd_widget_test/src/data_table.dart' as bdd;\n"; + } + return result += ''' import 'package:flutter_test/flutter_test.dart'; /// Usage: $rawLine -Future $methodName($testerType $customTesterName${_getMethodParameters(rawLine)}) async { +Future $methodName($testerType $customTesterName${_getMethodParameters(rawLine, hadDataTable)}) async { throw UnimplementedError(); } '''; + } + + String _getMethodParameters(String stepLine, bool hadDataTable) { + if (hadDataTable) { + return ', bdd.DataTable dataTable'; + } - String _getMethodParameters(String stepLine) { 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..dd46a5d 100644 --- a/lib/src/step_file.dart +++ b/lib/src/step_file.dart @@ -15,6 +15,7 @@ abstract class StepFile { GeneratorOptions generatorOptions, String testerTypeTagValue, String testerNameTagValue, + bool hadDataTable, ) { final file = '${getStepFilename(line)}.dart'; @@ -42,6 +43,7 @@ abstract class StepFile { line, testerTypeTagValue, testerNameTagValue, + hadDataTable, ); } @@ -57,6 +59,7 @@ abstract class StepFile { line, testerTypeTagValue, testerNameTagValue, + hadDataTable, ); } } @@ -69,6 +72,7 @@ class NewStepFile extends StepFile { this.line, this.testerType, this.testerName, + this.isDataTable, ) : 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 isDataTable; + String get dartContent => generateStepDart( + package, + line, + testerType, + testerName, + isDataTable, + ); } class ExistingStepFile extends StepFile { diff --git a/lib/src/step_generator.dart b/lib/src/step_generator.dart index fb5a25e..83162fa 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 hadDataTable, ) { final methodName = getStepMethodName(line); - final bddStep = - _getStep(methodName, package, line, testerType, customTesterName); + final bddStep = _getStep( + methodName, + package, + line, + testerType, + customTesterName, + hadDataTable, + ); return bddStep.content; } @@ -65,10 +72,17 @@ BddStep _getStep( String line, String testerType, String testerName, + bool hadDataTable, ) { //for now, predefined steps don't support testerType final factory = predefinedSteps[methodName] ?? - (_, __) => GenericStep(methodName, line, testerType, testerName); + (_, __) => GenericStep( + methodName, + line, + testerType, + testerName, + hadDataTable, + ); return factory(package, line); } diff --git a/test/data_tables_test.dart b/test/data_tables_test.dart index 04f0280..20b1478 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/src/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/src/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/src/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/src/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/src/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..e1c1011 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/src/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, + ); + }); } From f8560865eee3829eddd2a38dccfa8c0f49617fc0 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:54:48 +0000 Subject: [PATCH 02/20] Added asLists function to data table --- lib/src/data_table.dart | 3 +++ test/data_table_test.dart | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 test/data_table_test.dart diff --git a/lib/src/data_table.dart b/lib/src/data_table.dart index dedd574..8468637 100644 --- a/lib/src/data_table.dart +++ b/lib/src/data_table.dart @@ -2,4 +2,7 @@ class DataTable { const DataTable(this._data); final List> _data; + + List> asLists({bool ignoreFirstRow = false}) => + _data.sublist(ignoreFirstRow ? 1 : 0, _data.length); } diff --git a/test/data_table_test.dart b/test/data_table_test.dart new file mode 100644 index 0000000..8af3918 --- /dev/null +++ b/test/data_table_test.dart @@ -0,0 +1,30 @@ +import 'package:bdd_widget_test/src/data_table.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('asLists with default ignoreFirstRow', () { + final data = [ + ['Country', 'City'], + ['England', 'London'], + ['England', 'Manchester'], + ]; + final dataTable = DataTable(data); + + final result = dataTable.asLists(); + + expect(result, data); + }); + + test('asLists with ignoreFirstRow as true', () { + final data = [ + ['Country', 'City'], + ['England', 'London'], + ['England', 'Manchester'], + ]; + final dataTable = DataTable(data); + + final result = dataTable.asLists(ignoreFirstRow: true); + + expect(result, data.skip(1)); + }); +} From 301b9fb3f5ca0a5daed9edacea7a8104d6078342 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:35:02 +0000 Subject: [PATCH 03/20] Added asMaps to data table --- lib/src/data_table.dart | 15 +++++++++++++++ test/data_table_test.dart | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/src/data_table.dart b/lib/src/data_table.dart index 8468637..2f413a9 100644 --- a/lib/src/data_table.dart +++ b/lib/src/data_table.dart @@ -1,3 +1,5 @@ +import 'package:collection/collection.dart'; + class DataTable { const DataTable(this._data); @@ -5,4 +7,17 @@ class DataTable { List> asLists({bool ignoreFirstRow = false}) => _data.sublist(ignoreFirstRow ? 1 : 0, _data.length); + + List> asMaps() { + final result = >[]; + final headers = _data.first; + _data.skip(1).forEach((row) { + final map = {}; + headers.forEachIndexed((index, header) { + map[header] = row[index]; + }); + result.add(map); + }); + return result; + } } diff --git a/test/data_table_test.dart b/test/data_table_test.dart index 8af3918..baa9ab1 100644 --- a/test/data_table_test.dart +++ b/test/data_table_test.dart @@ -27,4 +27,21 @@ void main() { expect(result, data.skip(1)); }); + + 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); + }); } From a99c8db170e5de5f3096118481e1fe75e2bd86b2 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Fri, 12 Jan 2024 21:03:21 +0000 Subject: [PATCH 04/20] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 55e2d6c..12d97e9 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,4 @@ pubspec.lock !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages coverage/lcov.info +/coverage/ From 943f4bd3eed77f9f67ca77e0198add4e5c64bb55 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:19:54 +0000 Subject: [PATCH 05/20] Update .gitignore Co-authored-by: Oleksandr Leushchenko <4376913+olexale@users.noreply.github.com> --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 12d97e9..5019a52 100644 --- a/.gitignore +++ b/.gitignore @@ -74,5 +74,4 @@ pubspec.lock !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -coverage/lcov.info /coverage/ From 727e3014c72670a486fe96fcd0c2044e43b673de Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:22:03 +0000 Subject: [PATCH 06/20] Update lib/src/data_table.dart Co-authored-by: Oleksandr Leushchenko <4376913+olexale@users.noreply.github.com> --- lib/src/data_table.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/data_table.dart b/lib/src/data_table.dart index 2f413a9..130d5bf 100644 --- a/lib/src/data_table.dart +++ b/lib/src/data_table.dart @@ -6,7 +6,7 @@ class DataTable { final List> _data; List> asLists({bool ignoreFirstRow = false}) => - _data.sublist(ignoreFirstRow ? 1 : 0, _data.length); + _data.sublist(ignoreFirstRow ? 1 : 0); List> asMaps() { final result = >[]; From 68361cda34b5bafba1151d62a0e10673991193d7 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:25:02 +0000 Subject: [PATCH 07/20] Update lib/src/data_table.dart Co-authored-by: Oleksandr Leushchenko <4376913+olexale@users.noreply.github.com> --- lib/src/data_table.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/src/data_table.dart b/lib/src/data_table.dart index 130d5bf..e0113ff 100644 --- a/lib/src/data_table.dart +++ b/lib/src/data_table.dart @@ -9,15 +9,13 @@ class DataTable { _data.sublist(ignoreFirstRow ? 1 : 0); List> asMaps() { - final result = >[]; final headers = _data.first; - _data.skip(1).forEach((row) { + return _data.skip(1).map((row) { final map = {}; headers.forEachIndexed((index, header) { map[header] = row[index]; }); - result.add(map); - }); - return result; + return map; + }).toList(); } } From 025913ee319374d4a1dc5171043c85d17084ed14 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:30:40 +0000 Subject: [PATCH 08/20] Replaced static functions with regular function --- lib/src/data_table_parser.dart | 123 ++++++++++++++++----------------- lib/src/feature_file.dart | 7 +- lib/src/feature_generator.dart | 4 +- 3 files changed, 66 insertions(+), 68 deletions(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index e12c8ab..9994c09 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -2,78 +2,75 @@ 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'; -abstract class DataTableParser { - static bool hasBddDataTable(List lines) { - for (var index = 0; index < lines.length; index++) { - final isStep = lines[index].type == LineType.step; - final isNextLineTable = isNextTable(lines: lines, index: index + 1); - final isExamplesFormatted = hasExamplesFormat(bddLine: lines[index]); - if (isStep && isNextLineTable && !isExamplesFormatted) { - return true; - } +bool hasBddDataTable(List lines) { + for (var index = 0; index < lines.length; index++) { + final isStep = lines[index].type == LineType.step; + final isNextLineTable = isNextTable(lines: lines, index: index + 1); + final isExamplesFormatted = hasExamplesFormat(bddLine: lines[index]); + if (isStep && isNextLineTable && !isExamplesFormatted) { + return true; } - return false; } + return false; +} - static Iterable replaceDataTables(List lines) sync* { - for (var index = 0; index < lines.length; index++) { - final isStep = lines[index].type == LineType.step; - final isNextLineTable = isNextTable(lines: lines, index: index + 1); - if (isStep && isNextLineTable) { - if (!hasExamplesFormat(bddLine: lines[index])) { - // Cucumber data table - final text = lines[index].value; - final table = List>.empty(growable: true); - do { - table.add(_createRow(bddLine: lines[++index])); - } while (isNextTable(lines: lines, index: index + 1)); - yield BddLine.fromValue( - LineType.step, - '$text {const bdd.DataTable($table)}', - ); - } else { - // Data table formatted as examples - 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, - ]); +Iterable replaceDataTables(List lines) sync* { + for (var index = 0; index < lines.length; index++) { + final isStep = lines[index].type == LineType.step; + final isNextLineTable = isNextTable(lines: lines, index: index + 1); + if (isStep && isNextLineTable) { + if (!hasExamplesFormat(bddLine: lines[index])) { +// Cucumber data table + final text = lines[index].value; + final table = List>.empty(growable: true); + do { + table.add(_createRow(bddLine: lines[++index])); + } while (isNextTable(lines: lines, index: index + 1)); + yield BddLine.fromValue( + LineType.step, + '$text {const bdd.DataTable($table)}', + ); + } else { +// Data table formatted as examples + 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]; - } + for (final item in data) { + yield item[1]; } - } else { - yield lines[index]; } + } else { + yield lines[index]; } } +} - static bool isNextTable({ - required List lines, - required int index, - }) => - index < lines.length && _isTable(bddLine: lines[index]); +bool isNextTable({ + required List lines, + required int index, +}) => + index < lines.length && _isTable(bddLine: lines[index]); - static bool _isTable({required BddLine bddLine}) => - bddLine.type == LineType.examples; +bool _isTable({required BddLine bddLine}) => bddLine.type == LineType.examples; - static bool hasExamplesFormat({required BddLine bddLine}) => - examplesRegExp.allMatches(bddLine.rawLine).isNotEmpty; +bool hasExamplesFormat({required BddLine bddLine}) => + examplesRegExp.allMatches(bddLine.rawLine).isNotEmpty; - static List _createRow({ - required BddLine bddLine, - }) => - List.unmodifiable( - bddLine.value - .split('|') - .map((example) => example.trim()) - .takeWhile((value) => value.isNotEmpty) - .toList(), - ); -} +List _createRow({ + required BddLine bddLine, +}) => + List.unmodifiable( + bddLine.value + .split('|') + .map((example) => example.trim()) + .takeWhile((value) => value.isNotEmpty) + .toList(), + ); diff --git a/lib/src/feature_file.dart b/lib/src/feature_file.dart index f9249cc..5cae834 100644 --- a/lib/src/feature_file.dart +++ b/lib/src/feature_file.dart @@ -1,5 +1,6 @@ import 'package:bdd_widget_test/src/bdd_line.dart'; -import 'package:bdd_widget_test/src/data_table_parser.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'; @@ -73,10 +74,10 @@ class FeatureFile { final lines = input.mapIndexed( (index, bddLine) { final isStep = bddLine.type == LineType.step; - final hasExamplesFormat = DataTableParser.hasExamplesFormat( + final hasExamplesFormat = data_table_parser.hasExamplesFormat( bddLine: bddLine, ); - final isNextTable = DataTableParser.isNextTable( + final isNextTable = data_table_parser.isNextTable( lines: input.toList(), index: index + 1, ); diff --git a/lib/src/feature_generator.dart b/lib/src/feature_generator.dart index 5cc6f7a..e801235 100644 --- a/lib/src/feature_generator.dart +++ b/lib/src/feature_generator.dart @@ -48,7 +48,7 @@ String generateFeatureDart( if (tags.isNotEmpty) { sb.writeln("@Tags(['${tags.join("', '")}'])"); } - if (DataTableParser.hasBddDataTable(lines)) { + if (hasBddDataTable(lines)) { sb.writeln("import 'package:bdd_widget_test/src/data_table.dart' as bdd;"); } sb.writeln("import 'package:flutter/material.dart';"); @@ -178,7 +178,7 @@ void _parseFeature( scenarioParamsTag, ); - final flattenDataTables = DataTableParser.replaceDataTables( + final flattenDataTables = replaceDataTables( scenario.skipWhile((line) => line.type == LineType.tag).toList(), ).toList(); final scenariosToParse = flattenDataTables.first.type == LineType.scenario From 7ec8961ef78baf73ea35f86a529bcb1ba4c66cf8 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:31:11 +0000 Subject: [PATCH 09/20] Update lib/src/data_table_parser.dart Co-authored-by: Oleksandr Leushchenko <4376913+olexale@users.noreply.github.com> --- lib/src/data_table_parser.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index e12c8ab..de5954f 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -23,7 +23,7 @@ abstract class DataTableParser { if (!hasExamplesFormat(bddLine: lines[index])) { // Cucumber data table final text = lines[index].value; - final table = List>.empty(growable: true); + final table = >[]; do { table.add(_createRow(bddLine: lines[++index])); } while (isNextTable(lines: lines, index: index + 1)); From 38efd4e364b69cc1d5eb715d225b68a766e3d3a6 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:42:14 +0000 Subject: [PATCH 10/20] Extracted bodies to functions --- lib/src/data_table_parser.dart | 62 ++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index 9994c09..6042404 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -20,32 +20,9 @@ Iterable replaceDataTables(List lines) sync* { final isNextLineTable = isNextTable(lines: lines, index: index + 1); if (isStep && isNextLineTable) { if (!hasExamplesFormat(bddLine: lines[index])) { -// Cucumber data table - final text = lines[index].value; - final table = List>.empty(growable: true); - do { - table.add(_createRow(bddLine: lines[++index])); - } while (isNextTable(lines: lines, index: index + 1)); - yield BddLine.fromValue( - LineType.step, - '$text {const bdd.DataTable($table)}', - ); + yield* _createCucumberDataTable(lines: lines, index: index); } else { -// Data table formatted as examples - 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]; - } + yield* _createDataTableFromExamples(lines: lines, index: index); } } else { yield lines[index]; @@ -74,3 +51,38 @@ List _createRow({ .takeWhile((value) => value.isNotEmpty) .toList(), ); + +Iterable _createCucumberDataTable({ + required List lines, + required int index, +}) sync* { + final text = lines[index].value; + final table = List>.empty(growable: true); + do { + table.add(_createRow(bddLine: lines[++index])); + } while (isNextTable(lines: lines, index: index + 1)); + yield BddLine.fromValue( + LineType.step, + '$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]; + } +} From 4515e66eeca41f493ef6761f2f3d715c5e7166ee Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:46:38 +0000 Subject: [PATCH 11/20] Update data_table_parser.dart --- lib/src/data_table_parser.dart | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index 6042404..6c7882e 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -44,20 +44,18 @@ bool hasExamplesFormat({required BddLine bddLine}) => List _createRow({ required BddLine bddLine, }) => - List.unmodifiable( - bddLine.value - .split('|') - .map((example) => example.trim()) - .takeWhile((value) => value.isNotEmpty) - .toList(), - ); + 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 = List>.empty(growable: true); + final table = >[]; do { table.add(_createRow(bddLine: lines[++index])); } while (isNextTable(lines: lines, index: index + 1)); From 4997c6c47ccf982eaa59db95d2a1305d6c3e581a Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:47:56 +0000 Subject: [PATCH 12/20] Update lib/src/step/generic_step.dart Co-authored-by: Oleksandr Leushchenko <4376913+olexale@users.noreply.github.com> --- lib/src/step/generic_step.dart | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/src/step/generic_step.dart b/lib/src/step/generic_step.dart index 04303d6..a8656a6 100644 --- a/lib/src/step/generic_step.dart +++ b/lib/src/step/generic_step.dart @@ -19,13 +19,11 @@ class GenericStep implements BddStep { final bool hadDataTable; @override - String get content { - var result = ''; - if (hadDataTable) { - result += - "import 'package:bdd_widget_test/src/data_table.dart' as bdd;\n"; - } - return result += ''' + @override + String get content => + '${hadDataTable ? "import 'package:bdd_widget_test/src/data_table.dart' as bdd;\n" : ''}' + ''' +import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart'; /// Usage: $rawLine From 7da6de12bce908ebd8a48e35beccfe9508cddb9a Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:54:23 +0000 Subject: [PATCH 13/20] Update generic_step.dart --- lib/src/step/generic_step.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/src/step/generic_step.dart b/lib/src/step/generic_step.dart index a8656a6..77f551f 100644 --- a/lib/src/step/generic_step.dart +++ b/lib/src/step/generic_step.dart @@ -18,20 +18,17 @@ class GenericStep implements BddStep { final String customTesterName; final bool hadDataTable; - @override @override String get content => '${hadDataTable ? "import 'package:bdd_widget_test/src/data_table.dart' as bdd;\n" : ''}' ''' import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_test/flutter_test.dart'; /// Usage: $rawLine Future $methodName($testerType $customTesterName${_getMethodParameters(rawLine, hadDataTable)}) async { throw UnimplementedError(); } '''; - } String _getMethodParameters(String stepLine, bool hadDataTable) { if (hadDataTable) { From 5c60cc9907b1f026d07f28b9d29396bcefdd2611 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:03:21 +0000 Subject: [PATCH 14/20] Moved data table to the root lib folder --- example/test/songs_test.dart | 2 +- example/test/step/the_following_songs.dart | 2 +- lib/{src => }/data_table.dart | 0 lib/src/feature_generator.dart | 2 +- lib/src/step/generic_step.dart | 2 +- test/data_table_test.dart | 2 +- test/data_tables_test.dart | 10 +++++----- test/step/generic_step_test.dart | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) rename lib/{src => }/data_table.dart (100%) diff --git a/example/test/songs_test.dart b/example/test/songs_test.dart index 5033417..6589104 100644 --- a/example/test/songs_test.dart +++ b/example/test/songs_test.dart @@ -1,7 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: unused_import, directives_ordering -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/example/test/step/the_following_songs.dart b/example/test/step/the_following_songs.dart index dba6f83..1f85dfb 100644 --- a/example/test/step/the_following_songs.dart +++ b/example/test/step/the_following_songs.dart @@ -1,4 +1,4 @@ -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter_test/flutter_test.dart'; /// Usage: the following songs diff --git a/lib/src/data_table.dart b/lib/data_table.dart similarity index 100% rename from lib/src/data_table.dart rename to lib/data_table.dart diff --git a/lib/src/feature_generator.dart b/lib/src/feature_generator.dart index e801235..b4a171c 100644 --- a/lib/src/feature_generator.dart +++ b/lib/src/feature_generator.dart @@ -49,7 +49,7 @@ String generateFeatureDart( sb.writeln("@Tags(['${tags.join("', '")}'])"); } if (hasBddDataTable(lines)) { - sb.writeln("import 'package:bdd_widget_test/src/data_table.dart' as bdd;"); + 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';"); diff --git a/lib/src/step/generic_step.dart b/lib/src/step/generic_step.dart index 77f551f..9eda331 100644 --- a/lib/src/step/generic_step.dart +++ b/lib/src/step/generic_step.dart @@ -20,7 +20,7 @@ class GenericStep implements BddStep { @override String get content => - '${hadDataTable ? "import 'package:bdd_widget_test/src/data_table.dart' as bdd;\n" : ''}' + '${hadDataTable ? "import 'package:bdd_widget_test/data_table.dart' as bdd;\n" : ''}' ''' import 'package:flutter_test/flutter_test.dart'; diff --git a/test/data_table_test.dart b/test/data_table_test.dart index baa9ab1..7cbcecc 100644 --- a/test/data_table_test.dart +++ b/test/data_table_test.dart @@ -1,4 +1,4 @@ -import 'package:bdd_widget_test/src/data_table.dart'; +import 'package:bdd_widget_test/data_table.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { diff --git a/test/data_tables_test.dart b/test/data_tables_test.dart index 20b1478..6db852a 100644 --- a/test/data_tables_test.dart +++ b/test/data_tables_test.dart @@ -76,7 +76,7 @@ Feature: Testing feature // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: unused_import, directives_ordering -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -124,7 +124,7 @@ Feature: Testing feature // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: unused_import, directives_ordering -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -172,7 +172,7 @@ Feature: Testing feature // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: unused_import, directives_ordering -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -224,7 +224,7 @@ Feature: Testing feature // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: unused_import, directives_ordering -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -280,7 +280,7 @@ Feature: Testing feature // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: unused_import, directives_ordering -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/test/step/generic_step_test.dart b/test/step/generic_step_test.dart index e1c1011..1706a16 100644 --- a/test/step/generic_step_test.dart +++ b/test/step/generic_step_test.dart @@ -102,7 +102,7 @@ Feature: Testing feature '''; const expectedSteps = ''' -import 'package:bdd_widget_test/src/data_table.dart' as bdd; +import 'package:bdd_widget_test/data_table.dart' as bdd; import 'package:flutter_test/flutter_test.dart'; /// Usage: the following songs From 811ac72e87ce12ffb2ed98783d7d1c026645ecf1 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:09:15 +0000 Subject: [PATCH 15/20] Renamed function --- lib/src/data_table_parser.dart | 8 ++++---- lib/src/feature_file.dart | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index 6c7882e..22d0a62 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -5,7 +5,7 @@ import 'package:bdd_widget_test/src/scenario_generator.dart'; bool hasBddDataTable(List lines) { for (var index = 0; index < lines.length; index++) { final isStep = lines[index].type == LineType.step; - final isNextLineTable = isNextTable(lines: lines, index: index + 1); + final isNextLineTable = isTable(lines: lines, index: index + 1); final isExamplesFormatted = hasExamplesFormat(bddLine: lines[index]); if (isStep && isNextLineTable && !isExamplesFormatted) { return true; @@ -17,7 +17,7 @@ bool hasBddDataTable(List lines) { Iterable replaceDataTables(List lines) sync* { for (var index = 0; index < lines.length; index++) { final isStep = lines[index].type == LineType.step; - final isNextLineTable = isNextTable(lines: lines, index: index + 1); + final isNextLineTable = isTable(lines: lines, index: index + 1); if (isStep && isNextLineTable) { if (!hasExamplesFormat(bddLine: lines[index])) { yield* _createCucumberDataTable(lines: lines, index: index); @@ -30,7 +30,7 @@ Iterable replaceDataTables(List lines) sync* { } } -bool isNextTable({ +bool isTable({ required List lines, required int index, }) => @@ -58,7 +58,7 @@ Iterable _createCucumberDataTable({ final table = >[]; do { table.add(_createRow(bddLine: lines[++index])); - } while (isNextTable(lines: lines, index: index + 1)); + } while (isTable(lines: lines, index: index + 1)); yield BddLine.fromValue( LineType.step, '$text {const bdd.DataTable($table)}', diff --git a/lib/src/feature_file.dart b/lib/src/feature_file.dart index 5cae834..d974317 100644 --- a/lib/src/feature_file.dart +++ b/lib/src/feature_file.dart @@ -77,7 +77,7 @@ class FeatureFile { final hasExamplesFormat = data_table_parser.hasExamplesFormat( bddLine: bddLine, ); - final isNextTable = data_table_parser.isNextTable( + final isNextTable = data_table_parser.isTable( lines: input.toList(), index: index + 1, ); From 8b42acb73726c3f57f894a3893066a7e5d401e13 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:11:05 +0000 Subject: [PATCH 16/20] Update data_table_parser.dart --- lib/src/data_table_parser.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index 22d0a62..11b93d1 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -39,7 +39,7 @@ bool isTable({ bool _isTable({required BddLine bddLine}) => bddLine.type == LineType.examples; bool hasExamplesFormat({required BddLine bddLine}) => - examplesRegExp.allMatches(bddLine.rawLine).isNotEmpty; + examplesRegExp.firstMatch(bddLine.rawLine) != null; List _createRow({ required BddLine bddLine, From d62d9662512c72d3ff90f6f5def236aac0a08212 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:15:17 +0000 Subject: [PATCH 17/20] Update data_table_parser.dart --- lib/src/data_table_parser.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/data_table_parser.dart b/lib/src/data_table_parser.dart index 11b93d1..62b5d65 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -34,9 +34,7 @@ bool isTable({ required List lines, required int index, }) => - index < lines.length && _isTable(bddLine: lines[index]); - -bool _isTable({required BddLine bddLine}) => bddLine.type == LineType.examples; + index < lines.length && lines[index].type == LineType.examples; bool hasExamplesFormat({required BddLine bddLine}) => examplesRegExp.firstMatch(bddLine.rawLine) != null; From 940071be3436f2b95685629209537699cfb3d27f Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Sun, 21 Jan 2024 00:42:30 +0000 Subject: [PATCH 18/20] Fixed typo --- lib/src/step/generic_step.dart | 8 ++++---- lib/src/step_file.dart | 12 ++++++------ lib/src/step_generator.dart | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/src/step/generic_step.dart b/lib/src/step/generic_step.dart index 9eda331..df2f61f 100644 --- a/lib/src/step/generic_step.dart +++ b/lib/src/step/generic_step.dart @@ -9,23 +9,23 @@ class GenericStep implements BddStep { this.rawLine, this.testerType, this.customTesterName, - this.hadDataTable, + this.hasDataTable, ); final String rawLine; final String methodName; final String testerType; final String customTesterName; - final bool hadDataTable; + final bool hasDataTable; @override String get content => - '${hadDataTable ? "import 'package:bdd_widget_test/data_table.dart' as bdd;\n" : ''}' + '${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, hadDataTable)}) async { +Future $methodName($testerType $customTesterName${_getMethodParameters(rawLine, hasDataTable)}) async { throw UnimplementedError(); } '''; diff --git a/lib/src/step_file.dart b/lib/src/step_file.dart index dd46a5d..0ad715c 100644 --- a/lib/src/step_file.dart +++ b/lib/src/step_file.dart @@ -15,7 +15,7 @@ abstract class StepFile { GeneratorOptions generatorOptions, String testerTypeTagValue, String testerNameTagValue, - bool hadDataTable, + bool hasDataTable, ) { final file = '${getStepFilename(line)}.dart'; @@ -43,7 +43,7 @@ abstract class StepFile { line, testerTypeTagValue, testerNameTagValue, - hadDataTable, + hasDataTable, ); } @@ -59,7 +59,7 @@ abstract class StepFile { line, testerTypeTagValue, testerNameTagValue, - hadDataTable, + hasDataTable, ); } } @@ -72,7 +72,7 @@ class NewStepFile extends StepFile { this.line, this.testerType, this.testerName, - this.isDataTable, + this.hasDataTable, ) : super._(); final String package; @@ -80,13 +80,13 @@ class NewStepFile extends StepFile { final String filename; final String testerType; final String testerName; - final bool isDataTable; + final bool hasDataTable; String get dartContent => generateStepDart( package, line, testerType, testerName, - isDataTable, + hasDataTable, ); } diff --git a/lib/src/step_generator.dart b/lib/src/step_generator.dart index 83162fa..4fc604f 100644 --- a/lib/src/step_generator.dart +++ b/lib/src/step_generator.dart @@ -51,7 +51,7 @@ String generateStepDart( String line, String testerType, String customTesterName, - bool hadDataTable, + bool hasDataTable, ) { final methodName = getStepMethodName(line); @@ -61,7 +61,7 @@ String generateStepDart( line, testerType, customTesterName, - hadDataTable, + hasDataTable, ); return bddStep.content; } @@ -72,7 +72,7 @@ BddStep _getStep( String line, String testerType, String testerName, - bool hadDataTable, + bool hasDataTable, ) { //for now, predefined steps don't support testerType final factory = predefinedSteps[methodName] ?? @@ -81,7 +81,7 @@ BddStep _getStep( line, testerType, testerName, - hadDataTable, + hasDataTable, ); return factory(package, line); } From 4f37df6fc8a7bdfe445d6abbdefcbba2f2105049 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:26:13 +0000 Subject: [PATCH 19/20] Removed redundant flag --- lib/data_table.dart | 3 +-- test/data_table_test.dart | 15 +-------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/data_table.dart b/lib/data_table.dart index e0113ff..9977522 100644 --- a/lib/data_table.dart +++ b/lib/data_table.dart @@ -5,8 +5,7 @@ class DataTable { final List> _data; - List> asLists({bool ignoreFirstRow = false}) => - _data.sublist(ignoreFirstRow ? 1 : 0); + List> asLists() => _data; List> asMaps() { final headers = _data.first; diff --git a/test/data_table_test.dart b/test/data_table_test.dart index 7cbcecc..6dd7ed6 100644 --- a/test/data_table_test.dart +++ b/test/data_table_test.dart @@ -2,7 +2,7 @@ import 'package:bdd_widget_test/data_table.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - test('asLists with default ignoreFirstRow', () { + test('asLists', () { final data = [ ['Country', 'City'], ['England', 'London'], @@ -15,19 +15,6 @@ void main() { expect(result, data); }); - test('asLists with ignoreFirstRow as true', () { - final data = [ - ['Country', 'City'], - ['England', 'London'], - ['England', 'Manchester'], - ]; - final dataTable = DataTable(data); - - final result = dataTable.asLists(ignoreFirstRow: true); - - expect(result, data.skip(1)); - }); - test('asMaps', () { final data = [ ['id', 'isValid'], From 045899c26bcddd5e737392c1e50a536fe114c331 Mon Sep 17 00:00:00 2001 From: Ron Brosh <63312304+ron-brosh@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:28:42 +0000 Subject: [PATCH 20/20] Added data table step line type --- lib/src/bdd_line.dart | 7 +++---- lib/src/data_table_parser.dart | 8 +++++--- lib/src/feature_file.dart | 12 +++++++----- lib/src/feature_generator.dart | 12 +++++++++--- lib/src/step_file.dart | 14 +++++++------- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/src/bdd_line.dart b/lib/src/bdd_line.dart index b315a54..d04c3cd 100644 --- a/lib/src/bdd_line.dart +++ b/lib/src/bdd_line.dart @@ -4,16 +4,14 @@ 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; final LineType type; } -class DataTableBddLine extends BddLine { - DataTableBddLine(super.rawLine); -} - enum LineType { feature, background, @@ -21,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 62b5d65..41eeaae 100644 --- a/lib/src/data_table_parser.dart +++ b/lib/src/data_table_parser.dart @@ -4,7 +4,8 @@ import 'package:bdd_widget_test/src/scenario_generator.dart'; bool hasBddDataTable(List lines) { for (var index = 0; index < lines.length; index++) { - final isStep = lines[index].type == LineType.step; + 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) { @@ -16,7 +17,8 @@ bool hasBddDataTable(List lines) { Iterable replaceDataTables(List lines) sync* { for (var index = 0; index < lines.length; index++) { - final isStep = lines[index].type == LineType.step; + 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])) { @@ -58,7 +60,7 @@ Iterable _createCucumberDataTable({ table.add(_createRow(bddLine: lines[++index])); } while (isTable(lines: lines, index: index + 1)); yield BddLine.fromValue( - LineType.step, + LineType.dataTableStep, '$text {const bdd.DataTable($table)}', ); } diff --git a/lib/src/feature_file.dart b/lib/src/feature_file.dart index d974317..26894c7 100644 --- a/lib/src/feature_file.dart +++ b/lib/src/feature_file.dart @@ -32,17 +32,19 @@ 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, _testerName, - e is DataTableBddLine, ), ) .toList(); @@ -82,7 +84,7 @@ class FeatureFile { index: index + 1, ); if (isStep && !hasExamplesFormat && isNextTable) { - return DataTableBddLine(bddLine.rawLine); + return BddLine.fromRawValue(LineType.dataTableStep, bddLine.rawLine); } else { return bddLine; } diff --git a/lib/src/feature_generator.dart b/lib/src/feature_generator.dart index b4a171c..1b3bf59 100644 --- a/lib/src/feature_generator.dart +++ b/lib/src/feature_generator.dart @@ -141,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)};', ); @@ -189,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, @@ -239,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_file.dart b/lib/src/step_file.dart index 0ad715c..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,14 +11,13 @@ abstract class StepFile { static StepFile create( String featureDir, String package, - String line, + BddLine bddLine, Map existingSteps, GeneratorOptions generatorOptions, String testerTypeTagValue, String testerNameTagValue, - bool hasDataTable, ) { - final file = '${getStepFilename(line)}.dart'; + final file = '${getStepFilename(bddLine.value)}.dart'; if (existingSteps.containsKey(file)) { final import = @@ -40,10 +40,10 @@ abstract class StepFile { import, filename, package, - line, + bddLine.value, testerTypeTagValue, testerNameTagValue, - hasDataTable, + bddLine.type == LineType.dataTableStep, ); } @@ -56,10 +56,10 @@ abstract class StepFile { import, filename, package, - line, + bddLine.value, testerTypeTagValue, testerNameTagValue, - hasDataTable, + bddLine.type == LineType.dataTableStep, ); } }