Skip to content

Commit 4dc08c6

Browse files
committed
[ML] Jest tests for parseMessages(). Shared mocks for API integration tests and jest tests.
1 parent e4adf5e commit 4dc08c6

3 files changed

Lines changed: 267 additions & 66 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
/* To keep tests in sync, these mocks should be used in API intregation tests
9+
* as expected values to check against, and in the client side jest tests to be
10+
* the values used as function arguments for `parseMessages()` to retrieve the
11+
* messages populated with translations and documentation links.
12+
*/
13+
14+
export const basicValidJobMessages = [
15+
{
16+
id: 'job_id_valid',
17+
},
18+
{
19+
id: 'detectors_function_not_empty',
20+
},
21+
{
22+
id: 'success_bucket_span',
23+
bucketSpan: '15m',
24+
},
25+
{
26+
id: 'success_time_range',
27+
},
28+
{
29+
id: 'success_mml',
30+
},
31+
];
32+
33+
export const basicInvalidJobMessages = [
34+
{
35+
id: 'job_id_invalid',
36+
},
37+
{
38+
id: 'detectors_function_not_empty',
39+
},
40+
{
41+
id: 'bucket_span_valid',
42+
bucketSpan: '15m',
43+
},
44+
{
45+
id: 'skipped_extended_tests',
46+
},
47+
];
48+
49+
export const nonBasicIssuesMessages = [
50+
{
51+
id: 'job_id_valid',
52+
},
53+
{
54+
id: 'detectors_function_not_empty',
55+
},
56+
{
57+
id: 'cardinality_model_plot_high',
58+
},
59+
{
60+
id: 'cardinality_partition_field',
61+
fieldName: 'order_id',
62+
},
63+
{
64+
id: 'bucket_span_high',
65+
},
66+
{
67+
bucketSpanCompareFactor: 25,
68+
id: 'time_range_short',
69+
minTimeSpanReadable: '2 hours',
70+
},
71+
{
72+
id: 'success_influencers',
73+
},
74+
{
75+
id: 'half_estimated_mml_greater_than_mml',
76+
mml: '1MB',
77+
},
78+
{
79+
id: 'missing_summary_count_field_name',
80+
},
81+
];
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { docLinksServiceMock } from 'src/core/public/mocks';
9+
10+
import { parseMessages } from './messages';
11+
12+
import {
13+
basicValidJobMessages,
14+
basicInvalidJobMessages,
15+
nonBasicIssuesMessages,
16+
} from './messages.test.mock';
17+
18+
describe('Constants: Messages parseMessages()', () => {
19+
const docLinksService = docLinksServiceMock.createStartContract();
20+
21+
it('should parse valid job configuration messages', () => {
22+
expect(parseMessages(basicValidJobMessages, docLinksService)).toStrictEqual([
23+
{
24+
heading: 'Job ID format is valid',
25+
id: 'job_id_valid',
26+
status: 'success',
27+
text:
28+
'Lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores, starts and ends with an alphanumeric character, and is no more than 64 characters long.',
29+
url:
30+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/ml-job-resource.html#ml-job-resource',
31+
},
32+
{
33+
heading: 'Detector functions',
34+
id: 'detectors_function_not_empty',
35+
status: 'success',
36+
text: 'Presence of detector functions validated in all detectors.',
37+
url:
38+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#detectors',
39+
},
40+
{
41+
bucketSpan: '15m',
42+
heading: 'Bucket span',
43+
id: 'success_bucket_span',
44+
status: 'success',
45+
text: 'Format of "15m" is valid and passed validation checks.',
46+
url:
47+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#bucket-span',
48+
},
49+
{
50+
heading: 'Time range',
51+
id: 'success_time_range',
52+
status: 'success',
53+
text: 'Valid and long enough to model patterns in the data.',
54+
},
55+
{
56+
heading: 'Model memory limit',
57+
id: 'success_mml',
58+
status: 'success',
59+
text: 'Valid and within the estimated model memory limit.',
60+
url:
61+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#model-memory-limits',
62+
},
63+
]);
64+
});
65+
66+
it('should parse basic invalid job configuration messages', () => {
67+
expect(parseMessages(basicInvalidJobMessages, docLinksService)).toStrictEqual([
68+
{
69+
id: 'job_id_invalid',
70+
status: 'error',
71+
text:
72+
'Job ID is invalid. It can contain lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores and must start and end with an alphanumeric character.',
73+
url:
74+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/ml-job-resource.html#ml-job-resource',
75+
},
76+
{
77+
heading: 'Detector functions',
78+
id: 'detectors_function_not_empty',
79+
status: 'success',
80+
text: 'Presence of detector functions validated in all detectors.',
81+
url:
82+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#detectors',
83+
},
84+
{
85+
bucketSpan: '15m',
86+
heading: 'Bucket span',
87+
id: 'bucket_span_valid',
88+
status: 'success',
89+
text: 'Format of "15m" is valid.',
90+
url:
91+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/ml-job-resource.html#ml-analysisconfig',
92+
},
93+
{
94+
id: 'skipped_extended_tests',
95+
status: 'warning',
96+
text:
97+
'Skipped additional checks because the basic requirements of the job configuration were not met.',
98+
},
99+
]);
100+
});
101+
102+
it('should parse non-basic issues messages', () => {
103+
expect(parseMessages(nonBasicIssuesMessages, docLinksService)).toStrictEqual([
104+
{
105+
heading: 'Job ID format is valid',
106+
id: 'job_id_valid',
107+
status: 'success',
108+
text:
109+
'Lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores, starts and ends with an alphanumeric character, and is no more than 64 characters long.',
110+
url:
111+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/ml-job-resource.html#ml-job-resource',
112+
},
113+
{
114+
heading: 'Detector functions',
115+
id: 'detectors_function_not_empty',
116+
status: 'success',
117+
text: 'Presence of detector functions validated in all detectors.',
118+
url:
119+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#detectors',
120+
},
121+
{
122+
id: 'cardinality_model_plot_high',
123+
status: 'warning',
124+
text:
125+
'The estimated cardinality of undefined of fields relevant to creating model plots might result in resource intensive jobs.',
126+
},
127+
{
128+
fieldName: 'order_id',
129+
id: 'cardinality_partition_field',
130+
status: 'warning',
131+
text:
132+
'Cardinality of partition_field "order_id" is above 1000 and might result in high memory usage.',
133+
url:
134+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#cardinality',
135+
},
136+
{
137+
heading: 'Bucket span',
138+
id: 'bucket_span_high',
139+
status: 'info',
140+
text:
141+
'Bucket span is 1 day or more. Be aware that days are considered as UTC days, not local days.',
142+
url:
143+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#bucket-span',
144+
},
145+
{
146+
bucketSpanCompareFactor: 25,
147+
heading: 'Time range',
148+
id: 'time_range_short',
149+
minTimeSpanReadable: '2 hours',
150+
status: 'warning',
151+
text:
152+
'The selected or available time range might be too short. The recommended minimum time range should be at least 2 hours and 25 times the bucket span.',
153+
},
154+
{
155+
id: 'success_influencers',
156+
status: 'success',
157+
text: 'Influencer configuration passed the validation checks.',
158+
url:
159+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/ml-influencers.html',
160+
},
161+
{
162+
id: 'half_estimated_mml_greater_than_mml',
163+
mml: '1MB',
164+
status: 'warning',
165+
text:
166+
'The specified model memory limit is less than half of the estimated model memory limit and will likely hit the hard limit.',
167+
url:
168+
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#model-memory-limits',
169+
},
170+
{
171+
id: 'missing_summary_count_field_name',
172+
status: 'error',
173+
text:
174+
'A job configured with a datafeed with aggregations must set summary_count_field_name; use doc_count or suitable alternative.',
175+
},
176+
]);
177+
});
178+
});

