Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/tests/unit/test_clidocs.py
1566 views
1
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License"). You
4
# may not use this file except in compliance with the License. A copy of
5
# the License is located at
6
#
7
# http://aws.amazon.com/apache2.0/
8
#
9
# or in the "license" file accompanying this file. This file is
10
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
# ANY KIND, either express or implied. See the License for the specific
12
# language governing permissions and limitations under the License.
13
import json
14
15
from botocore.model import ShapeResolver, StructureShape, StringShape, \
16
ListShape, MapShape, Shape, DenormalizedStructureBuilder
17
18
from awscli.testutils import mock, unittest, FileCreator
19
from awscli.clidocs import OperationDocumentEventHandler, \
20
CLIDocumentEventHandler, TopicListerDocumentEventHandler, \
21
TopicDocumentEventHandler, GlobalOptionsDocumenter
22
from awscli.bcdoc.restdoc import ReSTDocument
23
from awscli.help import ServiceHelpCommand, TopicListerCommand, \
24
TopicHelpCommand, HelpCommand
25
from awscli.arguments import CustomArgument
26
27
28
class TestRecursiveShapes(unittest.TestCase):
29
def setUp(self):
30
self.arg_table = {}
31
self.help_command = mock.Mock()
32
self.help_command.event_class = 'custom'
33
self.help_command.arg_table = self.arg_table
34
self.operation_model = mock.Mock()
35
self.operation_model.service_model.operation_names = []
36
self.help_command.obj = self.operation_model
37
self.operation_handler = OperationDocumentEventHandler(
38
self.help_command)
39
40
def assert_rendered_docs_contain(self, expected):
41
writes = [args[0][0] for args in
42
self.help_command.doc.write.call_args_list]
43
writes = '\n'.join(writes)
44
self.assertIn(expected, writes)
45
46
def assert_proper_indentation(self):
47
indent = self.help_command.doc.style.indent.call_count
48
dedent = self.help_command.doc.style.dedent.call_count
49
message = 'Imbalanced indentation: indent (%s) != dedent (%s)'
50
self.assertEqual(indent, dedent, message % (indent, dedent))
51
52
def test_handle_recursive_input(self):
53
shape_map = {
54
'RecursiveStruct': {
55
'type': 'structure',
56
'members': {
57
'A': {'shape': 'NonRecursive'},
58
'B': {'shape': 'RecursiveStruct'},
59
}
60
},
61
'NonRecursive': {'type': 'string'}
62
}
63
shape = StructureShape('RecursiveStruct', shape_map['RecursiveStruct'],
64
ShapeResolver(shape_map))
65
66
self.arg_table['arg-name'] = mock.Mock(argument_model=shape)
67
self.operation_handler.doc_option_example(
68
'arg-name', self.help_command, 'process-cli-arg.foo.bar')
69
self.assert_rendered_docs_contain('{ ... recursive ... }')
70
71
def test_handle_recursive_output(self):
72
shape_map = {
73
'RecursiveStruct': {
74
'type': 'structure',
75
'members': {
76
'A': {'shape': 'NonRecursive'},
77
'B': {'shape': 'RecursiveStruct'},
78
}
79
},
80
'NonRecursive': {'type': 'string'}
81
}
82
shape = StructureShape('RecursiveStruct', shape_map['RecursiveStruct'],
83
ShapeResolver(shape_map))
84
85
operation_model = mock.Mock()
86
operation_model.output_shape = shape
87
self.help_command.obj = operation_model
88
self.operation_handler.doc_output(self.help_command, 'event-name')
89
self.assert_rendered_docs_contain('( ... recursive ... )')
90
91
def test_handle_empty_nested_struct(self):
92
shape_map = {
93
'InputStruct': {
94
'type': 'structure',
95
'members': {
96
'A': {'shape': 'Empty'},
97
}
98
},
99
'Empty': {'type': 'structure', 'members': {}}
100
}
101
shape = StructureShape('InputStruct', shape_map['InputStruct'],
102
ShapeResolver(shape_map))
103
104
self.arg_table['arg-name'] = mock.Mock(argument_model=shape)
105
self.operation_handler.doc_option_example(
106
'arg-name', self.help_command, 'process-cli-arg.foo.bar')
107
self.assert_proper_indentation()
108
109
def test_handle_no_output_shape(self):
110
operation_model = mock.Mock()
111
operation_model.output_shape = None
112
self.help_command.obj = operation_model
113
self.operation_handler.doc_output(self.help_command, 'event-name')
114
self.assert_rendered_docs_contain('None')
115
116
def test_handle_memberless_output_shape(self):
117
shape_map = {
118
'NoMembers': {
119
'type': 'structure',
120
'members': {}
121
}
122
}
123
shape = StructureShape('NoMembers', shape_map['NoMembers'],
124
ShapeResolver(shape_map))
125
126
operation_model = mock.Mock()
127
operation_model.output_shape = shape
128
self.help_command.obj = operation_model
129
self.operation_handler.doc_output(self.help_command, 'event-name')
130
self.assert_rendered_docs_contain('None')
131
132
133
class TestCLIDocumentEventHandler(unittest.TestCase):
134
def setUp(self):
135
self.session = mock.Mock()
136
self.obj = None
137
self.command_table = {}
138
self.arg_table = {}
139
self.name = 'my-command'
140
self.event_class = 'aws'
141
142
def create_help_command(self):
143
help_command = mock.Mock()
144
help_command.doc = ReSTDocument()
145
help_command.event_class = 'custom'
146
help_command.arg_table = {}
147
operation_model = mock.Mock()
148
operation_model.documentation = 'description'
149
operation_model.service_model.operation_names = []
150
help_command.obj = operation_model
151
return help_command
152
153
def create_tagged_union_shape(self):
154
shape_model = {
155
'type': 'structure',
156
'union': True,
157
'members': {}
158
}
159
tagged_union = StructureShape('tagged_union', shape_model)
160
return tagged_union
161
162
def get_help_docs_for_argument(self, shape):
163
arg_table = {'arg-name': mock.Mock(argument_model=shape)}
164
help_command = mock.Mock()
165
help_command.doc = ReSTDocument()
166
help_command.event_class = 'custom'
167
help_command.arg_table = arg_table
168
operation_model = mock.Mock()
169
operation_model.service_model.operation_names = []
170
help_command.obj = operation_model
171
operation_handler = OperationDocumentEventHandler(help_command)
172
operation_handler.doc_option('arg-name', help_command)
173
return help_command.doc.getvalue().decode('utf-8')
174
175
def test_breadcrumbs_man(self):
176
# Create an arbitrary help command class. This was chosen
177
# because it is fairly easy to instantiate.
178
help_cmd = ServiceHelpCommand(
179
self.session, self.obj, self.command_table, self.arg_table,
180
self.name, self.event_class
181
)
182
183
doc_handler = CLIDocumentEventHandler(help_cmd)
184
doc_handler.doc_breadcrumbs(help_cmd)
185
# These should not show up in the man page
186
self.assertEqual(help_cmd.doc.getvalue().decode('utf-8'), '')
187
188
def test_breadcrumbs_html(self):
189
help_cmd = ServiceHelpCommand(
190
self.session, self.obj, self.command_table, self.arg_table,
191
self.name, self.event_class
192
)
193
help_cmd.doc.target = 'html'
194
doc_handler = CLIDocumentEventHandler(help_cmd)
195
doc_handler.doc_breadcrumbs(help_cmd)
196
self.assertEqual(
197
help_cmd.doc.getvalue().decode('utf-8'),
198
'[ :ref:`aws <cli:aws>` ]'
199
)
200
201
def test_breadcrumbs_service_command_html(self):
202
help_cmd = ServiceHelpCommand(
203
self.session, self.obj, self.command_table, self.arg_table,
204
self.name, 'ec2'
205
)
206
help_cmd.doc.target = 'html'
207
doc_handler = CLIDocumentEventHandler(help_cmd)
208
doc_handler.doc_breadcrumbs(help_cmd)
209
self.assertEqual(
210
help_cmd.doc.getvalue().decode('utf-8'),
211
'[ :ref:`aws <cli:aws>` ]'
212
)
213
214
def test_breadcrumbs_operation_command_html(self):
215
help_cmd = ServiceHelpCommand(
216
self.session, self.obj, self.command_table, self.arg_table,
217
self.name, 'ec2.run-instances'
218
)
219
help_cmd.doc.target = 'html'
220
doc_handler = CLIDocumentEventHandler(help_cmd)
221
doc_handler.doc_breadcrumbs(help_cmd)
222
self.assertEqual(
223
help_cmd.doc.getvalue().decode('utf-8'),
224
'[ :ref:`aws <cli:aws>` . :ref:`ec2 <cli:aws ec2>` ]'
225
)
226
227
def test_breadcrumbs_wait_command_html(self):
228
help_cmd = ServiceHelpCommand(
229
self.session, self.obj, self.command_table, self.arg_table,
230
self.name, 's3api.wait.object-exists'
231
)
232
help_cmd.doc.target = 'html'
233
doc_handler = CLIDocumentEventHandler(help_cmd)
234
doc_handler.doc_breadcrumbs(help_cmd)
235
self.assertEqual(
236
help_cmd.doc.getvalue().decode('utf-8'),
237
('[ :ref:`aws <cli:aws>` . :ref:`s3api <cli:aws s3api>`'
238
' . :ref:`wait <cli:aws s3api wait>` ]')
239
)
240
241
def test_documents_json_header_shape(self):
242
shape = {
243
'type': 'string',
244
'jsonvalue': True,
245
'location': 'header',
246
'locationName': 'X-Amz-Header-Name'
247
}
248
shape = StringShape('JSONValueArg', shape)
249
rendered = self.get_help_docs_for_argument(shape)
250
self.assertIn('(JSON)', rendered)
251
252
def test_documents_enum_values(self):
253
shape = {
254
'type': 'string',
255
'enum': ['FOO', 'BAZ']
256
}
257
shape = StringShape('EnumArg', shape)
258
rendered = self.get_help_docs_for_argument(shape)
259
self.assertIn('Possible values', rendered)
260
self.assertIn('FOO', rendered)
261
self.assertIn('BAZ', rendered)
262
263
def test_documents_recursive_input(self):
264
shape_map = {
265
'RecursiveStruct': {
266
'type': 'structure',
267
'members': {
268
'A': {'shape': 'NonRecursive'},
269
'B': {'shape': 'RecursiveStruct'},
270
}
271
},
272
'NonRecursive': {'type': 'string'}
273
}
274
shape = StructureShape('RecursiveStruct',
275
shape_map['RecursiveStruct'],
276
ShapeResolver(shape_map))
277
rendered = self.get_help_docs_for_argument(shape)
278
self.assertIn('( ... recursive ... )', rendered)
279
280
def test_documents_nested_structure(self):
281
shape_map = {
282
'UpperStructure': {
283
'type': 'structure',
284
'members': {
285
'A': {'shape': 'NestedStruct'},
286
'B': {'shape': 'NestedStruct'},
287
}
288
},
289
'NestedStruct': {
290
'type': 'structure',
291
'members': {
292
'Nested_A': {'shape': 'Line'},
293
'Nested_B': {'shape': 'Line'},
294
}
295
},
296
'Line': {'type': 'string'}
297
}
298
shape = StructureShape('UpperStructure',
299
shape_map['UpperStructure'],
300
ShapeResolver(shape_map))
301
rendered = self.get_help_docs_for_argument(shape)
302
self.assertEqual(rendered.count('A -> (structure)'), 1)
303
self.assertEqual(rendered.count('B -> (structure)'), 1)
304
self.assertEqual(rendered.count('Nested_A -> (string)'), 2)
305
self.assertEqual(rendered.count('Nested_B -> (string)'), 2)
306
307
def test_documents_nested_list(self):
308
shape_map = {
309
'UpperList': {
310
'type': 'list',
311
'member': {'shape': 'NestedStruct'},
312
},
313
'NestedStruct': {
314
'type': 'structure',
315
'members': {
316
'Nested_A': {'shape': 'Line'},
317
'Nested_B': {'shape': 'Line'},
318
}
319
},
320
'Line': {'type': 'string'}
321
}
322
shape = ListShape('UpperList', shape_map['UpperList'],
323
ShapeResolver(shape_map))
324
rendered = self.get_help_docs_for_argument(shape)
325
self.assertEqual(rendered.count('(structure)'), 1)
326
self.assertEqual(rendered.count('Nested_A -> (string)'), 1)
327
self.assertEqual(rendered.count('Nested_B -> (string)'), 1)
328
329
def test_documents_nested_map(self):
330
shape_map = {
331
'UpperMap': {
332
'type': 'map',
333
'key': {'shape': 'NestedStruct'},
334
'value': {'shape': 'NestedStruct'},
335
},
336
'NestedStruct': {
337
'type': 'structure',
338
'members': {
339
'Nested_A': {'shape': 'Line'},
340
'Nested_B': {'shape': 'Line'},
341
}
342
},
343
'Line': {'type': 'string'}
344
}
345
shape = MapShape('UpperMap', shape_map['UpperMap'],
346
ShapeResolver(shape_map))
347
rendered = self.get_help_docs_for_argument(shape)
348
self.assertEqual(rendered.count('key -> (structure)'), 1)
349
self.assertEqual(rendered.count('value -> (structure)'), 1)
350
self.assertEqual(rendered.count('Nested_A -> (string)'), 2)
351
self.assertEqual(rendered.count('Nested_B -> (string)'), 2)
352
353
def test_description_only_for_crosslink_manpage(self):
354
help_command = self.create_help_command()
355
operation_handler = OperationDocumentEventHandler(help_command)
356
operation_handler.doc_description(help_command=help_command)
357
rendered = help_command.doc.getvalue().decode('utf-8')
358
# The links are generated in the "man" mode.
359
self.assertIn('See also: AWS API Documentation', rendered)
360
361
def test_includes_webapi_crosslink_in_html(self):
362
help_command = self.create_help_command()
363
# Configure this for 'html' generation:
364
help_command.obj.service_model.metadata = {'uid': 'service-1-2-3'}
365
help_command.obj.name = 'myoperation'
366
help_command.doc.target = 'html'
367
368
operation_handler = OperationDocumentEventHandler(help_command)
369
operation_handler.doc_description(help_command=help_command)
370
rendered = help_command.doc.getvalue().decode('utf-8')
371
# Should expect an external link because we're generating html.
372
self.assertIn(
373
'See also: `AWS API Documentation '
374
'<https://docs.aws.amazon.com/goto/'
375
'WebAPI/service-1-2-3/myoperation>`_', rendered)
376
377
def test_includes_streaming_blob_options(self):
378
help_command = self.create_help_command()
379
blob_shape = Shape('blob_shape', {'type': 'blob'})
380
blob_shape.serialization = {'streaming': True}
381
blob_arg = CustomArgument('blob_arg', argument_model=blob_shape)
382
help_command.arg_table = {'blob_arg': blob_arg}
383
operation_handler = OperationDocumentEventHandler(help_command)
384
operation_handler.doc_option(arg_name='blob_arg',
385
help_command=help_command)
386
rendered = help_command.doc.getvalue().decode('utf-8')
387
self.assertIn('streaming blob', rendered)
388
389
def test_streaming_blob_comes_after_docstring(self):
390
help_command = self.create_help_command()
391
blob_shape = Shape('blob_shape', {'type': 'blob'})
392
blob_shape.serialization = {'streaming': True}
393
blob_arg = CustomArgument(name='blob_arg',
394
argument_model=blob_shape,
395
help_text='FooBar')
396
help_command.arg_table = {'blob_arg': blob_arg}
397
operation_handler = OperationDocumentEventHandler(help_command)
398
operation_handler.doc_option(arg_name='blob_arg',
399
help_command=help_command)
400
rendered = help_command.doc.getvalue().decode('utf-8')
401
self.assertRegex(rendered, r'FooBar[\s\S]*streaming blob')
402
403
def test_includes_tagged_union_options(self):
404
help_command = self.create_help_command()
405
tagged_union = self.create_tagged_union_shape()
406
arg = CustomArgument(name='tagged_union',
407
argument_model=tagged_union)
408
help_command.arg_table = {'tagged_union': arg}
409
operation_handler = OperationDocumentEventHandler(help_command)
410
operation_handler.doc_option(arg_name='tagged_union',
411
help_command=help_command)
412
rendered = help_command.doc.getvalue().decode('utf-8')
413
self.assertIn('(tagged union structure)', rendered)
414
415
def test_tagged_union_comes_after_docstring_options(self):
416
help_command = self.create_help_command()
417
tagged_union = self.create_tagged_union_shape()
418
arg = CustomArgument(name='tagged_union',
419
argument_model=tagged_union,
420
help_text='FooBar')
421
help_command.arg_table = {'tagged_union': arg}
422
operation_handler = OperationDocumentEventHandler(help_command)
423
operation_handler.doc_option(arg_name='tagged_union',
424
help_command=help_command)
425
rendered = help_command.doc.getvalue().decode('utf-8')
426
self.assertRegex(rendered, r'FooBar[\s\S]*Tagged Union')
427
428
def test_tagged_union_comes_after_docstring_output(self):
429
help_command = self.create_help_command()
430
tagged_union = self.create_tagged_union_shape()
431
tagged_union.documentation = "FooBar"
432
shape = DenormalizedStructureBuilder().with_members({
433
'foo': {
434
'type': 'structure',
435
'union': True,
436
'documentation': 'FooBar',
437
'members': {}
438
}
439
}).build_model()
440
help_command.obj.output_shape = shape
441
operation_handler = OperationDocumentEventHandler(help_command)
442
operation_handler.doc_output(help_command=help_command,
443
event_name='foobar')
444
rendered = help_command.doc.getvalue().decode('utf-8')
445
self.assertRegex(rendered, r'FooBar[\s\S]*Tagged Union')
446
447
448
class TestTopicDocumentEventHandlerBase(unittest.TestCase):
449
def setUp(self):
450
self.session = mock.Mock()
451
self.file_creator = FileCreator()
452
453
self.tags_dict = {}
454
455
# Make a temporary json index to base information on
456
self.json_index = self.file_creator.create_file('index.json', '')
457
with open(self.json_index, 'w') as f:
458
json.dump(self.tags_dict, f, indent=4, sort_keys=True)
459
460
self.index_patch = mock.patch('awscli.topictags.TopicTagDB.index_file',
461
self.json_index)
462
self.dir_patch = mock.patch('awscli.topictags.TopicTagDB.topic_dir',
463
self.file_creator.rootdir)
464
self.index_patch.start()
465
self.dir_patch.start()
466
467
def tearDown(self):
468
self.dir_patch.stop()
469
self.index_patch.stop()
470
self.file_creator.remove_all()
471
472
473
class TestTopicListerDocumentEventHandler(TestTopicDocumentEventHandlerBase):
474
def setUp(self):
475
super(TestTopicListerDocumentEventHandler, self).setUp()
476
self.descriptions = [
477
'This describes the first topic',
478
'This describes the second topic',
479
'This describes the third topic'
480
]
481
self.tags_dict = {
482
'topic-name-1': {
483
'title': ['The first topic title'],
484
'description': [self.descriptions[0]],
485
'category': ['General']
486
},
487
'topic-name-2': {
488
'title': ['The second topic title'],
489
'description': [self.descriptions[1]],
490
'category': ['S3']
491
},
492
'topic-name-3': {
493
'title': ['The third topic title'],
494
'description': [self.descriptions[2]],
495
'category': ['General']
496
}
497
498
}
499
500
with open(self.json_index, 'w') as f:
501
json.dump(self.tags_dict, f, indent=4, sort_keys=True)
502
503
self.cmd = TopicListerCommand(self.session)
504
self.doc_handler = TopicListerDocumentEventHandler(self.cmd)
505
506
def test_breadcrumbs(self):
507
self.doc_handler.doc_breadcrumbs(self.cmd)
508
self.assertEqual(self.cmd.doc.getvalue().decode('utf-8'), '')
509
self.cmd.doc.target = 'html'
510
self.doc_handler.doc_breadcrumbs(self.cmd)
511
self.assertEqual(
512
'[ :ref:`aws <cli:aws>` ]',
513
self.cmd.doc.getvalue().decode('utf-8')
514
)
515
516
def test_title(self):
517
self.doc_handler.doc_title(self.cmd)
518
title_contents = self.cmd.doc.getvalue().decode('utf-8')
519
self.assertIn('.. _cli:aws help %s:' % self.cmd.name, title_contents)
520
self.assertIn('AWS CLI Topic Guide', title_contents)
521
522
def test_description(self):
523
self.doc_handler.doc_description(self.cmd)
524
self.assertIn(
525
'This is the AWS CLI Topic Guide',
526
self.cmd.doc.getvalue().decode('utf-8')
527
)
528
529
def test_subitems_start(self):
530
ref_output = [
531
'-------\nGeneral\n-------',
532
('* topic-name-1: %s\n'
533
'* topic-name-3: %s\n' %
534
(self.descriptions[0], self.descriptions[2])),
535
'--\nS3\n--',
536
'* topic-name-2: %s\n' % self.descriptions[1]
537
]
538
539
self.doc_handler.doc_subitems_start(self.cmd)
540
contents = self.cmd.doc.getvalue().decode('utf-8')
541
542
for line in ref_output:
543
self.assertIn(line, contents)
544
# Make sure the toctree is not in the man page
545
self.assertNotIn('.. toctree::', contents)
546
547
def test_subitems_start_html(self):
548
self.cmd.doc.target = 'html'
549
ref_output = [
550
'-------\nGeneral\n-------',
551
('* :ref:`topic-name-1 <cli:aws help topic-name-1>`: %s\n'
552
'* :ref:`topic-name-3 <cli:aws help topic-name-3>`: %s\n' %
553
(self.descriptions[0], self.descriptions[2])),
554
'--\nS3\n--',
555
('* :ref:`topic-name-2 <cli:aws help topic-name-2>`: %s\n' %
556
self.descriptions[1])
557
]
558
559
self.doc_handler.doc_subitems_start(self.cmd)
560
contents = self.cmd.doc.getvalue().decode('utf-8')
561
562
for line in ref_output:
563
self.assertIn(line, contents)
564
# Make sure the hidden toctree is in the html
565
self.assertIn('.. toctree::', contents)
566
self.assertIn(':hidden:', contents)
567
568
569
class TestTopicDocumentEventHandler(TestTopicDocumentEventHandlerBase):
570
def setUp(self):
571
super(TestTopicDocumentEventHandler, self).setUp()
572
self.name = 'topic-name-1'
573
self.title = 'The first topic title'
574
self.description = 'This is about the first topic'
575
self.category = 'General'
576
self.related_command = 'foo'
577
self.related_topic = 'topic-name-2'
578
self.topic_body = 'Hello World!'
579
580
self.tags_dict = {
581
self.name: {
582
'title': [self.title],
583
'description': [self.description],
584
'category': [self.category],
585
'related topic': [self.related_topic],
586
'related command': [self.related_command]
587
}
588
}
589
with open(self.json_index, 'w') as f:
590
json.dump(self.tags_dict, f, indent=4, sort_keys=True)
591
592
self.cmd = TopicHelpCommand(self.session, self.name)
593
self.doc_handler = TopicDocumentEventHandler(self.cmd)
594
595
def test_breadcrumbs(self):
596
self.doc_handler.doc_breadcrumbs(self.cmd)
597
self.assertEqual(self.cmd.doc.getvalue().decode('utf-8'), '')
598
self.cmd.doc.target = 'html'
599
self.doc_handler.doc_breadcrumbs(self.cmd)
600
self.assertEqual(
601
'[ :ref:`aws <cli:aws>` . :ref:`topics <cli:aws help topics>` ]',
602
self.cmd.doc.getvalue().decode('utf-8')
603
)
604
605
def test_title(self):
606
self.doc_handler.doc_title(self.cmd)
607
title_contents = self.cmd.doc.getvalue().decode('utf-8')
608
self.assertIn('.. _cli:aws help %s:' % self.name, title_contents)
609
self.assertIn(self.title, title_contents)
610
611
def test_description(self):
612
lines = [
613
':title: ' + self.title,
614
':description: ' + self.description,
615
':category:' + self.category,
616
':related command: ' + self.related_command,
617
':related topic: ' + self.related_topic,
618
self.topic_body
619
]
620
body = '\n'.join(lines)
621
self.file_creator.create_file(self.name + '.rst', body)
622
self.doc_handler.doc_description(self.cmd)
623
contents = self.cmd.doc.getvalue().decode('utf-8')
624
self.assertIn(self.topic_body, contents)
625
self.assertNotIn(':title ' + self.title, contents)
626
627
def test_description_no_tags(self):
628
lines = [
629
self.topic_body
630
]
631
body = '\n'.join(lines)
632
self.file_creator.create_file(self.name + '.rst', body)
633
self.doc_handler.doc_description(self.cmd)
634
contents = self.cmd.doc.getvalue().decode('utf-8')
635
self.assertIn(self.topic_body, contents)
636
637
def test_description_tags_in_body(self):
638
lines = [
639
':title: ' + self.title,
640
':description: ' + self.description,
641
':related command: ' + self.related_command
642
]
643
body_lines = [
644
':related_topic: ' + self.related_topic,
645
self.topic_body,
646
':foo: bar'
647
]
648
body = '\n'.join(lines + body_lines)
649
ref_body = '\n'.join(body_lines)
650
self.file_creator.create_file(self.name + '.rst', body)
651
self.doc_handler.doc_description(self.cmd)
652
contents = self.cmd.doc.getvalue().decode('utf-8')
653
self.assertIn(ref_body, contents)
654
655
def test_excludes_global_options(self):
656
self.doc_handler.doc_global_option(self.cmd)
657
global_options = self.cmd.doc.getvalue().decode('utf-8')
658
self.assertNotIn('Global Options', global_options)
659
660
661
class TestGlobalOptionsDocumenter(unittest.TestCase):
662
def create_help_command(self):
663
types = ['blob', 'integer', 'boolean', 'string']
664
arg_table = {}
665
for t in types:
666
name = f'{t}_type'
667
help_text = f'This arg type is {t}'
668
choices = ['A', 'B', 'C'] if t == 'string' else []
669
arg_table[name] = CustomArgument(name=name,
670
cli_type_name=t,
671
help_text=help_text,
672
choices=choices)
673
help_command = mock.Mock(spec=HelpCommand)
674
help_command.arg_table = arg_table
675
help_command.doc = ReSTDocument()
676
return help_command
677
678
def create_documenter(self):
679
return GlobalOptionsDocumenter(self.create_help_command())
680
681
def test_doc_global_options(self):
682
documenter = self.create_documenter()
683
options = documenter.doc_global_options()
684
self.assertIn('``--string_type`` (string)', options)
685
self.assertIn('``--integer_type`` (integer)', options)
686
self.assertIn('``--boolean_type`` (boolean)', options)
687
self.assertIn('``--blob_type`` (blob)', options)
688
self.assertIn('* A', options)
689
self.assertIn('* B', options)
690
self.assertIn('* C', options)
691
692
def test_doc_global_synopsis(self):
693
documenter = self.create_documenter()
694
synopsis = documenter.doc_global_synopsis()
695
self.assertIn('[--string_type <value>]', synopsis)
696
self.assertIn('[--integer_type <value>]', synopsis)
697
self.assertIn('[--boolean_type]', synopsis)
698
self.assertIn('[--blob_type <value>]', synopsis)
699
700