Passed
Push — master ( 00f0f1...b0c5e3 )
by
unknown
01:16
created

test_apply_overwrites_invalid_overwrite()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
"""Verify generate context behaviour and context overwrite priorities."""
2
import os
3
import re
4
from collections import OrderedDict
5
6
import pytest
7
8
from cookiecutter import generate
9
from cookiecutter.exceptions import ContextDecodingException
10
11
12
def context_data():
13
    """Generate pytest parametrization variables for test.
14
15
    Return ('input_params, expected_context') tuples.
16
    """
17
    context = (
18
        {'context_file': 'tests/test-generate-context/test.json'},
19
        {'test': {'1': 2, 'some_key': 'some_val'}},
20
    )
21
22
    context_with_default = (
23
        {
24
            'context_file': 'tests/test-generate-context/test.json',
25
            'default_context': {'1': 3},
26
        },
27
        {'test': {'1': 3, 'some_key': 'some_val'}},
28
    )
29
30
    context_with_extra = (
31
        {
32
            'context_file': 'tests/test-generate-context/test.json',
33
            'extra_context': {'1': 4},
34
        },
35
        {'test': {'1': 4, 'some_key': 'some_val'}},
36
    )
37
38
    context_with_default_and_extra = (
39
        {
40
            'context_file': 'tests/test-generate-context/test.json',
41
            'default_context': {'1': 3},
42
            'extra_context': {'1': 5},
43
        },
44
        {'test': {'1': 5, 'some_key': 'some_val'}},
45
    )
46
47
    yield context
48
    yield context_with_default
49
    yield context_with_extra
50
    yield context_with_default_and_extra
51
52
53
@pytest.mark.usefixtures('clean_system')
54
@pytest.mark.parametrize('input_params, expected_context', context_data())
55
def test_generate_context(input_params, expected_context):
56
    """Verify input contexts combinations result in expected content on output."""
57
    assert generate.generate_context(**input_params) == expected_context
58
59
60
@pytest.mark.usefixtures('clean_system')
61
def test_generate_context_with_json_decoding_error():
62
    """Verify malformed JSON file generates expected error output."""
63
    with pytest.raises(ContextDecodingException) as excinfo:
64
        generate.generate_context('tests/test-generate-context/invalid-syntax.json')
65
    # original message from json module should be included
66
    pattern = 'Expecting \'{0,1}:\'{0,1} delimiter: line 1 column (19|20) \\(char 19\\)'
67
    assert re.search(pattern, str(excinfo.value))
68
    # File name should be included too...for testing purposes, just test the
69
    # last part of the file. If we wanted to test the absolute path, we'd have
70
    # to do some additional work in the test which doesn't seem that needed at
71
    # this point.
72
    path = os.path.sep.join(['tests', 'test-generate-context', 'invalid-syntax.json'])
73
    assert path in str(excinfo.value)
74
75
76
def test_default_context_replacement_in_generate_context():
77
    """Verify default content settings are correctly replaced by template settings.
78
79
    Make sure that the default for list variables of `orientation` is based on
80
    the user config (`choices_template.json`) and not changed to a single value
81
    from `default_context`.
82
    """
83
    expected_context = {
84
        'choices_template': OrderedDict(
85
            [
86
                ('full_name', 'Raphael Pierzina'),
87
                ('github_username', 'hackebrot'),
88
                ('project_name', 'Kivy Project'),
89
                ('repo_name', '{{cookiecutter.project_name|lower}}'),
90
                ('orientation', ['landscape', 'all', 'portrait']),
91
            ]
92
        )
93
    }
94
95
    generated_context = generate.generate_context(
96
        context_file='tests/test-generate-context/choices_template.json',
97
        default_context={
98
            'not_in_template': 'foobar',
99
            'project_name': 'Kivy Project',
100
            'orientation': 'landscape',
101
        },
102
        extra_context={
103
            'also_not_in_template': 'foobar2',
104
            'github_username': 'hackebrot',
105
        },
106
    )
107
108
    assert generated_context == expected_context
109
110
111
def test_generate_context_decodes_non_ascii_chars():
112
    """Verify `generate_context` correctly decodes non-ascii chars."""
113
    expected_context = {'non_ascii': OrderedDict([('full_name', 'éèà'),])}
114
115
    generated_context = generate.generate_context(
116
        context_file='tests/test-generate-context/non_ascii.json'
117
    )
118
119
    assert generated_context == expected_context
120
121
122
@pytest.fixture
123
def template_context():
124
    """Fixture. Populates template content for future tests."""
125
    return OrderedDict(
126
        [
127
            ('full_name', 'Raphael Pierzina'),
128
            ('github_username', 'hackebrot'),
129
            ('project_name', 'Kivy Project'),
130
            ('repo_name', '{{cookiecutter.project_name|lower}}'),
131
            ('orientation', ['all', 'landscape', 'portrait']),
132
        ]
133
    )
134
135
136
def test_apply_overwrites_does_include_unused_variables(template_context):
137
    """Verify `apply_overwrites_to_context` skips variables that are not in context."""
138
    generate.apply_overwrites_to_context(
139
        context=template_context, overwrite_context={'not in template': 'foobar'}
140
    )
141
142
    assert 'not in template' not in template_context
143
144
145
def test_apply_overwrites_sets_non_list_value(template_context):
146
    """Verify `apply_overwrites_to_context` work with string variables."""
147
    generate.apply_overwrites_to_context(
148
        context=template_context, overwrite_context={'repo_name': 'foobar'}
149
    )
150
151
    assert template_context['repo_name'] == 'foobar'
152
153
154
def test_apply_overwrites_does_not_modify_choices_for_invalid_overwrite():
155
    """Verify variables overwrite for list if variable not in list ignored."""
156
    expected_context = {
157
        'choices_template': OrderedDict(
158
            [
159
                ('full_name', 'Raphael Pierzina'),
160
                ('github_username', 'hackebrot'),
161
                ('project_name', 'Kivy Project'),
162
                ('repo_name', '{{cookiecutter.project_name|lower}}'),
163
                ('orientation', ['all', 'landscape', 'portrait']),
164
            ]
165
        )
166
    }
167
168
    generated_context = generate.generate_context(
169
        context_file='tests/test-generate-context/choices_template.json',
170
        default_context={
171
            'not_in_template': 'foobar',
172
            'project_name': 'Kivy Project',
173
            'orientation': 'foobar',
174
        },
175
        extra_context={
176
            'also_not_in_template': 'foobar2',
177
            'github_username': 'hackebrot',
178
        },
179
    )
180
181
    assert generated_context == expected_context
182
183
184
def test_apply_overwrites_invalid_overwrite(template_context):
185
    """Verify variables overwrite for list if variable not in list not ignored."""
186
    with pytest.raises(ValueError):
187
        generate.apply_overwrites_to_context(
188
            context=template_context, overwrite_context={'orientation': 'foobar'}
189
        )
190
191
192
def test_apply_overwrites_sets_default_for_choice_variable(template_context):
193
    """Verify overwritten list member became a default value."""
194
    generate.apply_overwrites_to_context(
195
        context=template_context, overwrite_context={'orientation': 'landscape'}
196
    )
197
198
    assert template_context['orientation'] == ['landscape', 'all', 'portrait']
199