1# encoding: utf-8
2
3"""
4Step implementations for paragraph-related features
5"""
6
7from behave import given, then, when
8
9from docx import Document
10from docx.enum.text import WD_ALIGN_PARAGRAPH
11from docx.text.parfmt import ParagraphFormat
12
13from helpers import saved_docx_path, test_docx, test_text
14
15
16# given ===================================================
17
18@given('a document containing three paragraphs')
19def given_a_document_containing_three_paragraphs(context):
20    document = Document()
21    document.add_paragraph('foo')
22    document.add_paragraph('bar')
23    document.add_paragraph('baz')
24    context.document = document
25
26
27@given('a paragraph having {align_type} alignment')
28def given_a_paragraph_align_type_alignment(context, align_type):
29    paragraph_idx = {
30        'inherited': 0,
31        'left':      1,
32        'center':    2,
33        'right':     3,
34        'justified': 4,
35    }[align_type]
36    document = Document(test_docx('par-alignment'))
37    context.paragraph = document.paragraphs[paragraph_idx]
38
39
40@given('a paragraph having {style_state} style')
41def given_a_paragraph_having_style(context, style_state):
42    paragraph_idx = {
43        'no specified': 0,
44        'a missing':    1,
45        'Heading 1':    2,
46        'Body Text':    3,
47    }[style_state]
48    document = context.document = Document(test_docx('par-known-styles'))
49    context.paragraph = document.paragraphs[paragraph_idx]
50
51
52@given('a paragraph with content and formatting')
53def given_a_paragraph_with_content_and_formatting(context):
54    document = Document(test_docx('par-known-paragraphs'))
55    context.paragraph = document.paragraphs[0]
56
57
58# when ====================================================
59
60@when('I add a run to the paragraph')
61def when_add_new_run_to_paragraph(context):
62    context.run = context.p.add_run()
63
64
65@when('I assign a {style_type} to paragraph.style')
66def when_I_assign_a_style_type_to_paragraph_style(context, style_type):
67    paragraph = context.paragraph
68    style = context.style = context.document.styles['Heading 1']
69    style_spec = {
70        'style object': style,
71        'style name':   'Heading 1',
72    }[style_type]
73    paragraph.style = style_spec
74
75
76@when('I clear the paragraph content')
77def when_I_clear_the_paragraph_content(context):
78    context.paragraph.clear()
79
80
81@when('I insert a paragraph above the second paragraph')
82def when_I_insert_a_paragraph_above_the_second_paragraph(context):
83    paragraph = context.document.paragraphs[1]
84    paragraph.insert_paragraph_before('foobar', 'Heading1')
85
86
87@when('I set the paragraph text')
88def when_I_set_the_paragraph_text(context):
89    context.paragraph.text = 'bar\tfoo\r'
90
91
92# then =====================================================
93
94@then('paragraph.paragraph_format is its ParagraphFormat object')
95def then_paragraph_paragraph_format_is_its_parfmt_object(context):
96    paragraph = context.paragraph
97    paragraph_format = paragraph.paragraph_format
98    assert isinstance(paragraph_format, ParagraphFormat)
99    assert paragraph_format.element is paragraph._element
100
101
102@then('paragraph.style is {value_key}')
103def then_paragraph_style_is_value(context, value_key):
104    styles = context.document.styles
105    expected_value = {
106        'Normal':    styles['Normal'],
107        'Heading 1': styles['Heading 1'],
108        'Body Text': styles['Body Text'],
109    }[value_key]
110    paragraph = context.paragraph
111    assert paragraph.style == expected_value
112
113
114@then('the document contains four paragraphs')
115def then_the_document_contains_four_paragraphs(context):
116    assert len(context.document.paragraphs) == 4
117
118
119@then('the document contains the text I added')
120def then_document_contains_text_I_added(context):
121    document = Document(saved_docx_path)
122    paragraphs = document.paragraphs
123    p = paragraphs[-1]
124    r = p.runs[0]
125    assert r.text == test_text
126
127
128@then('the paragraph alignment property value is {align_value}')
129def then_the_paragraph_alignment_prop_value_is_value(context, align_value):
130    expected_value = {
131        'None':                      None,
132        'WD_ALIGN_PARAGRAPH.LEFT':   WD_ALIGN_PARAGRAPH.LEFT,
133        'WD_ALIGN_PARAGRAPH.CENTER': WD_ALIGN_PARAGRAPH.CENTER,
134        'WD_ALIGN_PARAGRAPH.RIGHT':  WD_ALIGN_PARAGRAPH.RIGHT,
135    }[align_value]
136    assert context.paragraph.alignment == expected_value
137
138
139@then('the paragraph formatting is preserved')
140def then_the_paragraph_formatting_is_preserved(context):
141    paragraph = context.paragraph
142    assert paragraph.style.name == 'Heading 1'
143
144
145@then('the paragraph has no content')
146def then_the_paragraph_has_no_content(context):
147    assert context.paragraph.text == ''
148
149
150@then('the paragraph has the style I set')
151def then_the_paragraph_has_the_style_I_set(context):
152    paragraph, expected_style = context.paragraph, context.style
153    assert paragraph.style == expected_style
154
155
156@then('the paragraph has the text I set')
157def then_the_paragraph_has_the_text_I_set(context):
158    assert context.paragraph.text == 'bar\tfoo\n'
159
160
161@then('the style of the second paragraph matches the style I set')
162def then_the_style_of_the_second_paragraph_matches_the_style_I_set(context):
163    second_paragraph = context.document.paragraphs[1]
164    assert second_paragraph.style.name == 'Heading 1'
165
166
167@then('the text of the second paragraph matches the text I set')
168def then_the_text_of_the_second_paragraph_matches_the_text_I_set(context):
169    second_paragraph = context.document.paragraphs[1]
170    assert second_paragraph.text == 'foobar'
171