From 4c8288b14294ee59a6c127d3cefd3ccbf06e71cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 14 Jun 2022 20:46:55 +0100 Subject: [PATCH 1/4] Incremental rendering of HTML report --- javascript/.gitignore | 14 +--------- javascript/html/.gitkeep | 0 javascript/package.json | 2 +- javascript/src/CucumberHtmlStream.ts | 22 +++++----------- javascript/src/index.mustache.html | 7 ++--- javascript/src/main.tsx | 31 +++++++++++++---------- javascript/test/CucumberHtmlStreamTest.ts | 19 +++----------- javascript/test/acceptance.ts | 9 ++++--- javascript/test/dummy.css | 1 + javascript/test/dummy.js | 1 + 10 files changed, 41 insertions(+), 65 deletions(-) create mode 100644 javascript/html/.gitkeep diff --git a/javascript/.gitignore b/javascript/.gitignore index 571a56f3..122125c4 100644 --- a/javascript/.gitignore +++ b/javascript/.gitignore @@ -1,17 +1,5 @@ dist/ .idea/ -.nyc_output/ -coverage/ node_modules/ -*.log -.deps -.tested* -.linted -.built* -.compared -.codegen -acceptance/ -storybook-static -*-go *.iml -.vscode-test +html/ diff --git a/javascript/html/.gitkeep b/javascript/html/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/javascript/package.json b/javascript/package.json index 9234a4c5..1ca3c32c 100644 --- a/javascript/package.json +++ b/javascript/package.json @@ -6,7 +6,7 @@ "types": "dist/src/CucumberHtmlStream.d.ts", "repository": { "type": "git", - "url": "git+https://github.com/cucumber/cucumber.git" + "url": "git+https://github.com/cucumber/cucumber-html.git" }, "author": "Aslak Hellesøy", "license": "MIT", diff --git a/javascript/src/CucumberHtmlStream.ts b/javascript/src/CucumberHtmlStream.ts index f349a575..115e246a 100644 --- a/javascript/src/CucumberHtmlStream.ts +++ b/javascript/src/CucumberHtmlStream.ts @@ -47,9 +47,12 @@ export default class CucumberHtmlStream extends Transform { if (err) return callback(err) this.writeFile(this.cssPath, (err) => { if (err) return callback(err) - this.writeTemplateBetween('{{css}}', '{{messages}}', (err) => { + this.writeTemplateBetween('{{css}}', '{{script}}', (err) => { if (err) return callback(err) - callback() + this.writeFile(this.jsPath, (err) => { + if (err) return callback(err) + this.writeTemplateBetween('{{script}}', '{{messages}}', callback) + }) }) }) }) @@ -58,13 +61,7 @@ export default class CucumberHtmlStream extends Transform { private writePostMessage(callback: TransformCallback) { this.writePreMessageUnlessAlreadyWritten((err) => { if (err) return callback(err) - this.writeTemplateBetween('{{messages}}', '{{script}}', (err) => { - if (err) return callback(err) - this.writeFile(this.jsPath, (err) => { - if (err) return callback(err) - this.writeTemplateBetween('{{script}}', null, callback) - }) - }) + this.writeTemplateBetween('{{messages}}', null, callback) }) } @@ -110,11 +107,6 @@ export default class CucumberHtmlStream extends Transform { } private writeMessage(envelope: messages.Envelope) { - if (!this.firstMessageWritten) { - this.firstMessageWritten = true - } else { - this.push(',') - } - this.push(JSON.stringify(envelope)) + this.push(`\n`) } } diff --git a/javascript/src/index.mustache.html b/javascript/src/index.mustache.html index e607a4b2..a3fddb06 100644 --- a/javascript/src/index.mustache.html +++ b/javascript/src/index.mustache.html @@ -9,13 +9,10 @@ -
-
- +
+{{messages}} diff --git a/javascript/src/main.tsx b/javascript/src/main.tsx index 6db90170..e00af856 100644 --- a/javascript/src/main.tsx +++ b/javascript/src/main.tsx @@ -1,8 +1,8 @@ import './styles.scss' -import * as messages from '@cucumber/messages' +import { Envelope } from '@cucumber/messages' import { components, searchFromURLParams } from '@cucumber/react-components' -import React from 'react' +import React, { useState } from 'react' import ReactDOM from 'react-dom' const { CucumberReact } = components @@ -10,18 +10,23 @@ const { FilteredResults, EnvelopesWrapper, SearchWrapper } = components.app declare global { interface Window { - CUCUMBER_MESSAGES: messages.Envelope[] + p(envelope: Envelope): void } } -const app = ( - - - - - - - -) +const App: React.FunctionComponent = () => { + const [envelopes, setEnvelopes] = useState([]) + window.p = (envelope) => setEnvelopes(envelopes.concat(envelope)) -ReactDOM.render(app, document.getElementById('content')) + return ( + + + + + + + + ) +} + +ReactDOM.render(, document.getElementById('content')) diff --git a/javascript/test/CucumberHtmlStreamTest.ts b/javascript/test/CucumberHtmlStreamTest.ts index 7eaed864..30a92998 100644 --- a/javascript/test/CucumberHtmlStreamTest.ts +++ b/javascript/test/CucumberHtmlStreamTest.ts @@ -35,11 +35,6 @@ async function renderAsHtml( } describe('CucumberHtmlStream', () => { - it('writes zero messages to html', async () => { - const html = await renderAsHtml() - assert(html.indexOf('window.CUCUMBER_MESSAGES = []') >= 0) - }) - it('writes one message to html', async () => { const e1: messages.Envelope = { testRunStarted: { @@ -47,9 +42,7 @@ describe('CucumberHtmlStream', () => { }, } const html = await renderAsHtml(e1) - assert( - html.indexOf(`window.CUCUMBER_MESSAGES = [${JSON.stringify(e1)}]`) >= 0 - ) + assert(html.indexOf(`p(${JSON.stringify(e1)})`) >= 0) }) it('writes two messages to html', async () => { @@ -65,12 +58,8 @@ describe('CucumberHtmlStream', () => { }, } const html = await renderAsHtml(e1, e2) - assert( - html.indexOf( - `window.CUCUMBER_MESSAGES = [${JSON.stringify(e1)},${JSON.stringify( - e2 - )}]` - ) >= 0 - ) + console.log(html) + assert(html.indexOf(``) >= 0) + assert(html.indexOf(``) >= 0) }) }) diff --git a/javascript/test/acceptance.ts b/javascript/test/acceptance.ts index 568519b0..4293c5c6 100644 --- a/javascript/test/acceptance.ts +++ b/javascript/test/acceptance.ts @@ -7,6 +7,7 @@ import puppeteer from 'puppeteer' import { PassThrough, pipeline } from 'stream' import CucumberHtmlStream from '../src/CucumberHtmlStream' +import { writeFile } from 'fs/promises' async function canRenderHtml(html: string): Promise { const browser = await puppeteer.launch({ @@ -33,10 +34,11 @@ describe('html-formatter', () => { `./node_modules/@cucumber/compatibility-kit/features/**/*.ndjson` ) for (const ndjson of files) { - it(`can render ${path.basename(ndjson, '.ndjson')}`, async () => { + const basename = path.basename(ndjson, '.ndjson') + it(`can render ${basename}`, async () => { const ndjsonData = fs.createReadStream(ndjson, { encoding: 'utf-8' }) const toMessageStream = new NdjsonToMessageStream() - const htmlData = await new Promise((resolve, reject) => { + const html = await new Promise((resolve, reject) => { const chunks: Buffer[] = [] const out = new PassThrough() .on('data', (chunk) => chunks.push(Buffer.from(chunk))) @@ -56,7 +58,8 @@ describe('html-formatter', () => { } ) }) - assert.ok(await canRenderHtml(htmlData.toString())) + await writeFile(`html/${basename}.html`, html, 'utf-8') + assert.ok(await canRenderHtml(html)) }) } }) diff --git a/javascript/test/dummy.css b/javascript/test/dummy.css index e69de29b..30ff5636 100644 --- a/javascript/test/dummy.css +++ b/javascript/test/dummy.css @@ -0,0 +1 @@ +/* dummy css */ diff --git a/javascript/test/dummy.js b/javascript/test/dummy.js index e69de29b..ae9b3356 100644 --- a/javascript/test/dummy.js +++ b/javascript/test/dummy.js @@ -0,0 +1 @@ +// dummy js From 12afaa0f29b46d3a1ce99a2465b3f1ac2b5ffa95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 14 Jun 2022 22:56:31 +0100 Subject: [PATCH 2/4] Document how to manually test incremental rendering --- javascript/README.md | 21 +++++++++++++++++++++ javascript/scripts/slowcat | 15 +++++++++++++++ 2 files changed, 36 insertions(+) create mode 100755 javascript/scripts/slowcat diff --git a/javascript/README.md b/javascript/README.md index ee0d7737..725c97e3 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -3,3 +3,24 @@ # html-formatter > Takes a stream of Cucumber messages and outputs a standalone HTML report using Cucumber's React components + +## Manually testing incremental output + +The generated HTML report can be viewed before the entire report has been generated. This can be tested manually. + + npm install + npm run build + npm run validate + +You should now have some HTML reports under `html/*.html`. Let's render this incrementally: + + rm -f incremental.html + touch incremental.html + + # open the empty file in a browser + open incremental.html + + # incrementally write some contents into that file, simulating cucumber writing the file slowly + cat html/examples-tables.feature.html | ./scripts/slowcat > incremental.html + +Return to the browser. Keep refresh it. You should see that the report contents changes. diff --git a/javascript/scripts/slowcat b/javascript/scripts/slowcat new file mode 100755 index 00000000..b26efc7d --- /dev/null +++ b/javascript/scripts/slowcat @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# +# Works like cat, but slows down printing after seeing the first tag. +# By default, the delay in slow mode is 1 second. This can be overridden by passing an argument +# + +pause=${1:-1} +slow=false +while IFS='$\n' read -r line; do + if [[ "$slow" = true ]]; then sleep $pause; fi + echo "$line" + if [[ "$line" = "" ]] && [[ "$slow" = false ]]; then + slow=true; + fi +done From e5a17630ec818ad50c69f8058e9c2bae8f3c6a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 14 Jun 2022 23:01:06 +0100 Subject: [PATCH 3/4] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5d2b716..4476053b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +- Incrementally render the HTML report. ([#120](https://github.com/cucumber/html-formatter/issues/120), [#121](https://github.com/cucumber/html-formatter/pull/121)) + ## [19.2.0] - 2022-05-27 ### Changed - Upgrade to `@cucumber/react-components` `^20.1.0` From 7fee1ef3439791c17e50a994f5e8a6288f4e1636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Tue, 14 Jun 2022 23:06:27 +0100 Subject: [PATCH 4/4] linting --- javascript/test/acceptance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/test/acceptance.ts b/javascript/test/acceptance.ts index 4293c5c6..60a8d64f 100644 --- a/javascript/test/acceptance.ts +++ b/javascript/test/acceptance.ts @@ -1,13 +1,13 @@ import { NdjsonToMessageStream } from '@cucumber/message-streams' import assert from 'assert' import fs from 'fs' +import { writeFile } from 'fs/promises' import glob from 'glob' import path from 'path' import puppeteer from 'puppeteer' import { PassThrough, pipeline } from 'stream' import CucumberHtmlStream from '../src/CucumberHtmlStream' -import { writeFile } from 'fs/promises' async function canRenderHtml(html: string): Promise { const browser = await puppeteer.launch({