mirror of
https://github.com/vale981/releases
synced 2025-03-04 17:21:43 -05:00
258 lines
9.1 KiB
Python
258 lines
9.1 KiB
Python
from spec import Spec, eq_
|
|
from docutils.nodes import (
|
|
reference, bullet_list, list_item, literal, raw, paragraph, Text
|
|
)
|
|
|
|
from releases import (
|
|
Issue,
|
|
construct_releases,
|
|
construct_nodes,
|
|
)
|
|
|
|
from _util import (
|
|
b, f, s,
|
|
entry,
|
|
make_app,
|
|
release,
|
|
releases,
|
|
setup_issues,
|
|
)
|
|
|
|
|
|
def _obj2name(obj):
|
|
cls = obj if isinstance(obj, type) else obj.__class__
|
|
return cls.__name__.split('.')[-1]
|
|
|
|
def _expect_type(node, cls):
|
|
type_ = _obj2name(node)
|
|
name = _obj2name(cls)
|
|
msg = "Expected %r to be a %s, but it's a %s" % (node, name, type_)
|
|
assert isinstance(node, cls), msg
|
|
|
|
|
|
class presentation(Spec):
|
|
"""
|
|
Expansion/extension of docutils nodes (rendering)
|
|
"""
|
|
def setup(self):
|
|
setup_issues(self)
|
|
|
|
def _generate(self, *entries, **kwargs):
|
|
raw = kwargs.pop('raw', False)
|
|
nodes = construct_nodes(releases(*entries, **kwargs))
|
|
# By default, yield the contents of the bullet list.
|
|
return nodes if raw else nodes[0][1][0]
|
|
|
|
def _test_link(self, kwargs, type_, expected):
|
|
app = make_app(**kwargs)
|
|
nodes = construct_nodes(construct_releases([
|
|
release('1.0.2', app=app),
|
|
entry(b(15, app=app)),
|
|
release('1.0.0'),
|
|
], app=app)[0])
|
|
# Shorthand for "I'll do my own asserts"
|
|
if expected is None:
|
|
return nodes
|
|
if type_ == 'release':
|
|
header = nodes[0][0][0].astext()
|
|
assert expected in header
|
|
elif type_ == 'issue':
|
|
link = nodes[0][1][0][0][2]
|
|
eq_(link['refuri'], expected)
|
|
else:
|
|
raise Exception("Gave unknown type_ kwarg to _test_link()!")
|
|
|
|
def issues_with_numbers_appear_as_number_links(self):
|
|
self._test_link({}, 'issue', 'bar_15')
|
|
|
|
def releases_appear_as_header_links(self):
|
|
self._test_link({}, 'release', 'foo_1.0.2')
|
|
|
|
def links_will_use_github_option_if_defined(self):
|
|
kwargs = {
|
|
'release_uri': None,
|
|
'issue_uri': None,
|
|
'github_path': 'foo/bar',
|
|
}
|
|
for type_, expected in (
|
|
('issue', 'https://github.com/foo/bar/issues/15'),
|
|
('release', 'https://github.com/foo/bar/tree/1.0.2'),
|
|
):
|
|
self._test_link(kwargs, type_, expected)
|
|
|
|
def issue_links_prefer_explicit_setting_over_github_setting(self):
|
|
kwargs = {
|
|
'release_uri': None,
|
|
'issue_uri': 'explicit_issue_%s',
|
|
'github_path': 'foo/bar',
|
|
}
|
|
self._test_link(kwargs, 'issue', 'explicit_issue_15')
|
|
|
|
def release_links_prefer_explicit_setting_over_github_setting(self):
|
|
kwargs = {
|
|
'release_uri': 'explicit_release_%s',
|
|
'issue_uri': None,
|
|
'github_path': 'foo/bar',
|
|
}
|
|
self._test_link(kwargs, 'release', 'explicit_release_1.0.2')
|
|
|
|
def completely_blank_uri_settings_does_not_asplode(self):
|
|
kwargs = {
|
|
'release_uri': None,
|
|
'issue_uri': None,
|
|
'github_path': None,
|
|
}
|
|
# Get nodes for direct inspection
|
|
nodes = self._test_link(kwargs, 'release', None)
|
|
# Ensure release entry still displays release version.
|
|
# (These are curently constructed as raw text nodes so no other great
|
|
# way to test this. Meh.)
|
|
text = nodes[0][0][0].astext()
|
|
assert '>1.0.2 <span' in text
|
|
# Ensure issues still display issue number. (Ditto.)
|
|
text = nodes[0][1][0][0].astext()
|
|
assert '>Bug</span>] #15:' in text
|
|
|
|
|
|
def _assert_prefix(self, entries, expectation):
|
|
assert expectation in self._generate(*entries)[0][0][0]
|
|
|
|
def bugs_marked_as_bugs(self):
|
|
self._assert_prefix(['1.0.2', self.b], 'Bug')
|
|
|
|
def features_marked_as_features(self):
|
|
self._assert_prefix(['1.1.0', self.f], 'Feature')
|
|
|
|
def support_marked_as_support(self):
|
|
self._assert_prefix(['1.1.0', self.s], 'Support')
|
|
|
|
def dashed_issues_appear_as_unlinked_issues(self):
|
|
node = self._generate('1.0.2', b('-'))
|
|
assert not isinstance(node[0][2], reference)
|
|
|
|
def zeroed_issues_appear_as_unlinked_issues(self):
|
|
node = self._generate('1.0.2', b(0))
|
|
assert not isinstance(node[0][2], reference)
|
|
|
|
def un_prefixed_list_items_appear_as_unlinked_bugs(self):
|
|
fake = list_item('', paragraph('', '',
|
|
Text("fixes an issue in "), literal('', 'methodname')))
|
|
node = self._generate('1.0.2', fake)
|
|
# [<raw prefix>, <inline colon>, <inline space>, <text>, <monospace>]
|
|
eq_(len(node[0]), 5)
|
|
assert 'Bug' in str(node[0][0])
|
|
assert 'fixes an issue' in str(node[0][3])
|
|
assert 'methodname' in str(node[0][4])
|
|
|
|
def un_prefixed_list_items_get_no_prefix_under_unstable_prehistory(self):
|
|
app = make_app(unstable_prehistory=True)
|
|
fake = list_item('', paragraph('', '', raw('', 'whatever')))
|
|
node = self._generate('0.1.0', fake, app=app, skip_initial=True)
|
|
# [<raw bug text>]
|
|
eq_(len(node[0]), 1)
|
|
assert 'Bug' not in str(node[0][0])
|
|
assert 'whatever' in str(node[0][0])
|
|
|
|
def issues_remain_wrapped_in_unordered_list_nodes(self):
|
|
node = self._generate('1.0.2', self.b, raw=True)[0][1]
|
|
_expect_type(node, bullet_list)
|
|
_expect_type(node[0], list_item)
|
|
|
|
def release_headers_have_local_style_tweaks(self):
|
|
node = self._generate('1.0.2', self.b, raw=True)[0][0]
|
|
_expect_type(node, raw)
|
|
# Header w/ bottom margin
|
|
assert '<h2 style="margin-bottom' in str(node)
|
|
# Date span w/ font-size
|
|
assert '<span style="font-size' in str(node)
|
|
|
|
def descriptions_are_preserved(self):
|
|
# Changelog containing an issue item w/ trailing node
|
|
issue = list_item('',
|
|
paragraph('', '', self.b.deepcopy(), raw('', 'x')),
|
|
)
|
|
# Trailing nodes should appear post-processing after the link/etc
|
|
rest = self._generate('1.0.2', issue)[0]
|
|
eq_(len(rest), 5)
|
|
_expect_type(rest[4], raw)
|
|
eq_(rest[4].astext(), 'x')
|
|
|
|
def complex_descriptions_are_preserved(self):
|
|
# Complex 'entry' mapping to an outer list_item (list) containing two
|
|
# paragraphs, one w/ the real issue + desc, another simply a 2nd text
|
|
# paragraph. Using 'raw' nodes for filler as needed.
|
|
issue = list_item('',
|
|
paragraph('', '', self.b.deepcopy(), raw('', 'x')),
|
|
paragraph('', '', raw('', 'y')),
|
|
)
|
|
li = self._generate('1.0.2', issue)
|
|
# Expect that the machinery parsing issue nodes/nodelists, is not
|
|
# discarding our 2nd 'paragraph'
|
|
eq_(len(li), 2)
|
|
p1, p2 = li
|
|
# Last item in 1st para is our 1st raw node
|
|
_expect_type(p1[4], raw)
|
|
eq_(p1[4].astext(), 'x')
|
|
# Only item in 2nd para is our 2nd raw node
|
|
_expect_type(p2[0], raw)
|
|
eq_(p2[0].astext(), 'y')
|
|
|
|
def descriptions_are_parsed_for_issue_roles(self):
|
|
item = list_item('',
|
|
paragraph('', '', self.b.deepcopy(), s(5))
|
|
)
|
|
para = self._generate('1.0.2', item)[0]
|
|
# Sanity check - in a broken parsing scenarion, the 4th child will be a
|
|
# raw issue object
|
|
assert not isinstance(para[4], Issue)
|
|
# First/primary link
|
|
_expect_type(para[2], reference)
|
|
eq_(para[2].astext(), '#15')
|
|
assert 'Bug' in para[0].astext()
|
|
# Second/inline link
|
|
_expect_type(para[6], reference)
|
|
eq_(para[6].astext(), '#5')
|
|
assert 'Support' in para[4].astext()
|
|
|
|
def unreleased_buckets_omit_major_version_when_only_one_exists(self):
|
|
result = self._generate(b(1), raw=True)[0][0][0]
|
|
html = str(result) # since repr() from test-fail hides actual text
|
|
assert "Next bugfix release" in html
|
|
|
|
def unreleased_buckets_display_major_version_when_multiple(self):
|
|
entries = (
|
|
b(3), # should appear in unreleased bugs for 2.x
|
|
'2.0.0',
|
|
b(2), # should appear in unreleased bugs for 1.x
|
|
'1.0.1',
|
|
b(1),
|
|
)
|
|
# Expectation: [2.x unreleased, 1.x unreleased, 1.0.1]
|
|
two_x, one_x, _ = self._generate(*entries, raw=True)
|
|
html = str(two_x[0][0])
|
|
assert "Next 2.x bugfix release" in html
|
|
html = str(one_x[0][0])
|
|
assert "Next 1.x bugfix release" in html
|
|
|
|
def unreleased_displays_version_when_only_some_lines_displayed(self):
|
|
# I.e. if there's unreleased 1.x stuff but no unreleased 2.x, still
|
|
# display the "1.x".
|
|
entries = (
|
|
# Note lack of any bugfixes post 2.0.0
|
|
'2.0.0',
|
|
b(2),
|
|
'1.0.1',
|
|
b(1),
|
|
)
|
|
# Expectation: [1.x unreleased, 1.0.1] - no 2.x.
|
|
result = self._generate(*entries, raw=True)
|
|
eq_(len(result), 2)
|
|
html = str(result[0][0][0])
|
|
assert "Next 1.x bugfix release" in html
|
|
|
|
def unstable_prehistory_active_means_only_one_unreleased_release(self):
|
|
app = make_app(unstable_prehistory=True)
|
|
entries = (b(2), f(3), '0.1.0', b(1))
|
|
result = self._generate(*entries, app=app, raw=True, skip_initial=True)
|
|
html = str(result[0][0][0])
|
|
assert "Next release" in html
|