x-pack/test/api_integration/apis/ml/job_validation/validate.ts

Lines changed: 8 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
*/
77

88
import expect from '@kbn/expect';
9+
import {
10+
basicValidJobMessages,
11+
basicInvalidJobMessages,
12+
nonBasicIssuesMessages,
13+
} from '../../../../../../x-pack/plugins/ml/common/constants/messages.test.mock';
914
import { FtrProviderContext } from '../../../ftr_provider_context';
1015
import { USER } from '../../../../functional/services/ml/security_common';
1116
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api';
@@ -72,24 +77,7 @@ export default ({ getService }: FtrProviderContext) => {
7277
.send(requestBody)
7378
.expect(200);
7479

75-
expect(body).to.eql([
76-
{
77-
id: 'job_id_valid',
78-
},
79-
{
80-
id: 'detectors_function_not_empty',
81-
},
82-
{
83-
id: 'success_bucket_span',
84-
bucketSpan: '15m',
85-
},
86-
{
87-
id: 'success_time_range',
88-
},
89-
{
90-
id: 'success_mml',
91-
},
92-
]);
80+
expect(body).to.eql(basicValidJobMessages);
9381
});
9482

9583
it('should recognize a basic invalid job configuration and skip advanced checks', async () => {
@@ -133,21 +121,7 @@ export default ({ getService }: FtrProviderContext) => {
133121
.send(requestBody)
134122
.expect(200);
135123

136-
expect(body).to.eql([
137-
{
138-
id: 'job_id_invalid',
139-
},
140-
{
141-
id: 'detectors_function_not_empty',
142-
},
143-
{
144-
id: 'bucket_span_valid',
145-
bucketSpan: '15m',
146-
},
147-
{
148-
id: 'skipped_extended_tests',
149-
},
150-
]);
124+
expect(body).to.eql(basicInvalidJobMessages);
151125
});
152126

153127
it('should recognize non-basic issues in job configuration', async () => {
@@ -206,39 +180,7 @@ export default ({ getService }: FtrProviderContext) => {
206180
}
207181
});
208182

209-
const expectedResponse = [
210-
{
211-
id: 'job_id_valid',
212-
},
213-
{
214-
id: 'detectors_function_not_empty',
215-
},
216-
{
217-
id: 'cardinality_model_plot_high',
218-
},
219-
{
220-
id: 'cardinality_partition_field',
221-
fieldName: 'order_id',
222-
},
223-
{
224-
id: 'bucket_span_high',
225-
},
226-
{
227-
bucketSpanCompareFactor: 25,
228-
id: 'time_range_short',
229-
minTimeSpanReadable: '2 hours',
230-
},
231-
{
232-
id: 'success_influencers',
233-
},
234-
{
235-
id: 'half_estimated_mml_greater_than_mml',
236-
mml: '1MB',
237-
},
238-
{
239-
id: 'missing_summary_count_field_name',
240-
},
241-
];
183+
const expectedResponse = nonBasicIssuesMessages;
242184

243185
expect(body.length).to.eql(
244186
expectedResponse.length,

0 commit comments

Comments
 (0)