Skip to content

Commit

Permalink
[TEST] improve 'events' visual tests
Browse files Browse the repository at this point in the history
Use a BPMN diagram that contains the whole events of the BPMN palette. So, we
now test all elements that the lib is currently supported, and we are prepared
to test remaining events to support in the future.

As the BPMN diagram is too large for the load method using the url query param
in the 'visual testing' page, add a new loading method:
  - allow the test page to load a BPMN diagram using a query param providing the
  url to the file to load (via the Fetch API)
  - copy the file from the test fixtures folder to a folder that is served by
  the test server
  - pass the relative path to the newly copied file as url parameter to make the
  page load this file
  - update the 'visual testing' page to display the BPMN file fetching errors

In addition, refactor and share functions used to load the BPMN content in e2e
tests.
  • Loading branch information
tbouffard committed Aug 24, 2020
1 parent 98a9e23 commit 5145db6
Show file tree
Hide file tree
Showing 11 changed files with 705 additions and 52 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"devDependencies": {
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^8.4.0",
"@types/debug": "^4.1.5",
"@types/jest": "^26.0.9",
"@types/jest-environment-puppeteer": "^4.3.2",
"@types/puppeteer": "^3.0.1",
Expand Down
57 changes: 52 additions & 5 deletions src/demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,45 @@ export function handleFileSelect(evt: any): void {
readAndLoadFile(f);
}

export function startBpmnVisualization(container: string): void {
function fetchBpmnContent(url: string): Promise<string> {
log(`Fetching BPMN content from url ${url}`);
return fetch(url).then(response => {
if (!response.ok) {
throw Error(String(response.status));
}
return response.text();
});
}

function loadBpmnFromUrl(url: string, statusFetchKoNotifier: (errorMsg: string) => void): void {
fetchBpmnContent(url)
.catch(error => {
const errorMessage = `Unable to fetch ${url}. ${error}`;
statusFetchKoNotifier(errorMessage);
throw new Error(errorMessage);
})
.then(responseBody => {
log('BPMN content fetched');
return responseBody;
})
.then(bpmn => {
loadBpmn(bpmn);
log(`Bpmn loaded from url ${url}`);
});
}

export interface BpmnVisualizationDemoConfiguration {
container: string;
statusFetchKoNotifier?: (errorMsg: string) => void;
}

function defaultStatusFetchKoNotifier(errorMsg: string): void {
console.error(errorMsg);
}

export function startBpmnVisualization(config: BpmnVisualizationDemoConfiguration): void {
const log = logStartup;
const container = config.container;

log(`Initializing BpmnVisualization with container '${container}'...`);
bpmnVisualization = new BpmnVisualization(window.document.getElementById(container));
Expand All @@ -62,16 +99,26 @@ export function startBpmnVisualization(container: string): void {
fitOnLoad = parameters.get('fitOnLoad') == 'true';
log(`Configure 'fit on load' to ${fitOnLoad}`);

log("Checking if 'BPMN auto loading from url parameter' is requested");
log("Checking if 'BPMN content' is provided as query parameter");
const bpmnParameterValue = parameters.get('bpmn');
if (bpmnParameterValue) {
const bpmn = decodeURIComponent(bpmnParameterValue);
log(`Received bpmn length: ${bpmn.length}`);
log(`Received bpmn content: ${bpmn}`);
log('BPMN auto loading');
loadBpmn(bpmn);
log('BPMN auto loading completed');
} else {
log('No BPMN auto loading');
log('BPMN content loading completed');
return;
}
log("No 'BPMN content' provided");

log("Checking if an 'url to fetch BPMN content' is provided as query parameter");
const urlParameterValue = parameters.get('url');
if (urlParameterValue) {
const url = decodeURIComponent(urlParameterValue);
const statusFetchKoNotifier = config.statusFetchKoNotifier || defaultStatusFetchKoNotifier;
loadBpmnFromUrl(url, statusFetchKoNotifier);
return;
}
log("No 'url to fetch BPMN content' provided");
}
5 changes: 5 additions & 0 deletions src/index-non-regression.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
position: absolute;
overflow: hidden;
}
.status-ko {
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<div id="fetch-status"></div>
<div id="viewport" class="graph-container"></div>

<!-- load global settings -->
Expand Down
2 changes: 1 addition & 1 deletion src/static/js/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ new DropFileUserInterface(window, 'drop-container', visualizationContainer, read
document.getElementById('bpmn-file').addEventListener('change', handleFileSelect, false);
document.getElementById('file-selector').classList.remove('hidden');

documentReady(startBpmnVisualization(visualizationContainer));
documentReady(startBpmnVisualization({ container: visualizationContainer }));
9 changes: 8 additions & 1 deletion src/static/js/non-regression.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,11 @@ const visualizationContainer = 'viewport';
// TODO: move to UI initializer
new DropFileUserInterface(window, 'drop-container', visualizationContainer, readAndLoadFile);

documentReady(startBpmnVisualization(visualizationContainer));
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function statusFetchKO(errorMsg) {
const statusElt = document.getElementById('fetch-status');
statusElt.innerText = errorMsg;
statusElt.className = 'status-ko';
}

documentReady(startBpmnVisualization({ container: visualizationContainer, statusFetchKoNotifier: statusFetchKO }));
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 42 additions & 20 deletions test/e2e/bpmn-rendering.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ declare global {
}
}

import { encodeUriXml, findFiles, linearizeXml, readFileSync } from '../helpers/file-helper';
// import debug from 'debug';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const debug = require('debug')('test');
import { copyFileSync, findFiles, loadBpmnContentForUrlQueryParam } from '../helpers/file-helper';
import debugLogger from 'debug';

const log = debugLogger('test');
const graphContainerId = 'viewport';

describe('no visual regression', () => {
Expand All @@ -46,13 +45,9 @@ describe('no visual regression', () => {
comparisonMethod: 'ssim',
};

function log(msg: string): void {
debug(msg);
}

function getSimplePlatformName(): string {
const platform = process.platform;
debug(`This platform is ${platform}`);
log(`This platform is ${platform}`);

if (platform.startsWith('win')) {
return 'windows';
Expand Down Expand Up @@ -139,17 +134,43 @@ describe('no visual regression', () => {
return defaultImageSnapshotConfig;
}

function bpmnContentForTestPage(fileName: string): string {
log(`Preparing bpmn content for test '${fileName}'`);
let rawBpmn = readFileSync(`../fixtures/bpmn/non-regression/${fileName}.bpmn`);
log(`Original bpmn length: ${rawBpmn.length}`);
enum BpmnLoadMethod {
QueryParam = 'query param',
Url = 'url',
}

rawBpmn = linearizeXml(rawBpmn);
log(`bpmn length after linearize: ${rawBpmn.length}`);
/**
* Configure how the BPMN file is loaded by the test page.
*
* When introducing a new test, there is generally no need to add configuration here as the default is OK. You only need configuration when the file content becomes larger (in
* that case, the test server returns an HTTP 400 error).
*
* Prior adding a config here, review your file to check if it is not too large because it contains too much elements, in particular, some elements not related to what you want to
* test.
*/
const bpmnLoadMethodConfig = new Map<string, BpmnLoadMethod>([['events', BpmnLoadMethod.Url]]);

const uriEncodedBpmn = encodeUriXml(rawBpmn);
log(`bpmn length in URI encoded form: ${uriEncodedBpmn.length}`);
return uriEncodedBpmn;
function getBpmnLoadMethod(fileName: string): BpmnLoadMethod {
return bpmnLoadMethodConfig.get(fileName) || BpmnLoadMethod.QueryParam;
}

function prepareTestResourcesAndGetPageUrl(fileName: string): string {
let url = 'http://localhost:10001/index-non-regression.html?fitOnLoad=true';

const bpmnLoadMethod = getBpmnLoadMethod(fileName);
log(`Use '${bpmnLoadMethod}' as BPMN Load Method for '${fileName}'`);
const relPathToBpmnFile = `../fixtures/bpmn/non-regression/${fileName}.bpmn`;
switch (bpmnLoadMethod) {
case BpmnLoadMethod.QueryParam:
const bpmnContent = loadBpmnContentForUrlQueryParam(relPathToBpmnFile);
url += `&bpmn=${bpmnContent}`;
break;
case BpmnLoadMethod.Url:
copyFileSync(relPathToBpmnFile, `../../dist/static/diagrams/`, `${fileName}.bpmn`);
url += `&url=./static/diagrams/${fileName}.bpmn`;
break;
}
return url;
}

const bpmnFiles = findFiles('../fixtures/bpmn/non-regression/');
Expand All @@ -166,9 +187,10 @@ describe('no visual regression', () => {
return filename.split('.').slice(0, -1).join('.');
});
it.each(bpmnFileNames)(`%s`, async (fileName: string) => {
const url = `http://localhost:10001/index-non-regression.html?fitOnLoad=true&bpmn=${bpmnContentForTestPage(fileName)}`;
const url = prepareTestResourcesAndGetPageUrl(fileName);

const response = await page.goto(url);
// Uncomment the following in case of http error 400
// Uncomment the following in case of http error 400 (probably because of a too large bpmn file)
// eslint-disable-next-line no-console
// await page.evaluate(() => console.log(`url is ${location.href}`));
expect(response.status()).toBe(200);
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/mxGraph.view.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { readFileSync } from '../helpers/file-helper';
import { loadBpmnContentForUrlQueryParam } from '../helpers/file-helper';

let graphContainerId = 'graph';

Expand Down Expand Up @@ -59,7 +59,7 @@ describe('BpmnVisu view - index page', () => {
});

it('should display graph in page', async () => {
await page.goto(`http://localhost:10001?bpmn=${readFileSync('../fixtures/bpmn/simple-start-task-end.bpmn')}`);
await page.goto(`http://localhost:10001?bpmn=${loadBpmnContentForUrlQueryParam('../fixtures/bpmn/simple-start-task-end.bpmn')}`);

await expectEvent('StartEvent_1', 'Start Event 1');
await expectSequenceFlow('Flow_1', 'Sequence Flow 1');
Expand All @@ -72,7 +72,7 @@ describe('BpmnVisu view - index page', () => {
describe('BpmnVisu view - lib-integration page', () => {
it('should display graph in page', async () => {
graphContainerId = 'bpmn-visualization-viewport';
await page.goto(`http://localhost:10001/lib-integration.html?bpmn=${readFileSync('../fixtures/bpmn/simple-start-only.bpmn')}`);
await page.goto(`http://localhost:10001/lib-integration.html?bpmn=${loadBpmnContentForUrlQueryParam('../fixtures/bpmn/simple-start-only.bpmn')}`);
await expect(page.title()).resolves.toMatch('BPMN Visualization Lib Integration');
await page.waitForSelector(`#${graphContainerId}`);

Expand Down
Loading

0 comments on commit 5145db6

Please sign in to comment.