Skip to content

Commit c7dbaaf

Browse files
authoredAug 5, 2024··
Validate test story descriptions. (#467)
* Refactored validate_description and title into a base class. Signed-off-by: dblock <dblock@amazon.com> * Validate story descriptions. Signed-off-by: dblock <dblock@amazon.com> * Use a pattern to validate story synopsis and description. Signed-off-by: dblock <dblock@amazon.com> --------- Signed-off-by: dblock <dblock@amazon.com>
1 parent 21bd106 commit c7dbaaf

21 files changed

+59
-41
lines changed
 

‎json_schemas/test_story.schema.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ properties:
66
type: string
77
description:
88
type: string
9+
pattern: ^\p{Lu}[\s\S]*\.$
910
prologues:
1011
type: array
1112
items:
@@ -32,6 +33,7 @@ definitions:
3233
synopsis:
3334
type: string
3435
description: A brief description of the chapter.
36+
pattern: ^\p{Lu}[\s\S]*\.$
3537
response:
3638
$ref: '#/definitions/ExpectedResponse'
3739
warnings:

‎tests/_core/reindex/pipeline.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ prologues:
1616
method: PUT
1717
request:
1818
payload:
19-
description: |
19+
description: |-
2020
Splits the `title`` field into a `words` list.
2121
Computes the length of the title field and stores it in a new `length` field.
2222
Removes the `year` field.

‎tests/indices/aliases/put_alias.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ chapters:
6363
payload:
6464
acknowledged: true
6565

66-
- synopsis: Retrieve aliases
66+
- synopsis: Retrieve aliases.
6767
path: /{index}/_alias
6868
method: GET
6969
parameters:

‎tests/ingest/pipeline.yaml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
$schema: ../../json_schemas/test_story.schema.yaml
22

3-
description: |
4-
Test the creation of an ingest pipeline with a text embedding processor.
3+
description: Test the creation of an ingest pipeline with a text embedding processor.
54
epilogues:
65
- path: /_ingest/pipeline/books_pipeline
76
method: DELETE

‎tests/ml/model_groups.yaml

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
$schema: ../../json_schemas/test_story.schema.yaml
22

3-
description: |
4-
Test the creation of model groups.
3+
description: Test the creation of model groups.
54
version: '>= 2.11'
65
prologues:
76
- path: /_cluster/settings
@@ -28,7 +27,7 @@ chapters:
2827
request:
2928
payload:
3029
name: NLP_Group
31-
description: Model group for NLP models
30+
description: Model group for NLP models.
3231
response:
3332
status: 200
3433
output:

‎tests/ml/models.yaml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
$schema: ../../json_schemas/test_story.schema.yaml
22

3-
description: |
4-
Test the creation of models.
3+
description: Test the creation of models.
54
version: '>= 2.11'
65
prologues:
76
- path: /_cluster/settings

‎tests/ppl/explain.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ epilogues:
1212
method: DELETE
1313
status: [200, 404]
1414
chapters:
15-
- synopsis: Get explain of SQL Query
15+
- synopsis: Get explain of SQL Query.
1616
path: /_plugins/_ppl/_explain
1717
method: POST
1818
request:

‎tests/ppl/query.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ epilogues:
1414
method: DELETE
1515
status: [200, 404]
1616
chapters:
17-
- synopsis: Get PPL query
17+
- synopsis: Get PPL query.
1818
path: /_plugins/_ppl
1919
method: POST
2020
request:

‎tests/sql/close.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
$schema: ../../json_schemas/test_story.schema.yaml
22

3-
description: Test to explicitly clear the cursor context
3+
description: Test to explicitly clear the cursor context.
44

55
prologues:
66
- path: /{index}

‎tests/sql/explain.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ epilogues:
1818
method: DELETE
1919
status: [200, 404]
2020
chapters:
21-
- synopsis: Get explain of SQL Query
21+
- synopsis: Get explain of SQL Query.
2222
path: /_plugins/_sql/_explain
2323
method: POST
2424
request:

‎tests/sql/query.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ epilogues:
2020
method: DELETE
2121
status: [200, 404]
2222
chapters:
23-
- synopsis: Get SQL query
23+
- synopsis: Get SQL query.
2424
path: /_plugins/_sql
2525
method: POST
2626
parameters:

‎tools/src/linter/components/Info.ts

+2-11
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
import { type OpenAPIV3 } from 'openapi-types'
1111
import { type ValidationError } from 'types'
1212
import ValidatorBase from './base/ValidatorBase'
13-
import { toLaxTitleCase } from 'titlecase'
14-
15-
const DESCRIPTION_REGEX = /^\p{Lu}[\s\S]*\.$/u
1613

1714
export default class Info extends ValidatorBase {
1815
path: string
@@ -32,16 +29,10 @@ export default class Info extends ValidatorBase {
3229
}
3330

3431
validate_description (): ValidationError | undefined {
35-
const description = this.spec?.description ?? ''
36-
if (description === '') { return this.error('Missing description property.') }
37-
if (!DESCRIPTION_REGEX.test(description)) { return this.error('Description must start with a capital letter and end with a period.') }
32+
return this.validate_description_field(this.spec?.description, true)
3833
}
3934

4035
validate_title (): ValidationError | undefined {
41-
const title = this.spec?.title ?? ''
42-
if (title === '') { return this.error('Missing title property.') }
43-
const expected_title = toLaxTitleCase(title)
44-
if (title.endsWith('.')) { return this.error('Title must not end with a period.') }
45-
if (title !== expected_title) return this.error(`Title must be capitalized, expected '${expected_title}'.`)
36+
return this.validate_title_field(this.spec?.title)
4637
}
4738
}

‎tools/src/linter/components/Operation.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import _ from 'lodash'
1212
import ValidatorBase from './base/ValidatorBase'
1313

1414
const GROUP_REGEX = /^([a-z]+[a-z_]*[a-z]+\.)?([a-z]+[a-z_]*[a-z]+)$/
15-
const DESCRIPTION_REGEX = /^\p{Lu}[\s\S]*\.$/u
1615

1716
export default class Operation extends ValidatorBase {
1817
path: string
@@ -65,9 +64,7 @@ export default class Operation extends ValidatorBase {
6564
}
6665

6766
validate_description (): ValidationError | undefined {
68-
const description = this.spec.description ?? ''
69-
if (description === '') { return this.error('Missing description property.') }
70-
if (!DESCRIPTION_REGEX.test(description)) return this.error('Description must start with a capital letter and end with a period.')
67+
return this.validate_description_field(this.spec?.description, true)
7168
}
7269

7370
validate_operation_id (): ValidationError | undefined {

‎tools/src/linter/components/Schema.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { type OpenAPIV3 } from 'openapi-types'
1212
import { type ValidationError } from 'types'
1313

1414
const NAME_REGEX = /^[A-Za-z0-9]+$/
15-
const DESCRIPTION_REGEX = /^\p{Lu}[\s\S]*\.$/u
1615

1716
export default class Schema extends ValidatorBase {
1817
name: string
@@ -36,8 +35,6 @@ export default class Schema extends ValidatorBase {
3635
}
3736

3837
validate_description (): ValidationError | undefined {
39-
const description = this.spec.description ?? ''
40-
if (description === '') return
41-
if (!DESCRIPTION_REGEX.test(description)) { return this.error('Description must start with a capital letter and end with a period.') }
38+
return this.validate_description_field(this.spec.description)
4239
}
4340
}

‎tools/src/linter/components/base/ValidatorBase.ts

+18
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* compatible open source license.
88
*/
99

10+
import { toLaxTitleCase } from 'titlecase'
1011
import { type ValidationError } from 'types'
12+
13+
const DESCRIPTION_REGEX = /^\p{Lu}[\s\S]*\.$/u
14+
1115
export default class ValidatorBase {
1216
file: string
1317
location: string | undefined
@@ -24,4 +28,18 @@ export default class ValidatorBase {
2428
validate (): ValidationError[] {
2529
throw new Error('Method not implemented.')
2630
}
31+
32+
validate_description_field (value?: string, required: boolean = false, key: string = 'description'): ValidationError | undefined {
33+
if (value === undefined) { return required ? this.error(`Missing ${key} property.`) : undefined }
34+
if (value === '') { return this.error(`Empty ${key} property.`) }
35+
if (!DESCRIPTION_REGEX.test(value)) { return this.error(`The ${key} must start with a capital letter and end with a period, got "${value}".`) }
36+
}
37+
38+
validate_title_field (value?: string, required: boolean = false, key: string = 'title'): ValidationError | undefined {
39+
if (value === undefined) { return required ? this.error(`Missing ${key} property.`) : undefined }
40+
if (value === '') { return this.error(`Empty ${key} property.`) }
41+
const expected = toLaxTitleCase(value)
42+
if (value.endsWith('.')) { return this.error(`The ${key} must not end with a period.`) }
43+
if (value !== expected) return this.error(`The ${key} must be capitalized, expected "${expected}", not "${value}".`)
44+
}
2745
}

‎tools/tests/linter/NamespaceFile.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ test('validate_info() periods', () => {
105105
{
106106
file: 'namespaces/invalid_info_periods.yaml',
107107
location: 'Info',
108-
message: 'Title must not end with a period.'
108+
message: 'The title must not end with a period.'
109109
},
110110
{
111111
file: 'namespaces/invalid_info_periods.yaml',
112112
location: 'Info',
113-
message: 'Description must start with a capital letter and end with a period.'
113+
message: 'The description must start with a capital letter and end with a period, got "Description should have a period".'
114114
}
115115
])
116116
})
@@ -126,12 +126,12 @@ test('validate_info() capitals', () => {
126126
{
127127
file: 'namespaces/invalid_info_capitals.yaml',
128128
location: 'Info',
129-
message: "Title must be capitalized, expected 'Title Must Be Capitalized'."
129+
message: "The title must be capitalized, expected \"Title Must Be Capitalized\", not \"Title must be capitalized\"."
130130
},
131131
{
132132
file: 'namespaces/invalid_info_capitals.yaml',
133133
location: 'Info',
134-
message: "Description must start with a capital letter and end with a period."
134+
message: "The description must start with a capital letter and end with a period, got \"description must start with a capital letter and end with a period.\"."
135135
}
136136
])
137137
})

‎tools/tests/linter/Operation.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ test('validate_description()', () => {
6969

7070
const invalid_description = operation({ 'x-operation-group': 'indices.create', description: 'This is a description without a period' })
7171
expect(invalid_description.validate_description())
72-
.toEqual(invalid_description.error('Description must start with a capital letter and end with a period.'))
72+
.toEqual(invalid_description.error('The description must start with a capital letter and end with a period, got "This is a description without a period".'))
7373

7474
const valid_description = operation({ 'x-operation-group': 'indices.create', description: 'This is a description with a period.' })
7575
expect(valid_description.validate_description())

‎tools/tests/linter/Schema.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ test('validate_description()', () => {
2626
expect(schema('Name', { description: 'Does not end with a period' }).validate_description()).toEqual({
2727
file: '_common.yaml',
2828
location: '#/components/schemas/Name',
29-
message: "Description must start with a capital letter and end with a period."
29+
message: "The description must start with a capital letter and end with a period, got \"Does not end with a period\"."
3030
})
3131
})

‎tools/tests/tester/StoryValidator.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ describe('StoryValidator', () => {
3535
"data/chapters/1/method MUST be equal to one of the allowed values: GET, PUT, POST, DELETE, PATCH, HEAD, OPTIONS")
3636
})
3737

38+
test('invalid description', () => {
39+
const evaluation = validate('tools/tests/tester/fixtures/invalid_description.yaml')
40+
expect(evaluation?.result).toBe('ERROR')
41+
expect(evaluation?.message).toBe("Invalid Story: " +
42+
"data/description must match pattern \"^\\p{Lu}[\\s\\S]*\\.$\" --- " +
43+
"data/chapters/0/synopsis must match pattern \"^\\p{Lu}[\\s\\S]*\\.$\"")
44+
})
45+
3846
test('valid story', () => {
3947
const evaluation = validate('tools/tests/tester/fixtures/valid_story.yaml')
4048
expect(evaluation).toBeUndefined()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
$schema: ../../../../json_schemas/test_story.schema.yaml
2+
3+
description: This story description is missing a period
4+
5+
chapters:
6+
- synopsis: this synopsis is not capitalized.
7+
method: GET
8+
path: /_cat/health

‎tools/tests/tester/fixtures/invalid_story.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ $schema: ../../../../json_schemas/test_story.schema.yaml
22

33
description: This story is invalid when validated against test_story.schema.yaml.
44
chapters:
5-
- synopsis: Missing Method
5+
- synopsis: Missing method.
66
path: /{index}
7-
- synopsis: Invalid Method
7+
- synopsis: Invalid method.
88
path: /
99
method: RETRIEVE
1010
epilogues:

0 commit comments

Comments
 (0)
Please sign in to comment.