Skip to content

Commit

Permalink
functional tests for stream examples
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed May 16, 2024
1 parent a568e97 commit c03a427
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 79 deletions.
2 changes: 1 addition & 1 deletion examples/response_stream/public/components/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const Page: FC<PropsWithChildren<PageProps>> = ({ title = 'Untitled', chi
<>
<EuiPageTemplate.Header>
<EuiTitle size="l">
<h1>{title}</h1>
<h1 data-test-subj="responseStreamPageTitle">{title}</h1>
</EuiTitle>
</EuiPageTemplate.Header>
<EuiPageTemplate.Section>{children}</EuiPageTemplate.Section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,19 @@ export const PageReducerStream: FC = () => {
<br />
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton color="primary" size="s" onClick={onClickHandler} aria-label={buttonLabel}>
<EuiButton
data-test-subj="responseStreamStartButton"
color="primary"
size="s"
onClick={onClickHandler}
aria-label={buttonLabel}
>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<EuiBadge>{progress}%</EuiBadge>
<EuiBadge data-test-subj="responseStreamProgressBadge">{progress}%</EuiBadge>
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
Expand All @@ -112,7 +118,9 @@ export const PageReducerStream: FC = () => {
<EuiSpacer />
<BarChartRace entities={entities} />
<EuiText>
<p>{getStatusMessage(isRunning, isCancelled, data.progress)}</p>
<p data-test-subj="responseStreamStatusMessage">
{getStatusMessage(isRunning, isCancelled, progress)}
</p>
<EuiCheckbox
id="responseStreamSimulateErrorsCheckbox"
label="Simulate errors (gets applied to new streams only, not currently running ones)."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,19 @@ export const PageReduxStream: FC = () => {
<br />
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton color="primary" size="s" onClick={onClickHandler} aria-label={buttonLabel}>
<EuiButton
data-test-subj="responseStreamStartButton"
color="primary"
size="s"
onClick={onClickHandler}
aria-label={buttonLabel}
>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<EuiBadge>{progress}%</EuiBadge>
<EuiBadge data-test-subj="responseStreamProgressBadge">{progress}%</EuiBadge>
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
Expand All @@ -118,7 +124,9 @@ export const PageReduxStream: FC = () => {
<EuiSpacer />
<BarChartRace entities={entities} />
<EuiText>
<p>{getStatusMessage(isRunning, isCancelled, progress)}</p>
<p data-test-subj="responseStreamStatusMessage">
{getStatusMessage(isRunning, isCancelled, progress)}
</p>
<EuiCheckbox
id="responseStreamSimulateErrorsCheckbox"
label="Simulate errors (gets applied to new streams only, not currently running ones)."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ export const PageSimpleStringStream: FC = () => {
<br />
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton color="primary" size="s" onClick={onClickHandler} aria-label={buttonLabel}>
<EuiButton
data-test-subj="responseStreamStartButton"
color="primary"
size="s"
onClick={onClickHandler}
aria-label={buttonLabel}
>
{buttonLabel}
</EuiButton>
</EuiFlexItem>
Expand All @@ -81,7 +87,7 @@ export const PageSimpleStringStream: FC = () => {
/>
<EuiSpacer />
<EuiText>
<p>{data}</p>
<p data-test-subj="responseStreamString">{data}</p>
</EuiText>
{errors.length > 0 && (
<EuiCallOut title="Sorry, there was an error" color="danger" iconType="warning">
Expand Down
1 change: 1 addition & 0 deletions test/examples/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default async function ({ readConfigFile }) {
require.resolve('./unified_field_list_examples'),
require.resolve('./discover_customization_examples'),
require.resolve('./error_boundary'),
require.resolve('./response_stream'),
],
services: {
...functionalConfig.get('services'),
Expand Down
12 changes: 11 additions & 1 deletion test/examples/response_stream/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ import { FtrProviderContext } from '../../functional/ftr_provider_context';

// eslint-disable-next-line import/no-default-export
export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) {
describe('response stream', function () {
const browser = getService('browser');
const PageObjects = getPageObjects(['common', 'header']);

describe('response-stream', function () {
before(async () => {
await browser.setWindowSize(1300, 900);
await PageObjects.common.navigateToApp('response-stream', { insertTimestamp: false });
});

loadTestFile(require.resolve('./string_stream'));
loadTestFile(require.resolve('./reducer_stream'));
loadTestFile(require.resolve('./redux_stream'));
});
}
101 changes: 32 additions & 69 deletions test/examples/response_stream/reducer_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,84 +6,47 @@
* Side Public License, v 1.
*/

import fetch from 'node-fetch';
import { format as formatUrl } from 'url';

import expect from '@kbn/expect';

import { FtrProviderContext } from '../../functional/ftr_provider_context';

import { parseStream } from './parse_stream';

// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const config = getService('config');
const kibanaServerUrl = formatUrl(config.get('servers.kibana'));

describe('POST /internal/response_stream/reducer_stream', () => {
it('should return full data without streaming', async () => {
const resp = await supertest
.post('/internal/response_stream/reducer_stream')
.set('kbn-xsrf', 'kibana')
.send({
timeout: 1,
})
.expect(200);

expect(Buffer.isBuffer(resp.body)).to.be(true);

const chunks: string[] = resp.body.toString().split('\n');

expect(chunks.length).to.be(201);

const lastChunk = chunks.pop();
expect(lastChunk).to.be('');

let data: any[] = [];
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const retry = getService('retry');

describe('useReducer stream example', () => {
it('navigates to the example', async () => {
await testSubjects.click('ndjson-usereducer-stream');

await retry.try(async () => {
expect(await testSubjects.getVisibleText('responseStreamPageTitle')).to.be(
'NDJSON useReducer stream'
);
expect(await testSubjects.getVisibleText('responseStreamProgressBadge')).to.be('0%');
expect(await testSubjects.getVisibleText('responseStreamStatusMessage')).to.be(
'Development did not start yet.'
);
});
});

expect(() => {
data = chunks.map((c) => JSON.parse(c));
}).not.to.throwError();
it('starts the stream', async () => {
await testSubjects.click('responseStreamStartButton');

data.forEach((d) => {
expect(typeof d.type).to.be('string');
await retry.try(async () => {
expect(await testSubjects.getVisibleText('responseStreamProgressBadge')).not.to.be('0%');
expect(await testSubjects.getVisibleText('responseStreamStatusMessage')).to.be(
'Development is ongoing, the hype is real!'
);
});

const progressData = data.filter((d) => d.type === 'update_progress');
expect(progressData.length).to.be(100);
expect(progressData[0].payload).to.be(1);
expect(progressData[progressData.length - 1].payload).to.be(100);
});

it('should return data in chunks with streaming', async () => {
const response = await fetch(`${kibanaServerUrl}/internal/response_stream/reducer_stream`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'kbn-xsrf': 'stream',
},
body: JSON.stringify({ timeout: 1 }),
it('finishes the stream', async () => {
await retry.tryForTime(60000, async () => {
expect(await testSubjects.getVisibleText('responseStreamProgressBadge')).to.be('100%');
expect(await testSubjects.getVisibleText('responseStreamStatusMessage')).to.be(
'Development completed, the release got out the door!'
);
});

const stream = response.body;

expect(stream).not.to.be(null);

if (stream !== null) {
const progressData: any[] = [];

for await (const action of parseStream(stream)) {
expect(action.type).not.to.be('error');
if (action.type === 'update_progress') {
progressData.push(action);
}
}

expect(progressData.length).to.be(100);
expect(progressData[0].payload).to.be(1);
expect(progressData[progressData.length - 1].payload).to.be(100);
}
});
});
};
}
52 changes: 52 additions & 0 deletions test/examples/response_stream/redux_stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../functional/ftr_provider_context';

// eslint-disable-next-line import/no-default-export
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const retry = getService('retry');

describe('redux stream example', () => {
it('navigates to the example', async () => {
await testSubjects.click('ndjson-redux-toolkit-stream');

await retry.try(async () => {
expect(await testSubjects.getVisibleText('responseStreamPageTitle')).to.be(
'NDJSON Redux Toolkit stream'
);
expect(await testSubjects.getVisibleText('responseStreamProgressBadge')).to.be('0%');
expect(await testSubjects.getVisibleText('responseStreamStatusMessage')).to.be(
'Development did not start yet.'
);
});
});

it('starts the stream', async () => {
await testSubjects.click('responseStreamStartButton');

await retry.try(async () => {
expect(await testSubjects.getVisibleText('responseStreamProgressBadge')).not.to.be('0%');
expect(await testSubjects.getVisibleText('responseStreamStatusMessage')).to.be(
'Development is ongoing, the hype is real!'
);
});
});

it('finishes the stream', async () => {
await retry.tryForTime(60000, async () => {
expect(await testSubjects.getVisibleText('responseStreamProgressBadge')).to.be('100%');
expect(await testSubjects.getVisibleText('responseStreamStatusMessage')).to.be(
'Development completed, the release got out the door!'
);
});
});
});
}
46 changes: 46 additions & 0 deletions test/examples/response_stream/string_stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../functional/ftr_provider_context';

// eslint-disable-next-line import/no-default-export
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const retry = getService('retry');

describe('string stream example', () => {
it('navigates to the example', async () => {
await testSubjects.click('simple-string-stream');

await retry.try(async () => {
expect(await testSubjects.getVisibleText('responseStreamPageTitle')).to.be(
'Simple string stream'
);
expect(await testSubjects.exists('responseStreamStartButton')).to.be(true);
expect(await testSubjects.getVisibleText('responseStreamString')).to.be('');
});
});

it('starts the stream', async () => {
await testSubjects.click('responseStreamStartButton');

await retry.try(async () => {
expect(await testSubjects.getVisibleText('responseStreamString')).not.to.be('');
});
});

it('finishes the stream', async () => {
await retry.tryForTime(60000, async () => {
expect(await testSubjects.getVisibleText('responseStreamString')).to.be(
'Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. Elasticsearch is developed in Java and is dual-licensed under the source-available Server Side Public License and the Elastic license, while other parts fall under the proprietary (source-available) Elastic License. Official clients are available in Java, .NET (C#), PHP, Python, Apache Groovy, Ruby and many other languages. According to the DB-Engines ranking, Elasticsearch is the most popular enterprise search engine.'
);
});
});
});
}

0 comments on commit c03a427

Please sign in to comment.