export_steps.check_output_field_key()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nop 3
dl 0
loc 13
rs 9.85
c 0
b 0
f 0
1
import json
2
import os
3
import shutil
4
import random
5
import string
6
from xml.etree import ElementTree
7
8
from behave import given
9
from behave import then
10
11
12
@then("the output should be parsable as json")
13
def check_output_json(context):
14
    out = context.stdout_capture.getvalue()
15
    assert json.loads(out), out
16
17
18
@then('"{field}" in the json output should have {number:d} elements')
19
@then('"{field}" in the json output should have 1 element')
20
def check_output_field(context, field, number=1):
21
    out = context.stdout_capture.getvalue()
22
    out_json = json.loads(out)
23
    assert field in out_json, [field, out_json]
24
    assert len(out_json[field]) == number, len(out_json[field])
25
26
27
@then('"{field}" in the json output should not contain "{key}"')
28
def check_output_field_not_key(context, field, key):
29
    out = context.stdout_capture.getvalue()
30
    out_json = json.loads(out)
31
    assert field in out_json
32
    assert key not in out_json[field]
33
34
35
@then('"{field}" in the json output should contain "{key}"')
36
def check_output_field_key(context, field, key):
37
    out = context.stdout_capture.getvalue()
38
    struct = json.loads(out)
39
40
    for node in field.split("."):
41
        try:
42
            struct = struct[int(node)]
43
        except ValueError:
44
            assert node in struct
45
            struct = struct[node]
46
47
    assert key in struct
48
49
50
@then("the json output should contain {path}")
51
@then('the json output should contain {path} = "{value}"')
52
def check_json_output_path(context, path, value=None):
53
    """E.g.
54
    the json output should contain entries.0.title = "hello"
55
    """
56
    out = context.stdout_capture.getvalue()
57
    struct = json.loads(out)
58
59
    for node in path.split("."):
60
        try:
61
            struct = struct[int(node)]
62
        except ValueError:
63
            struct = struct[node]
64
65
    if value is not None:
66
        assert struct == value, struct
67
    else:
68
        assert struct is not None
69
70
71
@then(
72
    'entry {entry_number:d} should have an array "{name}" with {items_number:d} elements'
73
)
74
def entry_array_count(context, entry_number, name, items_number):
75
    # note that entry_number is 1-indexed.
76
    out = context.stdout_capture.getvalue()
77
    out_json = json.loads(out)
78
    assert len(out_json["entries"][entry_number - 1][name]) == items_number
79
80
81
@then("the output should be a valid XML string")
82
def assert_valid_xml_string(context):
83
    output = context.stdout_capture.getvalue()
84
    xml_tree = ElementTree.fromstring(output)
85
    assert xml_tree, output
86
87
88
@then('"{item}" node in the xml output should have {number:d} elements')
89
def assert_xml_output_entries_count(context, item, number):
90
    output = context.stdout_capture.getvalue()
91
    xml_tree = ElementTree.fromstring(output)
92
93
    xml_tags = (node.tag for node in xml_tree)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable node does not seem to be defined.
Loading history...
94
    assert item in xml_tags, str(list(xml_tags))
95
96
    actual_entry_count = len(xml_tree.find(item))
97
    assert actual_entry_count == number, actual_entry_count
98
99
100
@then('there should be {number:d} "{item}" elements')
101
def count_elements(context, number, item):
102
    output = context.stdout_capture.getvalue()
103
    xml_tree = ElementTree.fromstring(output)
104
    assert len(xml_tree.findall(".//" + item)) == number
105
106
107
@then('"tags" in the xml output should contain {expected_tags_json_list}')
108
def assert_xml_output_tags(context, expected_tags_json_list):
109
    output = context.stdout_capture.getvalue()
110
    xml_tree = ElementTree.fromstring(output)
111
112
    xml_tags = (node.tag for node in xml_tree)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable node does not seem to be defined.
Loading history...
113
    assert "tags" in xml_tags, str(list(xml_tags))
114
115
    expected_tags = json.loads(expected_tags_json_list)
116
    actual_tags = set(t.attrib["name"] for t in xml_tree.find("tags"))
117
    assert actual_tags == set(expected_tags), [actual_tags, set(expected_tags)]
118
119
120
@given('we create cache directory "{dir_name}"')
121
@given("we create a cache directory")
122
def create_directory(context, dir_name=None):
123
    if not dir_name:
124
        dir_name = "cache_" + "".join(
125
            random.choices(string.ascii_uppercase + string.digits, k=20)
126
        )
127
128
    working_dir = os.path.join("features", "cache", dir_name)
129
    if os.path.exists(working_dir):
130
        shutil.rmtree(working_dir)
131
    os.makedirs(working_dir)
132
    context.cache_dir = dir_name
133
134
135
@then('cache "{dir_name}" should contain the files')
136
@then('cache "{dir_name}" should contain the files {expected_files_json_list}')
137
@then("the cache should contain the files")
138
def assert_dir_contains_files(context, dir_name=None, expected_files_json_list=""):
139
    if not dir_name:
140
        dir_name = context.cache_dir
141
142
    working_dir = os.path.join("features", "cache", dir_name)
143
    actual_files = os.listdir(working_dir)
144
145
    expected_files = context.text or expected_files_json_list
146
    expected_files = expected_files.split("\n")
147
148
    # sort to deal with inconsistent default file ordering on different OS's
149
    actual_files.sort()
150
    expected_files.sort()
151
152
    assert actual_files == expected_files, [actual_files, expected_files]
153
154
155
@then('the content of file "{file_path}" in cache directory "{cache_dir}" should be')
156
@then('the content of file "{file_path}" in the cache should be')
157
def assert_exported_yaml_file_content(context, file_path, cache_dir=None):
158
    if not cache_dir:
159
        cache_dir = context.cache_dir
160
161
    expected_content = context.text.strip().splitlines()
162
    full_file_path = os.path.join("features", "cache", cache_dir, file_path)
163
164
    with open(full_file_path, "r") as f:
165
        actual_content = f.read().strip().splitlines()
166
167
    for actual_line, expected_line in zip(actual_content, expected_content):
168
        if actual_line.startswith("tags: ") and expected_line.startswith("tags: "):
169
            assert_equal_tags_ignoring_order(actual_line, expected_line)
170
        else:
171
            assert actual_line.strip() == expected_line.strip(), [
172
                actual_line.strip(),
173
                expected_line.strip(),
174
            ]
175
176
177
def assert_equal_tags_ignoring_order(actual_line, expected_line):
178
    actual_tags = set(tag.strip() for tag in actual_line[len("tags: ") :].split(","))
179
    expected_tags = set(
180
        tag.strip() for tag in expected_line[len("tags: ") :].split(",")
181
    )
182
    assert actual_tags == expected_tags, [actual_tags, expected_tags]
183