Skip to content

Commit

Permalink
Base64 encode string literals in JsonFormatter (#2261)
Browse files Browse the repository at this point in the history
Co-authored-by: David Goss <david@davidgoss.co>
  • Loading branch information
badeball and davidjgoss authored Oct 7, 2023
1 parent 188d644 commit 26431b1
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Please see [CONTRIBUTING.md](./CONTRIBUTING.md) on how to contribute to Cucumber
### Removed
- BREAKING CHANGE: Drop support for Node.js 14, 16 and 19 ([#2331](https://github.com/cucumber/cucumber-js/pull/2331))

### Fixed
- Ensure attached string literals are base64-encoded in JSON reports ([#2260](https://github.com/cucumber/cucumber-js/issues/2260))

## [9.6.0] - 2023-10-07
### Fixed
- Improve handling of formatter paths ([#2315](https://github.com/cucumber/cucumber-js/pull/2315))
Expand Down
6 changes: 5 additions & 1 deletion src/formatter/json_formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,11 @@ export default class JsonFormatter extends Formatter {
}
if (testStepAttachments?.length > 0) {
data.embeddings = testStepAttachments.map((attachment) => ({
data: attachment.body,
data:
attachment.contentEncoding ===
messages.AttachmentContentEncoding.IDENTITY
? Buffer.from(attachment.body).toString('base64')
: attachment.body,
mime_type: attachment.mediaType,
}))
}
Expand Down
74 changes: 70 additions & 4 deletions src/formatter/json_formatter_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ describe('JsonFormatter', () => {
keyword: 'Given ',
line: 3,
match: {
location: 'json_formatter_steps.ts:39',
location: 'json_formatter_steps.ts:56',
},
name: 'a passing step',
result: {
Expand All @@ -261,15 +261,15 @@ describe('JsonFormatter', () => {
})
})

describe('with attachments', () => {
it('outputs the step with embeddings', async function () {
describe('with attachments (buffer)', () => {
it('outputs the step with embeddings (preserving base64 encoding)', async function () {
// Arrange
const sources = [
{
data: [
'Feature: my feature',
' Scenario: my scenario',
' Given a step that attaches',
' Given a step that attaches buffer (image/png)',
].join('\n'),
uri: 'a.feature',
},
Expand All @@ -294,6 +294,72 @@ describe('JsonFormatter', () => {
})
})

describe('with attachments (bas64-encoded string)', () => {
it('outputs the step with embeddings (preserving base64 encoding)i', async function () {
// Arrange
const sources = [
{
data: [
'Feature: my feature',
' Scenario: my scenario',
' Given a step that attaches base64-encoded string',
].join('\n'),
uri: 'a.feature',
},
]

const supportCodeLibrary = getJsonFormatterSupportCodeLibrary(clock)

// Act
const output = await testFormatter({
sources,
supportCodeLibrary,
type: 'json',
})

const steps = JSON.parse(output)[0].elements[0].steps
expect(steps[0].embeddings).to.deep.eq([
{
data: 'Zm9v',
mime_type: 'text/plain',
},
])
})
})

describe('with attachments (string literal)', () => {
it('outputs the step with embeddings (base64-encoded)', async function () {
// Arrange
const sources = [
{
data: [
'Feature: my feature',
' Scenario: my scenario',
' Given a step that attaches string literal',
].join('\n'),
uri: 'a.feature',
},
]

const supportCodeLibrary = getJsonFormatterSupportCodeLibrary(clock)

// Act
const output = await testFormatter({
sources,
supportCodeLibrary,
type: 'json',
})

const steps = JSON.parse(output)[0].elements[0].steps
expect(steps[0].embeddings).to.deep.eq([
{
data: 'Zm9v',
mime_type: 'text/plain',
},
])
})
})

describe('with a doc string', () => {
it('outputs the doc string as a step argument', async () => {
// Arrange
Expand Down
21 changes: 19 additions & 2 deletions test/fixtures/json_formatter_steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,25 @@ export function getJsonFormatterSupportCodeLibrary(
throw 'error' // eslint-disable-line @typescript-eslint/no-throw-literal
})

Given('a step that attaches', async function (this: World) {
await this.attach(Buffer.from([137, 80, 78, 71]), 'image/png')
Given(
'a step that attaches buffer \\(image\\/png)',
async function (this: World) {
await this.attach(Buffer.from([137, 80, 78, 71]), 'image/png')
}
)

Given(
'a step that attaches base64-encoded string',
async function (this: World) {
await this.attach(
Buffer.from('foo').toString('base64'),
'base64:text/plain'
)
}
)

Given('a step that attaches string literal', async function (this: World) {
await this.attach('foo', 'text/plain')
})

Given('a step {int}', function (_int: Number) {})
Expand Down

0 comments on commit 26431b1

Please sign in to comment.