Skip to content

Commit 7c104ba

Browse files
committed
Failure count on format
1 parent 0994cff commit 7c104ba

File tree

6 files changed

+77
-43
lines changed

6 files changed

+77
-43
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/.idea
2+
/.vscode

README.md

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,29 +54,42 @@ Gherkin Utils is [available on Maven Central](https://central.sonatype.com/artif
5454

5555
## Command line
5656

57+
```bash
58+
-> npx @cucumber/gherkin-utils format features
59+
❌ 7 files failed to format
60+
🥒 14 files left unchanged
61+
🥒 25 files reformatted
62+
```
63+
5764
To run Gherkin Utils as a formatter, try any of the following:
5865

59-
```console
66+
```bash
6067
# Format `file.feature`
6168
npx @cucumber/gherkin-utils format features/file.feature
69+
# Format `one.feature` and `two.feature`
70+
npx @cucumber/gherkin-utils format features/one.feature features/two.feature
6271
# Format all feature files in `features/` (and any subdirectories)
6372
npx @cucumber/gherkin-utils format features/
73+
# Format all feature files ending with `_test.feature` in `features`
74+
npx @cucumber/gherkin-utils format features/**/*_test.feature
6475
# Check files that would be reformatted in `features/`
6576
npx @cucumber/gherkin-utils format --check features/
6677
# Check files that would be reformatted in `features/` and output the diff
6778
npx @cucumber/gherkin-utils format --diff features/
6879
```
6980

70-
The following example translates all `.feature` files to `.feature.md` files and then deletes the `.feature` files (see [Markdown with Gherkin](https://github.com/cucumber/common/blob/main/gherkin/MARKDOWN_WITH_GHERKIN.md)).
71-
**Note**: Globs must be quoted to prevent the shell from expanding the globs.
81+
To convert to [Markdown with Gherkin](https://github.com/cucumber/common/blob/main/gherkin/MARKDOWN_WITH_GHERKIN.md) or feature files while formatting, try the following:
7282

73-
```console
74-
npx @cucumber/gherkin-utils format --move "features/**/*.feature" "features/**/*.feature.md"
83+
```bash
84+
# Format all feature files in `features/` (and any subdirectories) and convert to gherkin markdown
85+
npx @cucumber/gherkin-utils format --to-syntax=markdown features/
86+
# Format all feature files in `features/` (and any subdirectories) and convert to gherkin
87+
npx @cucumber/gherkin-utils format --to-syntax=gherkin features/
7588
```
7689

7790
For more details on usage, see the help menu.
7891

79-
```console
92+
```bash
8093
npx @cucumber/gherkin-utils --help
8194
```
8295

@@ -89,35 +102,31 @@ This module can also be used as a library. It provides two main utilities, `pret
89102
This function takes a GherkinDocument as input and returns a pretty-printed representation in Gherkin or Markdown.
90103

91104
```javascript
92-
import {
93-
AstBuilder,
94-
GherkinClassicTokenMatcher,
95-
Parser,
96-
} from "@cucumber/gherkin";
97-
import { pretty } from "@cucumber/gherkin-utils";
98-
import { IdGenerator } from "@cucumber/messages";
105+
import { AstBuilder, GherkinClassicTokenMatcher,Parser } from "@cucumber/gherkin";
106+
import { pretty } from "@cucumber/gherkin-utils"
107+
import { IdGenerator } from "@cucumber/messages"
99108

100-
const uuidFn = IdGenerator.uuid();
109+
const uuidFn = IdGenerator.uuid()
101110

102-
const builder = new AstBuilder(uuidFn);
103-
const matcher = new GherkinClassicTokenMatcher();
104-
const parser = new Parser(builder, matcher);
111+
const builder = new AstBuilder(uuidFn)
112+
const matcher = new GherkinClassicTokenMatcher()
113+
const parser = new Parser(builder, matcher)
105114

106115
const feature = `Feature:
107116
Scenario:
108-
Given step text`;
117+
Given step text`
109118

110-
const gherkinDocument = parser.parse(feature);
119+
const gherkinDocument = parser.parse(feature)
111120

112-
const formattedGherkinFeature = pretty(gherkinDocument);
121+
const formattedGherkinFeature = pretty(gherkinDocument)
113122
/*
114123
Feature:
115124
116125
Scenario:
117126
Given step text
118127
119128
*/
120-
const formattedGherkinMarkdownFeature = pretty(gherkinDocument, "markdown");
129+
const formattedGherkinMarkdownFeature = pretty(gherkinDocument, "markdown")
121130
/*
122131
# Feature:
123132
@@ -147,16 +156,13 @@ By default, all elements are accepted, which means that if you want to do filter
147156
Here's an example:
148157

149158
```typescript
150-
import {
151-
GherkinDocumentWalker,
152-
rejectAllFilters,
153-
} from "@cucumber/gherkin-utils";
159+
import { GherkinDocumentWalker, rejectAllFilters } from "@cucumber/gherkin-utils"
154160

155161
// Only keeps scenarios which name include 'magic'
156162
const filter = new GherkinDocumentWalker({
157163
...rejectAllFilters,
158164
...{ acceptScenario: (scenario) => scenario.name.includes("magic") },
159-
});
165+
})
160166

161167
// Makes a list with all the scenario names
162168
const allScenarioNames: string[] = [];
@@ -165,7 +171,7 @@ const scenarioNameFinder = new GherkinDocumentWalker(
165171
{
166172
handleScenario: (scenario) => allScenarioNames.push(scenario.name),
167173
}
168-
);
174+
)
169175
```
170176

171177
## Feedback

javascript/features/file.feature

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Feature:
2+
3+
Scenario:
4+
Given something

javascript/features/fqile.feature

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Feature:
2+
3+
Scenario:
4+
Given something

javascript/src/cli.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ import { formatCommand, FormatOptions } from './commands/formatCommand'
66
const program = new Command()
77
program.version(version)
88

9-
// TODO: Default to running against the `features` directory
9+
const fileFormats = ['gherkin', 'markdown']
10+
11+
// TODO: Default to running against the `features` directory?
1012
program
1113
.command('format')
12-
.arguments('[paths...]')
14+
.argument(
15+
'[paths...]',
16+
'One or more .feature or .feature.md files, or directories containing such files'
17+
)
1318
.option(
1419
'--check',
1520
'Avoid writing any formatted files back; instead, exit with a non-zero status code if any files would have been modified, and zero otherwise'
@@ -19,15 +24,11 @@ program
1924
'Avoid writing any formatted files back; instead, output a diff of changes that would be made and exit with a non-zero status code if any files would have been modified, and zero otherwise'
2025
)
2126
.option('-l, --language <ISO 639-1>', 'specify the language (dialect) of the source')
22-
.addOption(new Option('-f, --from-syntax <syntax>', 'from syntax').choices(['gherkin', 'markdown']))
23-
.addOption(new Option('-t, --to-syntax <syntax>', 'to syntax').choices(['gherkin', 'markdown'])
24-
)
27+
// TODO: Deprecate `--from-syntax`
28+
.addOption(new Option('-f, --from-syntax <syntax>', 'from syntax').choices(fileFormats))
29+
.addOption(new Option('-t, --to-syntax <syntax>', 'to syntax').choices(fileFormats))
2530
.description(
26-
`Formats one or more files or directories. STDIN is formatted and written to STDOUT (assuming gherkin syntax by default)`,
27-
{
28-
paths:
29-
'One or more .feature or .feature.md files, or directories containing such files',
30-
}
31+
`Formats one or more files or directories. STDIN is formatted and written to STDOUT (assuming gherkin syntax by default)`
3132
)
3233
.action(async (files: string[], options: FormatOptions) => {
3334
await formatCommand(files, process.stdin.isTTY ? null : process.stdin, process.stdout, options)

javascript/src/commands/formatCommand.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import {
55
Parser,
66
} from '@cucumber/gherkin'
77
import * as messages from '@cucumber/messages'
8+
import * as diff from 'diff'
89
import fs, { unlink as unlinkCb } from 'fs'
910
import path from 'path'
1011
import { Readable, Writable } from 'stream'
1112
import { promisify } from 'util'
12-
import * as diff from 'diff'
13+
1314
import pretty, { Syntax } from '../pretty'
1415

1516
const unlink = promisify(unlinkCb)
@@ -31,6 +32,8 @@ type FileFormat = {
3132
}
3233

3334
// TODO: Support `.md` files
35+
// TODO: Support globs
36+
// TODO: Ignore conversion failures
3437
function getFeatureFiles(filePath: string): string[] {
3538
const stat = fs.statSync(filePath)
3639
let files: string[] = []
@@ -82,17 +85,31 @@ export async function formatCommand(
8285

8386
let unchangedCount = 0
8487
let reformatCount = 0
88+
let failuresCount = 0
8589

8690
for (const fileFormat of fileFormats) {
87-
const wouldBeReformatted = await convert(fileFormat, options.language, options)
88-
wouldBeReformatted ? reformatCount++ : unchangedCount++
91+
try {
92+
const wouldBeReformatted = await convert(fileFormat, options.language, options)
93+
wouldBeReformatted ? reformatCount++ : unchangedCount++
94+
} catch (error) {
95+
// TODO: Include file path
96+
failuresCount++
97+
console.error(`Failed to convert file: ${error.message}`)
98+
}
99+
}
100+
101+
if (failuresCount > 0) {
102+
console.error(`❌ ${failuresCount} file${getPlural(failuresCount)} failed to format`)
89103
}
90104
if (unchangedCount > 0) {
91-
console.log(`${unchangedCount} file${getPlural(unchangedCount)} left unchanged`)
105+
console.log(`🥒 ${unchangedCount} file${getPlural(unchangedCount)} left unchanged`)
92106
}
93107
if (reformatCount > 0) {
94108
const tense = options.check ? 'would be ' : ''
95-
console.log(`${reformatCount} file${getPlural(reformatCount)} ${tense}reformatted`)
109+
console.log(`🥒 ${reformatCount} file${getPlural(reformatCount)} ${tense}reformatted`)
110+
process.exit(1)
111+
}
112+
if (failuresCount > 0) {
96113
process.exit(1)
97114
}
98115
}
@@ -106,7 +123,7 @@ async function convert(fileFormat: FileFormat, language: string, options: Format
106123
parse(output, fileFormat.writableSyntax, gherkinDocument.feature?.language)
107124
} catch (err) {
108125
err.message += `The generated output is not parseable. This is a bug.
109-
Please report a bug at https://github.com/cucumber/common/issues/new
126+
Please report a bug at https://github.com/cucumber/gherkin/issues
110127
111128
--- Generated ${fileFormat.writableSyntax} source ---
112129
${output}
@@ -127,6 +144,7 @@ ${output}
127144
if (options.diff) {
128145
const differences = diff.createPatch('filename.feature', source, output)
129146
console.log(differences)
147+
return true
130148
}
131149

132150
const writable = fileFormat.writable()

0 commit comments

Comments
 (0)