[Uptime] [Synthetics Integration] browser functional tests (#110648)

* uptime - synthetics integration - add browser functional tests

* focus tests

* unfocus test

* Uptime - Synthetics Integration - adds stringToJsonFormatter
This commit is contained in:
Dominique Clarke 2021-09-01 14:54:00 -04:00 committed by GitHub
parent 9dec97b5f4
commit e25c9dfece
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 277 additions and 3 deletions

View file

@ -6,7 +6,12 @@
*/
import { BrowserFields, ConfigKeys } from '../types';
import { Formatter, commonFormatters, arrayToJsonFormatter } from '../common/formatters';
import {
Formatter,
commonFormatters,
arrayToJsonFormatter,
stringToJsonFormatter,
} from '../common/formatters';
export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;
@ -15,7 +20,7 @@ export const browserFormatters: BrowserFormatMap = {
[ConfigKeys.SOURCE_ZIP_USERNAME]: null,
[ConfigKeys.SOURCE_ZIP_PASSWORD]: null,
[ConfigKeys.SOURCE_ZIP_FOLDER]: null,
[ConfigKeys.SOURCE_INLINE]: (fields) => JSON.stringify(fields[ConfigKeys.SOURCE_INLINE]),
[ConfigKeys.SOURCE_INLINE]: (fields) => stringToJsonFormatter(fields[ConfigKeys.SOURCE_INLINE]),
[ConfigKeys.PARAMS]: null,
[ConfigKeys.SCREENSHOTS]: null,
[ConfigKeys.SYNTHETICS_ARGS]: (fields) =>

View file

@ -68,6 +68,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
{
id: 'syntheticsBrowserZipURLConfig',
name: zipUrlLabel,
'data-test-subj': `syntheticsSourceTab__zipUrl`,
content: (
<>
<EuiSpacer size="m" />
@ -92,6 +93,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
setConfig((prevConfig) => ({ ...prevConfig, zipUrl: value }))
}
value={config.zipUrl}
data-test-subj="syntheticsBrowserZipUrl"
/>
</EuiFormRow>
<EuiFormRow
@ -114,6 +116,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
setConfig((prevConfig) => ({ ...prevConfig, folder: value }))
}
value={config.folder}
data-test-subj="syntheticsBrowserZipUrlFolder"
/>
</EuiFormRow>
<EuiFormRow
@ -142,6 +145,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
languageId={MonacoEditorLangId.JSON}
onChange={(code) => setConfig((prevConfig) => ({ ...prevConfig, params: code }))}
value={config.params}
data-test-subj="syntheticsBrowserZipUrlParams"
/>
</EuiFormRow>
<EuiFormRow
@ -164,6 +168,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
setConfig((prevConfig) => ({ ...prevConfig, username: value }))
}
value={config.username}
data-test-subj="syntheticsBrowserZipUrlUsername"
/>
</EuiFormRow>
<EuiFormRow
@ -186,6 +191,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
setConfig((prevConfig) => ({ ...prevConfig, password: value }))
}
value={config.password}
data-test-subj="syntheticsBrowserZipUrlPassword"
/>
</EuiFormRow>
</>
@ -199,6 +205,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
defaultMessage="Inline script"
/>
),
'data-test-subj': `syntheticsSourceTab__inline`,
content: (
<EuiFormRow
isInvalid={!config.inlineScript}

View file

@ -5,7 +5,12 @@
* 2.0.
*/
import { arrayToJsonFormatter, objectToJsonFormatter, secondsToCronFormatter } from './formatters';
import {
arrayToJsonFormatter,
objectToJsonFormatter,
stringToJsonFormatter,
secondsToCronFormatter,
} from './formatters';
describe('formatters', () => {
describe('cronToSecondsNormalizer', () => {
@ -33,4 +38,16 @@ describe('formatters', () => {
expect(objectToJsonFormatter({})).toEqual(null);
});
});
describe('stringToJsonFormatter', () => {
it('takes a string and returns an json string', () => {
expect(stringToJsonFormatter('step("test step", () => {})')).toEqual(
'"step(\\"test step\\", () => {})"'
);
});
it('returns null if the string is falsy', () => {
expect(stringToJsonFormatter('')).toEqual(null);
});
});
});

View file

@ -30,3 +30,5 @@ export const secondsToCronFormatter = (value: string = '') => (value ? `${value}
export const objectToJsonFormatter = (value: Record<string, string> = {}) =>
Object.keys(value).length ? JSON.stringify(value) : null;
export const stringToJsonFormatter = (value: string = '') => (value ? JSON.stringify(value) : null);

View file

@ -72,6 +72,58 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
],
...config,
},
...(monitorType === 'browser'
? [
{
data_stream: {
dataset: 'browser.network',
type: 'synthetics',
},
id: `${getSyntheticsPolicy(agentFullPolicy)?.streams?.[1]?.id}`,
processors: [
{
add_observer_metadata: {
geo: {
name: 'Fleet managed',
},
},
},
{
add_fields: {
fields: {
'monitor.fleet_managed': true,
},
target: '',
},
},
],
},
{
data_stream: {
dataset: 'browser.screenshot',
type: 'synthetics',
},
id: `${getSyntheticsPolicy(agentFullPolicy)?.streams?.[2]?.id}`,
processors: [
{
add_observer_metadata: {
geo: {
name: 'Fleet managed',
},
},
},
{
add_fields: {
fields: {
'monitor.fleet_managed': true,
},
target: '',
},
},
],
},
]
: []),
],
type: `synthetics/${monitorType}`,
use_output: 'default',
@ -95,6 +147,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
host,
});
const generateBrowserConfig = (config: Record<string, string>): Record<string, string> => ({
...basicConfig,
...config,
});
describe('displays custom UI', () => {
before(async () => {
const version = await uptimeService.syntheticsPackage.getSyntheticsPackageVersion();
@ -439,6 +496,137 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
})
);
});
it('allows saving browser monitor', async () => {
// This test ensures that updates made to the Synthetics Policy are carried all the way through
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
const config = generateBrowserConfig({
zipUrl: 'http://test.zip',
params: JSON.stringify({ url: 'http://localhost:8080' }),
folder: 'folder',
username: 'username',
password: 'password',
});
await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config);
await uptimePage.syntheticsIntegration.confirmAndSave();
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
const agentPolicyId = agentPolicy.id;
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
agentPolicyId
);
expect(getSyntheticsPolicy(agentFullPolicy)).to.eql(
generatePolicy({
agentFullPolicy,
version,
name: monitorName,
monitorType: 'browser',
config: {
screenshots: 'on',
schedule: '@every 3m',
timeout: '16s',
tags: [config.tags],
'service.name': config.apmServiceName,
'source.zip_url.url': config.zipUrl,
'source.zip_url.folder': config.folder,
'source.zip_url.username': config.username,
'source.zip_url.password': config.password,
params: JSON.parse(config.params),
},
})
);
});
it('allows saving browser monitor with inline script', async () => {
// This test ensures that updates made to the Synthetics Policy are carried all the way through
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
const config = generateBrowserConfig({
inlineScript:
'step("load homepage", async () => { await page.goto(\'https://www.elastic.co\'); });',
});
await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config, true);
await uptimePage.syntheticsIntegration.confirmAndSave();
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
const agentPolicyId = agentPolicy.id;
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
agentPolicyId
);
expect(getSyntheticsPolicy(agentFullPolicy)).to.eql(
generatePolicy({
agentFullPolicy,
version,
name: monitorName,
monitorType: 'browser',
config: {
screenshots: 'on',
schedule: '@every 3m',
timeout: '16s',
tags: [config.tags],
'service.name': config.apmServiceName,
'source.inline.script': config.inlineScript,
},
})
);
});
it('allows saving browser monitor advanced options', async () => {
// This test ensures that updates made to the Synthetics Policy are carried all the way through
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
const config = generateBrowserConfig({
zipUrl: 'http://test.zip',
params: JSON.stringify({ url: 'http://localhost:8080' }),
folder: 'folder',
username: 'username',
password: 'password',
});
const advancedConfig = {
screenshots: 'off',
syntheticsArgs: '-ssBlocks',
};
await uptimePage.syntheticsIntegration.createBasicBrowserMonitorDetails(config);
await uptimePage.syntheticsIntegration.configureBrowserAdvancedOptions(advancedConfig);
await uptimePage.syntheticsIntegration.confirmAndSave();
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
const agentPolicyId = agentPolicy.id;
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
agentPolicyId
);
expect(getSyntheticsPolicy(agentFullPolicy)).to.eql(
generatePolicy({
agentFullPolicy,
version,
name: monitorName,
monitorType: 'browser',
config: {
screenshots: advancedConfig.screenshots,
schedule: '@every 3m',
timeout: '16s',
tags: [config.tags],
'service.name': config.apmServiceName,
'source.zip_url.url': config.zipUrl,
'source.zip_url.folder': config.folder,
'source.zip_url.username': config.username,
'source.zip_url.password': config.password,
params: JSON.parse(config.params),
synthetics_args: [advancedConfig.syntheticsArgs],
},
})
);
});
});
});
}

View file

@ -205,6 +205,16 @@ export function SyntheticsIntegrationPageProvider({
*/
async configureRequestBody(testSubj: string, value: string) {
await testSubjects.click(`syntheticsRequestBodyTab__${testSubj}`);
await this.fillCodeEditor(value);
},
/**
*
* Fills the monaco code editor
* @params value {string} value of code input
*
*/
async fillCodeEditor(value: string) {
const codeEditorContainer = await testSubjects.find('codeEditorContainer');
const textArea = await codeEditorContainer.findByCssSelector('textarea');
await textArea.clearValue();
@ -273,6 +283,40 @@ export function SyntheticsIntegrationPageProvider({
await this.fillTextInputByTestSubj('syntheticsICMPHostField', host);
},
/**
* Creates a basic browser monitor
* @params name {string} the name of the monitor
* @params zipUrl {string} the zip url of the synthetics suites
*/
async createBasicBrowserMonitorDetails(
{
name,
inlineScript,
zipUrl,
folder,
params,
username,
password,
apmServiceName,
tags,
}: Record<string, string>,
isInline: boolean = false
) {
await this.selectMonitorType('browser');
await this.fillTextInputByTestSubj('packagePolicyNameInput', name);
await this.createBasicMonitorDetails({ name, apmServiceName, tags });
if (isInline) {
await testSubjects.click('syntheticsSourceTab__inline');
await this.fillCodeEditor(inlineScript);
return;
}
await this.fillTextInputByTestSubj('syntheticsBrowserZipUrl', zipUrl);
await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlFolder', folder);
await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlUsername', username);
await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlPassword', password);
await this.fillCodeEditor(params);
},
/**
* Enables TLS
*/
@ -376,5 +420,16 @@ export function SyntheticsIntegrationPageProvider({
await label.click();
}
},
/**
* Configure browser advanced settings
* @params name {string} the name of the monitor
* @params zipUrl {string} the zip url of the synthetics suites
*/
async configureBrowserAdvancedOptions({ screenshots, syntheticsArgs }: Record<string, string>) {
await testSubjects.click('syntheticsBrowserAdvancedFieldsAccordion');
await testSubjects.selectValue('syntheticsBrowserScreenshots', screenshots);
await this.setComboBox('syntheticsBrowserSyntheticsArgs', syntheticsArgs);
},
};
}