mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Routing example plugin (#69581)
* Routing example plugin * Routing example plugin * address review comments * consolidate route registration into single function * ts fix * Add functional tests * typescript fix * Fix typo * check against HttpFetchError not Error * fix ts * fix unhappy ci Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
badb7b5c8c
commit
339e13bc53
22 changed files with 1107 additions and 0 deletions
9
examples/routing_example/README.md
Normal file
9
examples/routing_example/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
Team owner: Platform
|
||||
|
||||
A working example of a plugin that registers and uses multiple custom routes.
|
||||
|
||||
Read more:
|
||||
|
||||
- [IRouter API Docs](../../docs/development/core/server/kibana-plugin-core-server.irouter.md)
|
||||
- [HttpHandler (core.http.fetch) API Docs](../../docs/development/core/public/kibana-plugin-core-public.httphandler.md)
|
||||
- [Routing Conventions](../../STYLEGUIDE.md#api-endpoints)
|
27
examples/routing_example/common/index.ts
Normal file
27
examples/routing_example/common/index.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export const RANDOM_NUMBER_ROUTE_PATH = '/api/random_number';
|
||||
|
||||
export const RANDOM_NUMBER_BETWEEN_ROUTE_PATH = '/api/random_number_between';
|
||||
|
||||
export const POST_MESSAGE_ROUTE_PATH = '/api/post_message';
|
||||
|
||||
// Internal APIs should use the `internal` prefix, instead of the `api` prefix.
|
||||
export const INTERNAL_GET_MESSAGE_BY_ID_ROUTE = '/internal/get_message';
|
9
examples/routing_example/kibana.json
Normal file
9
examples/routing_example/kibana.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"id": "routingExample",
|
||||
"version": "0.0.1",
|
||||
"kibanaVersion": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["developerExamples"],
|
||||
"optionalPlugins": []
|
||||
}
|
105
examples/routing_example/public/app.tsx
Normal file
105
examples/routing_example/public/app.tsx
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { AppMountParameters } from 'kibana/public';
|
||||
import {
|
||||
EuiPage,
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiText,
|
||||
EuiHorizontalRule,
|
||||
EuiPageContentHeader,
|
||||
EuiListGroup,
|
||||
} from '@elastic/eui';
|
||||
import { RandomNumberRouteExample } from './random_number_example';
|
||||
import { RandomNumberBetweenRouteExample } from './random_number_between_example';
|
||||
import { Services } from './services';
|
||||
import { PostMessageRouteExample } from './post_message_example';
|
||||
import { GetMessageRouteExample } from './get_message_example';
|
||||
|
||||
type Props = Services;
|
||||
|
||||
function RoutingExplorer({
|
||||
fetchRandomNumber,
|
||||
fetchRandomNumberBetween,
|
||||
addSuccessToast,
|
||||
postMessage,
|
||||
getMessageById,
|
||||
}: Props) {
|
||||
return (
|
||||
<EuiPage>
|
||||
<EuiPageBody>
|
||||
<EuiPageContent>
|
||||
<EuiPageContentHeader>
|
||||
<EuiText>
|
||||
<h1>Routing examples</h1>
|
||||
</EuiText>
|
||||
</EuiPageContentHeader>
|
||||
<EuiText>
|
||||
<EuiListGroup
|
||||
listItems={[
|
||||
{
|
||||
label: 'IRouter API docs',
|
||||
href:
|
||||
'https://github.com/elastic/kibana/blob/master/docs/development/core/server/kibana-plugin-core-server.irouter.md',
|
||||
iconType: 'logoGithub',
|
||||
target: '_blank',
|
||||
size: 's',
|
||||
},
|
||||
{
|
||||
label: 'HttpHandler (core.http.fetch) API docs',
|
||||
href:
|
||||
'https://github.com/elastic/kibana/blob/master/docs/development/core/public/kibana-plugin-core-public.httphandler.md',
|
||||
iconType: 'logoGithub',
|
||||
target: '_blank',
|
||||
size: 's',
|
||||
},
|
||||
{
|
||||
label: 'Conventions',
|
||||
href: 'https://github.com/elastic/kibana/tree/master/STYLEGUIDE.md#api-endpoints',
|
||||
iconType: 'logoGithub',
|
||||
target: '_blank',
|
||||
size: 's',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</EuiText>
|
||||
<EuiHorizontalRule />
|
||||
<RandomNumberRouteExample fetchRandomNumber={fetchRandomNumber} />
|
||||
<EuiHorizontalRule />
|
||||
<RandomNumberBetweenRouteExample fetchRandomNumberBetween={fetchRandomNumberBetween} />
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<PostMessageRouteExample addSuccessToast={addSuccessToast} postMessage={postMessage} />
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<GetMessageRouteExample getMessageById={getMessageById} />
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
);
|
||||
}
|
||||
|
||||
export const renderApp = (props: Props, element: AppMountParameters['element']) => {
|
||||
ReactDOM.render(<RoutingExplorer {...props} />, element);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
96
examples/routing_example/public/get_message_example.tsx
Normal file
96
examples/routing_example/public/get_message_example.tsx
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React, { useCallback } from 'react';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
EuiText,
|
||||
EuiButton,
|
||||
EuiLoadingSpinner,
|
||||
EuiFieldText,
|
||||
EuiCallOut,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
import { HttpFetchError } from '../../../src/core/public';
|
||||
import { isError } from './is_error';
|
||||
import { Services } from './services';
|
||||
|
||||
interface Props {
|
||||
getMessageById: Services['getMessageById'];
|
||||
}
|
||||
|
||||
export function GetMessageRouteExample({ getMessageById }: Props) {
|
||||
const [error, setError] = useState<HttpFetchError | undefined>();
|
||||
const [isFetching, setIsFetching] = useState<boolean>(false);
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [id, setId] = useState<string>('');
|
||||
|
||||
const doFetch = useCallback(async () => {
|
||||
if (isFetching) return;
|
||||
setIsFetching(true);
|
||||
const response = await getMessageById(id);
|
||||
|
||||
if (isError(response)) {
|
||||
setError(response);
|
||||
setMessage('');
|
||||
} else {
|
||||
setError(undefined);
|
||||
setMessage(response);
|
||||
}
|
||||
|
||||
setIsFetching(false);
|
||||
}, [isFetching, getMessageById, setMessage, id]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiText>
|
||||
<h2>GET example with param</h2>
|
||||
|
||||
<p>This examples uses a simple GET route that takes an id as a param in the route path.</p>
|
||||
<EuiFormRow label="Message Id">
|
||||
<EuiFieldText
|
||||
value={id}
|
||||
onChange={(e) => setId(e.target.value)}
|
||||
data-test-subj="routingExampleGetMessageId"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow hasEmptyLabelSpace={true}>
|
||||
<EuiButton
|
||||
data-test-subj="routingExampleFetchMessage"
|
||||
disabled={isFetching || id === ''}
|
||||
onClick={() => doFetch()}
|
||||
>
|
||||
{isFetching ? <EuiLoadingSpinner /> : 'Get message'}
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
|
||||
{error !== undefined ? (
|
||||
<EuiCallOut color="danger" iconType="alert">
|
||||
{error.message}
|
||||
</EuiCallOut>
|
||||
) : null}
|
||||
{message !== '' ? (
|
||||
<p>
|
||||
Message is: <pre data-test-subj="routingExampleGetMessage">{message}</pre>
|
||||
</p>
|
||||
) : null}
|
||||
</EuiText>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
23
examples/routing_example/public/index.ts
Normal file
23
examples/routing_example/public/index.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { PluginInitializer } from 'kibana/public';
|
||||
import { RoutingExamplePlugin } from './plugin';
|
||||
|
||||
export const plugin: PluginInitializer<{}, {}> = () => new RoutingExamplePlugin();
|
24
examples/routing_example/public/is_error.ts
Normal file
24
examples/routing_example/public/is_error.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { HttpFetchError } from '../../../src/core/public';
|
||||
|
||||
export function isError<T>(error: T | HttpFetchError): error is HttpFetchError {
|
||||
return error instanceof HttpFetchError;
|
||||
}
|
78
examples/routing_example/public/plugin.tsx
Normal file
78
examples/routing_example/public/plugin.tsx
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
CoreStart,
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
AppMountParameters,
|
||||
AppNavLinkStatus,
|
||||
} from '../../../src/core/public';
|
||||
import { DeveloperExamplesSetup } from '../../developer_examples/public';
|
||||
import { getServices } from './services';
|
||||
|
||||
interface SetupDeps {
|
||||
developerExamples: DeveloperExamplesSetup;
|
||||
}
|
||||
|
||||
export class RoutingExamplePlugin implements Plugin<{}, {}, SetupDeps, {}> {
|
||||
public setup(core: CoreSetup, { developerExamples }: SetupDeps) {
|
||||
core.application.register({
|
||||
id: 'routingExample',
|
||||
title: 'Routing',
|
||||
navLinkStatus: AppNavLinkStatus.hidden,
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart] = await core.getStartServices();
|
||||
const startServices = getServices(coreStart);
|
||||
const { renderApp } = await import('./app');
|
||||
return renderApp(startServices, params.element);
|
||||
},
|
||||
});
|
||||
|
||||
developerExamples.register({
|
||||
appId: 'routingExample',
|
||||
title: 'Routing',
|
||||
description: `Examples show how to use core routing and fetch services to register and query your own custom routes.`,
|
||||
links: [
|
||||
{
|
||||
label: 'IRouter',
|
||||
href:
|
||||
'https://github.com/elastic/kibana/blob/master/docs/development/core/server/kibana-plugin-core-server.irouter.md',
|
||||
iconType: 'logoGithub',
|
||||
target: '_blank',
|
||||
size: 's',
|
||||
},
|
||||
{
|
||||
label: 'HttpHandler (core.http.fetch)',
|
||||
href:
|
||||
'https://github.com/elastic/kibana/blob/master/docs/development/core/public/kibana-plugin-core-public.httphandler.md',
|
||||
iconType: 'logoGithub',
|
||||
target: '_blank',
|
||||
size: 's',
|
||||
},
|
||||
],
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
return {};
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
}
|
103
examples/routing_example/public/post_message_example.tsx
Normal file
103
examples/routing_example/public/post_message_example.tsx
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React, { useCallback } from 'react';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
EuiText,
|
||||
EuiButton,
|
||||
EuiLoadingSpinner,
|
||||
EuiFieldText,
|
||||
EuiCallOut,
|
||||
EuiFormRow,
|
||||
EuiTextArea,
|
||||
} from '@elastic/eui';
|
||||
import { HttpFetchError } from '../../../src/core/public';
|
||||
import { isError } from './is_error';
|
||||
import { Services } from './services';
|
||||
|
||||
interface Props {
|
||||
postMessage: Services['postMessage'];
|
||||
addSuccessToast: Services['addSuccessToast'];
|
||||
}
|
||||
|
||||
export function PostMessageRouteExample({ postMessage, addSuccessToast }: Props) {
|
||||
const [error, setError] = useState<HttpFetchError | undefined>();
|
||||
const [isPosting, setIsPosting] = useState<boolean>(false);
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [id, setId] = useState<string>('');
|
||||
|
||||
const doFetch = useCallback(async () => {
|
||||
if (isPosting) return;
|
||||
setIsPosting(true);
|
||||
const response = await postMessage(message, id);
|
||||
|
||||
if (response && isError(response)) {
|
||||
setError(response);
|
||||
} else {
|
||||
setError(undefined);
|
||||
addSuccessToast('Message was added!');
|
||||
setMessage('');
|
||||
setId('');
|
||||
}
|
||||
|
||||
setIsPosting(false);
|
||||
}, [isPosting, postMessage, addSuccessToast, setMessage, message, id]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiText>
|
||||
<h2>POST example with body</h2>
|
||||
<p>
|
||||
This examples uses a simple POST route that takes a body parameter and an id as a param in
|
||||
the route path.
|
||||
</p>
|
||||
<EuiFormRow label="Message Id">
|
||||
<EuiFieldText
|
||||
value={id}
|
||||
onChange={(e) => setId(e.target.value)}
|
||||
data-test-subj="routingExampleSetMessageId"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow label="Message">
|
||||
<EuiTextArea
|
||||
data-test-subj="routingExampleSetMessage"
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow hasEmptyLabelSpace={true}>
|
||||
<EuiButton
|
||||
data-test-subj="routingExamplePostMessage"
|
||||
disabled={isPosting || id === '' || message === ''}
|
||||
onClick={() => doFetch()}
|
||||
>
|
||||
{isPosting ? <EuiLoadingSpinner /> : 'Post message'}
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
|
||||
{error !== undefined ? (
|
||||
<EuiCallOut color="danger" iconType="alert">
|
||||
{error.message}
|
||||
</EuiCallOut>
|
||||
) : null}
|
||||
</EuiText>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React, { useCallback } from 'react';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
EuiText,
|
||||
EuiButton,
|
||||
EuiLoadingSpinner,
|
||||
EuiFieldText,
|
||||
EuiCallOut,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
import { HttpFetchError } from '../../../src/core/public';
|
||||
import { isError } from './is_error';
|
||||
import { Services } from './services';
|
||||
|
||||
interface Props {
|
||||
fetchRandomNumberBetween: Services['fetchRandomNumberBetween'];
|
||||
}
|
||||
|
||||
export function RandomNumberBetweenRouteExample({ fetchRandomNumberBetween }: Props) {
|
||||
const [error, setError] = useState<HttpFetchError | undefined>();
|
||||
const [randomNumber, setRandomNumber] = useState<number>(0);
|
||||
const [isFetching, setIsFetching] = useState<boolean>(false);
|
||||
const [maxInput, setMaxInput] = useState<string>('10');
|
||||
|
||||
const doFetch = useCallback(async () => {
|
||||
if (isFetching) return;
|
||||
setIsFetching(true);
|
||||
const response = await fetchRandomNumberBetween(Number.parseInt(maxInput, 10));
|
||||
|
||||
if (isError(response)) {
|
||||
setError(response);
|
||||
} else {
|
||||
setRandomNumber(response);
|
||||
}
|
||||
|
||||
setIsFetching(false);
|
||||
}, [isFetching, maxInput, fetchRandomNumberBetween]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiText>
|
||||
<h2>GET example with query</h2>
|
||||
<p>
|
||||
This examples uses a simple GET route that takes a query parameter in the request and
|
||||
returns a single number.
|
||||
</p>
|
||||
<EuiFormRow label="Generate a random number between 0 and">
|
||||
<EuiFieldText
|
||||
data-test-subj="routingExampleMaxRandomNumberBetween"
|
||||
value={maxInput}
|
||||
onChange={(e) => setMaxInput(e.target.value)}
|
||||
isInvalid={isNaN(Number(maxInput))}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow hasEmptyLabelSpace={true}>
|
||||
<EuiButton
|
||||
data-test-subj="routingExampleFetchRandomNumberBetween"
|
||||
disabled={isFetching || isNaN(Number(maxInput))}
|
||||
onClick={() => doFetch()}
|
||||
>
|
||||
{isFetching ? <EuiLoadingSpinner /> : 'Generate random number'}
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
|
||||
{error !== undefined ? (
|
||||
<EuiCallOut color="danger" iconType="alert">
|
||||
{error.message}
|
||||
</EuiCallOut>
|
||||
) : null}
|
||||
{randomNumber > -1 ? (
|
||||
<h2>
|
||||
Random number is
|
||||
<div data-test-subj="routingExampleRandomNumberBetween">{randomNumber}</div>
|
||||
</h2>
|
||||
) : null}
|
||||
</EuiText>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
78
examples/routing_example/public/random_number_example.tsx
Normal file
78
examples/routing_example/public/random_number_example.tsx
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React, { useCallback } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { EuiText, EuiButton, EuiLoadingSpinner, EuiCallOut } from '@elastic/eui';
|
||||
import { HttpFetchError } from '../../../src/core/public';
|
||||
import { Services } from './services';
|
||||
import { isError } from './is_error';
|
||||
|
||||
interface Props {
|
||||
fetchRandomNumber: Services['fetchRandomNumber'];
|
||||
}
|
||||
|
||||
export function RandomNumberRouteExample({ fetchRandomNumber }: Props) {
|
||||
const [error, setError] = useState<HttpFetchError | undefined>(undefined);
|
||||
const [randomNumber, setRandomNumber] = useState<number>(0);
|
||||
const [isFetching, setIsFetching] = useState<boolean>(false);
|
||||
|
||||
const doFetch = useCallback(async () => {
|
||||
if (isFetching) return;
|
||||
setIsFetching(true);
|
||||
const response = await fetchRandomNumber();
|
||||
|
||||
if (isError(response)) {
|
||||
setError(response);
|
||||
} else {
|
||||
setRandomNumber(response);
|
||||
}
|
||||
|
||||
setIsFetching(false);
|
||||
}, [isFetching, fetchRandomNumber]);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EuiText>
|
||||
<h2>GET example</h2>
|
||||
<p>
|
||||
This examples uses a simple GET route that takes no parameters or body in the request and
|
||||
returns a single number.
|
||||
</p>
|
||||
<EuiButton
|
||||
data-test-subj="routingExampleFetchRandomNumber"
|
||||
disabled={isFetching}
|
||||
onClick={() => doFetch()}
|
||||
>
|
||||
{isFetching ? <EuiLoadingSpinner /> : 'Generate a random number'}
|
||||
</EuiButton>
|
||||
|
||||
{error !== undefined ? (
|
||||
<EuiCallOut color="danger" iconType="alert">
|
||||
{error}
|
||||
</EuiCallOut>
|
||||
) : null}
|
||||
{randomNumber > -1 ? (
|
||||
<h2>
|
||||
Random number is <div data-test-subj="routingExampleRandomNumber">{randomNumber}</div>
|
||||
</h2>
|
||||
) : null}
|
||||
</EuiText>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
78
examples/routing_example/public/services.ts
Normal file
78
examples/routing_example/public/services.ts
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { CoreStart, HttpFetchError } from 'kibana/public';
|
||||
import {
|
||||
RANDOM_NUMBER_ROUTE_PATH,
|
||||
RANDOM_NUMBER_BETWEEN_ROUTE_PATH,
|
||||
POST_MESSAGE_ROUTE_PATH,
|
||||
INTERNAL_GET_MESSAGE_BY_ID_ROUTE,
|
||||
} from '../common';
|
||||
|
||||
export interface Services {
|
||||
fetchRandomNumber: () => Promise<number | HttpFetchError>;
|
||||
fetchRandomNumberBetween: (max: number) => Promise<number | HttpFetchError>;
|
||||
postMessage: (message: string, id: string) => Promise<undefined | HttpFetchError>;
|
||||
getMessageById: (id: string) => Promise<string | HttpFetchError>;
|
||||
addSuccessToast: (message: string) => void;
|
||||
}
|
||||
|
||||
export function getServices(core: CoreStart): Services {
|
||||
return {
|
||||
addSuccessToast: (message: string) => core.notifications.toasts.addSuccess(message),
|
||||
fetchRandomNumber: async () => {
|
||||
try {
|
||||
const response = await core.http.fetch<{ randomNumber: number }>(RANDOM_NUMBER_ROUTE_PATH);
|
||||
return response.randomNumber;
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
},
|
||||
fetchRandomNumberBetween: async (max: number) => {
|
||||
try {
|
||||
const response = await core.http.fetch<{ randomNumber: number }>(
|
||||
RANDOM_NUMBER_BETWEEN_ROUTE_PATH,
|
||||
{ query: { max } }
|
||||
);
|
||||
return response.randomNumber;
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
},
|
||||
postMessage: async (message: string, id: string) => {
|
||||
try {
|
||||
await core.http.post(`${POST_MESSAGE_ROUTE_PATH}/${id}`, {
|
||||
body: JSON.stringify({ message }),
|
||||
});
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
},
|
||||
getMessageById: async (id: string) => {
|
||||
try {
|
||||
const response = await core.http.get<{ message: string }>(
|
||||
`${INTERNAL_GET_MESSAGE_BY_ID_ROUTE}/${id}`
|
||||
);
|
||||
return response.message;
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
24
examples/routing_example/server/index.ts
Normal file
24
examples/routing_example/server/index.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { PluginInitializer } from 'kibana/server';
|
||||
|
||||
import { RoutingExamplePlugin } from './plugin';
|
||||
|
||||
export const plugin: PluginInitializer<{}, {}> = () => new RoutingExamplePlugin();
|
37
examples/routing_example/server/plugin.ts
Normal file
37
examples/routing_example/server/plugin.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, CoreStart } from 'kibana/server';
|
||||
import { registerRoutes } from './routes';
|
||||
|
||||
export class RoutingExamplePlugin implements Plugin<{}, {}> {
|
||||
public setup(core: CoreSetup) {
|
||||
const router = core.http.createRouter();
|
||||
|
||||
registerRoutes(router);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
return {};
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
}
|
19
examples/routing_example/server/routes/index.ts
Normal file
19
examples/routing_example/server/routes/index.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
export { registerRoutes } from './register_routes';
|
90
examples/routing_example/server/routes/message_routes.ts
Normal file
90
examples/routing_example/server/routes/message_routes.ts
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { POST_MESSAGE_ROUTE_PATH, INTERNAL_GET_MESSAGE_BY_ID_ROUTE } from '../../common';
|
||||
|
||||
import { IRouter } from '../../../../src/core/server';
|
||||
|
||||
/**
|
||||
*
|
||||
* NOTE: DON'T USE IN MEMORY DATA STRUCTURES TO STORE DATA!
|
||||
*
|
||||
* That won't work in a system with multiple Kibanas, which is a setup we recommend for
|
||||
* load balancing. I'm only doing so here to simplify the routing example. In real life,
|
||||
* Elasticsearch should be used to persist data that can be shared across multiple Kibana
|
||||
* instances.
|
||||
*/
|
||||
|
||||
const messages: { [key: string]: string } = {};
|
||||
|
||||
/**
|
||||
* @param router Pushes a message with an id onto an in memory map.
|
||||
*/
|
||||
export function registerPostMessageRoute(router: IRouter) {
|
||||
router.post(
|
||||
{
|
||||
path: `${POST_MESSAGE_ROUTE_PATH}/{id}`,
|
||||
validate: {
|
||||
params: schema.object({
|
||||
// This parameter name matches the one in POST_MESSAGE_ROUTE_PATH: `api/post_message/{id}`.
|
||||
// Params are often used for ids like this.
|
||||
id: schema.string(),
|
||||
}),
|
||||
body: schema.object({
|
||||
message: schema.string({ maxLength: 100 }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
if (messages[request.params.id]) {
|
||||
return response.badRequest({
|
||||
body: `Message with id ${request.params.id} already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
// See note above. NEVER DO THIS IN REAL CODE! Data should only be persisted in Elasticsearch.
|
||||
messages[request.params.id] = request.body.message;
|
||||
|
||||
return response.ok();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param router Returns the message with the given id from an in memory array.
|
||||
*/
|
||||
export function registerGetMessageByIdRoute(router: IRouter) {
|
||||
router.get(
|
||||
{
|
||||
path: `${INTERNAL_GET_MESSAGE_BY_ID_ROUTE}/{id}`,
|
||||
validate: {
|
||||
params: schema.object({
|
||||
id: schema.string(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
if (!messages[request.params.id]) {
|
||||
return response.notFound();
|
||||
}
|
||||
return response.ok({ body: { message: messages[request.params.id] } });
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { RANDOM_NUMBER_BETWEEN_ROUTE_PATH } from '../../common';
|
||||
|
||||
import { IRouter } from '../../../../src/core/server';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param router Registers a get route that returns a random number between one and another number suplied by the user.
|
||||
*/
|
||||
export function registerGetRandomNumberBetweenRoute(router: IRouter) {
|
||||
router.get(
|
||||
{
|
||||
path: RANDOM_NUMBER_BETWEEN_ROUTE_PATH,
|
||||
validate: {
|
||||
query: schema.object({
|
||||
max: schema.number({ defaultValue: 10 }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
return response.ok({
|
||||
body: {
|
||||
randomNumber: Math.random() * request.query.max,
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { RANDOM_NUMBER_ROUTE_PATH } from '../../common';
|
||||
|
||||
import { IRouter } from '../../../../src/core/server';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param router Registers a get route that returns a random number between one and ten. It has no input
|
||||
* parameters, and returns a random number in the body.
|
||||
*/
|
||||
export function registerGetRandomNumberRoute(router: IRouter) {
|
||||
router.get(
|
||||
{
|
||||
path: RANDOM_NUMBER_ROUTE_PATH,
|
||||
validate: {},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
return response.ok({
|
||||
body: {
|
||||
randomNumber: Math.random() * 10,
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
30
examples/routing_example/server/routes/register_routes.ts
Normal file
30
examples/routing_example/server/routes/register_routes.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { IRouter } from 'kibana/server';
|
||||
import { registerGetRandomNumberRoute } from './random_number_generator';
|
||||
import { registerGetRandomNumberBetweenRoute } from './random_number_between_generator';
|
||||
import { registerGetMessageByIdRoute, registerPostMessageRoute } from './message_routes';
|
||||
|
||||
export function registerRoutes(router: IRouter) {
|
||||
registerGetRandomNumberRoute(router);
|
||||
registerGetRandomNumberBetweenRoute(router);
|
||||
registerGetMessageByIdRoute(router);
|
||||
registerPostMessageRoute(router);
|
||||
}
|
16
examples/routing_example/tsconfig.json
Normal file
16
examples/routing_example/tsconfig.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"public/**/*.ts",
|
||||
"public/**/*.tsx",
|
||||
"server/**/*.ts",
|
||||
"common/**/*.ts",
|
||||
"../../typings/**/*",
|
||||
],
|
||||
"exclude": []
|
||||
}
|
|
@ -29,6 +29,7 @@ export default async function ({ readConfigFile }) {
|
|||
require.resolve('./bfetch_explorer'),
|
||||
require.resolve('./ui_actions'),
|
||||
require.resolve('./state_sync'),
|
||||
require.resolve('./routing'),
|
||||
],
|
||||
services: {
|
||||
...functionalConfig.get('services'),
|
||||
|
|
72
test/examples/routing/index.ts
Normal file
72
test/examples/routing/index.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from 'test/functional/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) {
|
||||
const retry = getService('retry');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const PageObjects = getPageObjects(['common']);
|
||||
|
||||
describe('routing examples', function () {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('routingExample');
|
||||
});
|
||||
|
||||
it('basic get example', async () => {
|
||||
await retry.try(async () => {
|
||||
await testSubjects.click('routingExampleFetchRandomNumber');
|
||||
const numberAsString = await testSubjects.getVisibleText('routingExampleRandomNumber');
|
||||
expect(numberAsString).to.not.be(undefined);
|
||||
const number = parseFloat(numberAsString);
|
||||
expect(number).to.be.lessThan(10);
|
||||
expect(number).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('basic get example with query param', async () => {
|
||||
await retry.try(async () => {
|
||||
await testSubjects.setValue('routingExampleMaxRandomNumberBetween', '3');
|
||||
await testSubjects.click('routingExampleFetchRandomNumberBetween');
|
||||
const numberAsString = await testSubjects.getVisibleText(
|
||||
'routingExampleRandomNumberBetween'
|
||||
);
|
||||
expect(numberAsString).to.not.be(undefined);
|
||||
const number = parseFloat(numberAsString);
|
||||
expect(number).to.be.lessThan(3);
|
||||
expect(number).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('post and get message example', async () => {
|
||||
await testSubjects.setValue('routingExampleSetMessageId', '234');
|
||||
await testSubjects.setValue('routingExampleSetMessage', 'hello!');
|
||||
await testSubjects.click('routingExamplePostMessage');
|
||||
await testSubjects.setValue('routingExampleGetMessageId', '234');
|
||||
await testSubjects.click('routingExampleFetchMessage');
|
||||
|
||||
await retry.try(async () => {
|
||||
const message = await testSubjects.getVisibleText('routingExampleGetMessage');
|
||||
expect(message).to.be('hello!');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue