[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:
parent
9dec97b5f4
commit
e25c9dfece
6 changed files with 277 additions and 3 deletions
|
@ -6,7 +6,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BrowserFields, ConfigKeys } from '../types';
|
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>;
|
export type BrowserFormatMap = Record<keyof BrowserFields, Formatter>;
|
||||||
|
|
||||||
|
@ -15,7 +20,7 @@ export const browserFormatters: BrowserFormatMap = {
|
||||||
[ConfigKeys.SOURCE_ZIP_USERNAME]: null,
|
[ConfigKeys.SOURCE_ZIP_USERNAME]: null,
|
||||||
[ConfigKeys.SOURCE_ZIP_PASSWORD]: null,
|
[ConfigKeys.SOURCE_ZIP_PASSWORD]: null,
|
||||||
[ConfigKeys.SOURCE_ZIP_FOLDER]: 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.PARAMS]: null,
|
||||||
[ConfigKeys.SCREENSHOTS]: null,
|
[ConfigKeys.SCREENSHOTS]: null,
|
||||||
[ConfigKeys.SYNTHETICS_ARGS]: (fields) =>
|
[ConfigKeys.SYNTHETICS_ARGS]: (fields) =>
|
||||||
|
|
|
@ -68,6 +68,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
{
|
{
|
||||||
id: 'syntheticsBrowserZipURLConfig',
|
id: 'syntheticsBrowserZipURLConfig',
|
||||||
name: zipUrlLabel,
|
name: zipUrlLabel,
|
||||||
|
'data-test-subj': `syntheticsSourceTab__zipUrl`,
|
||||||
content: (
|
content: (
|
||||||
<>
|
<>
|
||||||
<EuiSpacer size="m" />
|
<EuiSpacer size="m" />
|
||||||
|
@ -92,6 +93,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
setConfig((prevConfig) => ({ ...prevConfig, zipUrl: value }))
|
setConfig((prevConfig) => ({ ...prevConfig, zipUrl: value }))
|
||||||
}
|
}
|
||||||
value={config.zipUrl}
|
value={config.zipUrl}
|
||||||
|
data-test-subj="syntheticsBrowserZipUrl"
|
||||||
/>
|
/>
|
||||||
</EuiFormRow>
|
</EuiFormRow>
|
||||||
<EuiFormRow
|
<EuiFormRow
|
||||||
|
@ -114,6 +116,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
setConfig((prevConfig) => ({ ...prevConfig, folder: value }))
|
setConfig((prevConfig) => ({ ...prevConfig, folder: value }))
|
||||||
}
|
}
|
||||||
value={config.folder}
|
value={config.folder}
|
||||||
|
data-test-subj="syntheticsBrowserZipUrlFolder"
|
||||||
/>
|
/>
|
||||||
</EuiFormRow>
|
</EuiFormRow>
|
||||||
<EuiFormRow
|
<EuiFormRow
|
||||||
|
@ -142,6 +145,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
languageId={MonacoEditorLangId.JSON}
|
languageId={MonacoEditorLangId.JSON}
|
||||||
onChange={(code) => setConfig((prevConfig) => ({ ...prevConfig, params: code }))}
|
onChange={(code) => setConfig((prevConfig) => ({ ...prevConfig, params: code }))}
|
||||||
value={config.params}
|
value={config.params}
|
||||||
|
data-test-subj="syntheticsBrowserZipUrlParams"
|
||||||
/>
|
/>
|
||||||
</EuiFormRow>
|
</EuiFormRow>
|
||||||
<EuiFormRow
|
<EuiFormRow
|
||||||
|
@ -164,6 +168,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
setConfig((prevConfig) => ({ ...prevConfig, username: value }))
|
setConfig((prevConfig) => ({ ...prevConfig, username: value }))
|
||||||
}
|
}
|
||||||
value={config.username}
|
value={config.username}
|
||||||
|
data-test-subj="syntheticsBrowserZipUrlUsername"
|
||||||
/>
|
/>
|
||||||
</EuiFormRow>
|
</EuiFormRow>
|
||||||
<EuiFormRow
|
<EuiFormRow
|
||||||
|
@ -186,6 +191,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
setConfig((prevConfig) => ({ ...prevConfig, password: value }))
|
setConfig((prevConfig) => ({ ...prevConfig, password: value }))
|
||||||
}
|
}
|
||||||
value={config.password}
|
value={config.password}
|
||||||
|
data-test-subj="syntheticsBrowserZipUrlPassword"
|
||||||
/>
|
/>
|
||||||
</EuiFormRow>
|
</EuiFormRow>
|
||||||
</>
|
</>
|
||||||
|
@ -199,6 +205,7 @@ export const SourceField = ({ onChange, defaultConfig = defaultValues }: Props)
|
||||||
defaultMessage="Inline script"
|
defaultMessage="Inline script"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
'data-test-subj': `syntheticsSourceTab__inline`,
|
||||||
content: (
|
content: (
|
||||||
<EuiFormRow
|
<EuiFormRow
|
||||||
isInvalid={!config.inlineScript}
|
isInvalid={!config.inlineScript}
|
||||||
|
|
|
@ -5,7 +5,12 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { arrayToJsonFormatter, objectToJsonFormatter, secondsToCronFormatter } from './formatters';
|
import {
|
||||||
|
arrayToJsonFormatter,
|
||||||
|
objectToJsonFormatter,
|
||||||
|
stringToJsonFormatter,
|
||||||
|
secondsToCronFormatter,
|
||||||
|
} from './formatters';
|
||||||
|
|
||||||
describe('formatters', () => {
|
describe('formatters', () => {
|
||||||
describe('cronToSecondsNormalizer', () => {
|
describe('cronToSecondsNormalizer', () => {
|
||||||
|
@ -33,4 +38,16 @@ describe('formatters', () => {
|
||||||
expect(objectToJsonFormatter({})).toEqual(null);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,3 +30,5 @@ export const secondsToCronFormatter = (value: string = '') => (value ? `${value}
|
||||||
|
|
||||||
export const objectToJsonFormatter = (value: Record<string, string> = {}) =>
|
export const objectToJsonFormatter = (value: Record<string, string> = {}) =>
|
||||||
Object.keys(value).length ? JSON.stringify(value) : null;
|
Object.keys(value).length ? JSON.stringify(value) : null;
|
||||||
|
|
||||||
|
export const stringToJsonFormatter = (value: string = '') => (value ? JSON.stringify(value) : null);
|
||||||
|
|
|
@ -72,6 +72,58 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
],
|
],
|
||||||
...config,
|
...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}`,
|
type: `synthetics/${monitorType}`,
|
||||||
use_output: 'default',
|
use_output: 'default',
|
||||||
|
@ -95,6 +147,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
host,
|
host,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const generateBrowserConfig = (config: Record<string, string>): Record<string, string> => ({
|
||||||
|
...basicConfig,
|
||||||
|
...config,
|
||||||
|
});
|
||||||
|
|
||||||
describe('displays custom UI', () => {
|
describe('displays custom UI', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const version = await uptimeService.syntheticsPackage.getSyntheticsPackageVersion();
|
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],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,16 @@ export function SyntheticsIntegrationPageProvider({
|
||||||
*/
|
*/
|
||||||
async configureRequestBody(testSubj: string, value: string) {
|
async configureRequestBody(testSubj: string, value: string) {
|
||||||
await testSubjects.click(`syntheticsRequestBodyTab__${testSubj}`);
|
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 codeEditorContainer = await testSubjects.find('codeEditorContainer');
|
||||||
const textArea = await codeEditorContainer.findByCssSelector('textarea');
|
const textArea = await codeEditorContainer.findByCssSelector('textarea');
|
||||||
await textArea.clearValue();
|
await textArea.clearValue();
|
||||||
|
@ -273,6 +283,40 @@ export function SyntheticsIntegrationPageProvider({
|
||||||
await this.fillTextInputByTestSubj('syntheticsICMPHostField', host);
|
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
|
* Enables TLS
|
||||||
*/
|
*/
|
||||||
|
@ -376,5 +420,16 @@ export function SyntheticsIntegrationPageProvider({
|
||||||
await label.click();
|
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);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue