Skip to content

Commit e4bc95e

Browse files
committed
Add support for custom headers in generated files
- Introduced `customHeaders` option in `GeneratorOptions` to allow custom imports and comments in generated step and feature files. - Updated relevant files to utilize the new `customHeaders` feature, replacing default imports when specified. - Enhanced documentation and examples to guide users on how to implement custom headers. - Bumped version to 2.0.1.
1 parent 4473fd4 commit e4bc95e

15 files changed

Lines changed: 226 additions & 27 deletions

.github/workflows/dart.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ jobs:
3434
run: dart pub global activate coverage
3535

3636
- name: 🧪 Run tests
37-
run: dart pub global run coverage:test_with_coverage
38-
39-
- name: 🎯 Check Code Coverage
40-
uses: VeryGoodOpenSource/very_good_coverage@v1
37+
run: dart pub global run coverage:test_with_coverage --fail-under 100
4138

4239
- name: 🥇 Update coverage badge
4340
if: github.event_name != 'pull_request'

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## [2.0.1] - Custom headers support
2+
3+
* Add `customHeaders` configuration option to include custom header lines (imports, comments, etc.) in all generated step files and feature files
4+
15
## [2.0.0] - Upgrade dependencies
26

37
* **BREAKING CHANGE**: The package doesn't provide pre-built steps anymore. Steps will appear in the `step` folder.

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,34 @@ targets:
315315
include: package:<your_package>/bdd_options.yaml
316316
```
317317

318+
### How to add custom headers to generated files?
319+
320+
You can add custom header lines (imports, comments, etc.) to all generated step files **and feature files** using the `customHeaders` option in the `build.yaml` file:
321+
```yaml
322+
targets:
323+
$default:
324+
builders:
325+
bdd_widget_test|featureBuilder:
326+
options:
327+
customHeaders:
328+
- "import 'package:flutter_test/flutter_test.dart';"
329+
- "// Custom test utilities"
330+
- "import 'package:my_custom_package/my_helper.dart';"
331+
```
332+
333+
This is useful when you need to:
334+
- Use custom test frameworks (like Patrol) instead of the default flutter_test
335+
- Import custom helper classes or utilities in all your generated files
336+
- Add specific packages that your tests will commonly use
337+
- Include custom test utilities, mocks, or constants
338+
- Add custom comments or documentation to generated files
339+
340+
**Important**: When `customHeaders` are provided, the default imports (`import 'package:flutter/material.dart';` and `import 'package:flutter_test/flutter_test.dart';`) are **not** automatically included in feature files, and the default `import 'package:flutter_test/flutter_test.dart';` is not included in step files. You have full control over what imports and content are added to your generated files.
341+
342+
The custom headers will be added to:
343+
- **Feature files**: After any data table imports, replacing the default flutter/material and flutter_test imports
344+
- **Step files**: After any data table imports, replacing the default flutter_test import
345+
318346
### How to group steps in a single project?
319347

320348
You may create sub-folders (like `common`, `login`, `home`, etc.) in the `step` folder and move generated steps there. The plugin is smart enough to find them (see the `example` folder).

example/bdd_options_example.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Example bdd_options.yaml file showing how to use customHeaders
2+
# This file can be referenced from build.yaml using the include option
3+
4+
# Add custom header lines that will be added to all generated step files
5+
customHeaders:
6+
- "import 'package:flutter_test/flutter_test.dart';"
7+
- "import 'package:mockito/mockito.dart';"
8+
- "import 'package:my_project/test_helpers.dart';"
9+
- "import 'package:my_project/mocks/database_mock.dart';"
10+
11+
# You can also include external steps from other packages
12+
externalSteps:
13+
- package:common_bdd_steps/step/i_wait.dart
14+
- package:common_bdd_steps/step/i_see_loading.dart

example/build.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ targets:
1515
# addHooks: true # if true, hooks will be added to the test; default is false
1616
# hookFolderName: bdd_hooks
1717
# include: package:<package1>/bdd_options.yaml # you may add defaul external steps with this line
18+
# customHeaders: # add custom header lines to all generated step files
19+
# - "import 'package:flutter_test/flutter_test.dart';"
20+
# - "import 'package:my_project/test_helpers.dart';"
1821
externalSteps: # or list only steps that you need
1922
# - package:<package2>/step/i_see_text.dart
2023
# - package:<package2>/step/i_dont_see_text.dart

lib/src/feature_file.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class FeatureFile {
8383
includeIntegrationTestBinding,
8484
includeIntegrationTestImport,
8585
hookFile,
86+
generatorOptions,
8687
);
8788

8889
List<StepFile> getStepFiles() => _stepFiles;

lib/src/feature_generator.dart

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:bdd_widget_test/src/bdd_line.dart';
22
import 'package:bdd_widget_test/src/data_table_parser.dart';
3+
import 'package:bdd_widget_test/src/generator_options.dart';
34
import 'package:bdd_widget_test/src/hook_file.dart';
45
import 'package:bdd_widget_test/src/scenario_generator.dart';
56
import 'package:bdd_widget_test/src/step_file.dart';
@@ -16,6 +17,7 @@ String generateFeatureDart(
1617
bool includeIntegrationTestBinding,
1718
bool includeIntegrationTestImport,
1819
HookFile? hookFile,
20+
GeneratorOptions generatorOptions,
1921
) {
2022
final sb = StringBuffer();
2123
sb.writeln('// GENERATED CODE - DO NOT MODIFY BY HAND');
@@ -59,8 +61,17 @@ String generateFeatureDart(
5961
if (hasBddDataTable(lines)) {
6062
sb.writeln("import 'package:bdd_widget_test/data_table.dart' as bdd;");
6163
}
62-
sb.writeln("import 'package:flutter/material.dart';");
63-
sb.writeln("import 'package:flutter_test/flutter_test.dart';");
64+
65+
// Use custom headers if provided, otherwise use default imports
66+
if (generatorOptions.customHeaders.isNotEmpty) {
67+
for (final header in generatorOptions.customHeaders) {
68+
sb.writeln(header);
69+
}
70+
} else {
71+
sb.writeln("import 'package:flutter/material.dart';");
72+
sb.writeln("import 'package:flutter_test/flutter_test.dart';");
73+
}
74+
6475
if (includeIntegrationTestImport) {
6576
sb.writeln("import 'package:integration_test/integration_test.dart';");
6677
}

lib/src/generator_options.dart

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class GeneratorOptions {
2020
String? hookFolderName,
2121
this.include,
2222
bool? includeIntegrationTestBinding,
23+
List<String>? customHeaders,
2324
}) : stepFolder = stepFolderName ?? _stepFolderName,
2425
relativeToTestFolder = relativeToTestFolder ?? true,
2526
testMethodName = testMethodName ?? _defaultTestMethodName,
@@ -28,24 +29,26 @@ class GeneratorOptions {
2829
addHooks = addHooks ?? false,
2930
hookFolderName = hookFolderName ?? _hookFolderName,
3031
externalSteps = externalSteps ?? const [],
31-
includeIntegrationTestBinding = includeIntegrationTestBinding ?? true;
32+
includeIntegrationTestBinding = includeIntegrationTestBinding ?? true,
33+
customHeaders = customHeaders ?? const [];
3234

3335
factory GeneratorOptions.fromMap(Map<String, dynamic> json) =>
3436
GeneratorOptions(
35-
testMethodName: json['testMethodName'] as String?,
36-
testerType: json['testerType'] as String?,
37-
testerName: json['testerName'] as String?,
38-
externalSteps: (json['externalSteps'] as List?)?.cast<String>(),
39-
stepFolderName: json['stepFolderName'] as String?,
40-
relativeToTestFolder: json['relativeToTestFolder'] as bool?,
41-
addHooks: json['addHooks'] as bool?,
42-
hookFolderName: json['hookFolderName'] as String?,
43-
include: json['include'] is String
44-
? [(json['include'] as String)]
45-
: (json['include'] as List?)?.cast<String>(),
46-
includeIntegrationTestBinding:
47-
json['includeIntegrationTestBinding'] as bool?,
48-
);
37+
testMethodName: json['testMethodName'] as String?,
38+
testerType: json['testerType'] as String?,
39+
testerName: json['testerName'] as String?,
40+
externalSteps: (json['externalSteps'] as List?)?.cast<String>(),
41+
stepFolderName: json['stepFolderName'] as String?,
42+
relativeToTestFolder: json['relativeToTestFolder'] as bool?,
43+
addHooks: json['addHooks'] as bool?,
44+
hookFolderName: json['hookFolderName'] as String?,
45+
include: json['include'] is String
46+
? [(json['include'] as String)]
47+
: (json['include'] as List?)?.cast<String>(),
48+
includeIntegrationTestBinding:
49+
json['includeIntegrationTestBinding'] as bool?,
50+
customHeaders:
51+
(json['customHeaders'] as List?)?.cast<String>() ?? []);
4952

5053
final String stepFolder;
5154
final bool relativeToTestFolder;
@@ -57,6 +60,7 @@ class GeneratorOptions {
5760
final List<String>? include;
5861
final List<String> externalSteps;
5962
final bool includeIntegrationTestBinding;
63+
final List<String> customHeaders;
6064
}
6165

6266
Future<GeneratorOptions> flattenOptions(GeneratorOptions options) async {
@@ -109,4 +113,5 @@ GeneratorOptions merge(GeneratorOptions a, GeneratorOptions b) =>
109113
include: b.include,
110114
includeIntegrationTestBinding:
111115
a.includeIntegrationTestBinding || b.includeIntegrationTestBinding,
116+
customHeaders: [...a.customHeaders, ...b.customHeaders],
112117
);

lib/src/step/generic_step.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:bdd_widget_test/src/generator_options.dart';
12
import 'package:bdd_widget_test/src/regex.dart';
23
import 'package:bdd_widget_test/src/step/bdd_step.dart';
34
import 'package:bdd_widget_test/src/step_generator.dart';
@@ -10,25 +11,33 @@ class GenericStep implements BddStep {
1011
this.testerType,
1112
this.customTesterName,
1213
this.hasDataTable,
14+
this.generatorOptions,
1315
);
1416

1517
final String rawLine;
1618
final String methodName;
1719
final String testerType;
1820
final String customTesterName;
1921
final bool hasDataTable;
22+
final GeneratorOptions generatorOptions;
2023

2124
@override
22-
String get content =>
23-
'${hasDataTable ? "import 'package:bdd_widget_test/data_table.dart' as bdd;\n" : ''}'
24-
'''
25-
import 'package:flutter_test/flutter_test.dart';
25+
String get content {
26+
final hasCustomHeaders = generatorOptions.customHeaders.isNotEmpty;
27+
final headerSection = hasCustomHeaders
28+
? generatorOptions.customHeaders.join('\n')
29+
: "import 'package:flutter_test/flutter_test.dart';";
30+
31+
return '${hasDataTable ? "import 'package:bdd_widget_test/data_table.dart' as bdd;\n" : ''}'
32+
'''
33+
$headerSection
2634
2735
/// Usage: $rawLine
2836
Future<void> $methodName($testerType $customTesterName${_getMethodParameters(rawLine, hasDataTable)}) async {
2937
throw UnimplementedError();
3038
}
3139
''';
40+
}
3241

3342
String _getMethodParameters(String stepLine, bool hadDataTable) {
3443
final params = parseRawStepLine(stepLine).skip(1);

lib/src/step_file.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ abstract class StepFile {
4545
testerTypeTagValue,
4646
testerNameTagValue,
4747
bddLine.type == LineType.dataTableStep,
48+
generatorOptions,
4849
);
4950
}
5051

@@ -67,6 +68,7 @@ abstract class StepFile {
6768
testerTypeTagValue,
6869
testerNameTagValue,
6970
bddLine.type == LineType.dataTableStep,
71+
generatorOptions,
7072
);
7173
}
7274
}
@@ -80,6 +82,7 @@ class NewStepFile extends StepFile {
8082
this.testerType,
8183
this.testerName,
8284
this.hasDataTable,
85+
this.generatorOptions,
8386
) : super._();
8487

8588
final String package;
@@ -88,12 +91,14 @@ class NewStepFile extends StepFile {
8891
final String testerType;
8992
final String testerName;
9093
final bool hasDataTable;
94+
final GeneratorOptions generatorOptions;
9195
String get dartContent => generateStepDart(
9296
package,
9397
line,
9498
testerType,
9599
testerName,
96100
hasDataTable,
101+
generatorOptions,
97102
);
98103
}
99104

0 commit comments

Comments
 (0)