Skip to content

Commit

Permalink
Add some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
facelessuser committed Aug 27, 2022
1 parent 802d58a commit 3ac9422
Show file tree
Hide file tree
Showing 12 changed files with 1,081 additions and 35 deletions.
33 changes: 19 additions & 14 deletions pymdownx/blocks/admonitions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Admonitions."""
import xml.etree.ElementTree as etree
from .block import Block, type_string, type_class
from .block import Block, type_class


class Admonition(Block):
Expand All @@ -20,44 +20,49 @@ class Admonition(Block):
"""

NAME = 'admonition'
ARGUMENTS = {'required': 1, 'parsers': [type_string]}
ARGUMENTS = {'optional': 1}
OPTIONS = {
'type': ['', type_class],
}

def on_create(self, parent):
"""Create the element."""

# Set classes
classes = ['admonition']
atype = self.options['type']
if atype and atype != 'admonition':
classes.append(atype)

# Create the admonition
el = etree.SubElement(parent, 'div')
el = etree.SubElement(parent, 'div', {'class': ' '.join(classes)})

# Create the title
title = self.args[0]
ad_title = etree.SubElement(el, 'p', {'class': 'admonition-title'})
ad_title.text = title
if not self.args:
if not atype:
title = None
else:
title = atype.capitalize()
else:
title = self.args[0]

# Set classes
classes = ['admonition']
if self.options['type']:
classes.append(self.options['type'])
if title is not None:
ad_title = etree.SubElement(el, 'p', {'class': 'admonition-title'})
ad_title.text = title

el.set('class', ' '.join(classes))
return el


class Note(Admonition):
"""Note."""

NAME = 'note'
ARGUMENTS = {'optional': 1, 'parsers': [type_string]}
OPTIONS = {}

def on_parse(self):
"""Handle on parse event."""

self.options['type'] = self.NAME
if not self.args:
self.args.append(self.NAME.title())
return True


Expand Down
24 changes: 15 additions & 9 deletions pymdownx/blocks/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def _ranged_number(value, minimum, maximum, number_type):
def type_number(value):
"""Ensure type number or fail."""

if not isinstance(float, int):
if not isinstance(value, (float, int)):
raise ValueError("Could not convert type {} to a number".format(type(value)))

return value
Expand All @@ -40,22 +40,24 @@ def type_number(value):
def type_integer(value):
"""Ensure type integer or fail."""

if not isinstance(int):
raise ValueError("Could not convert type {} to an integer".format(type(value)))
if not isinstance(value, int):
if not isinstance(value, float) or not value.is_integer():
raise ValueError("Could not convert type {} to an integer".format(type(value)))
value = int(value)

return value


def type_ranged_number(minimum=None, maximum=None):
"""Ensure typed number is within range."""

functools.partial(_ranged_number, minimum=minimum, maximum=maximum, number_type=type_number)
return functools.partial(_ranged_number, minimum=minimum, maximum=maximum, number_type=type_number)


def type_ranged_integer(minimum=None, maximum=None):
"""Ensured type integer is within range."""

functools.partial(_ranged_number, minimum=minimum, maximum=maximum, number_type=type_integer)
return functools.partial(_ranged_number, minimum=minimum, maximum=maximum, number_type=type_integer)


def type_tag(value):
Expand Down Expand Up @@ -90,9 +92,6 @@ def type_string(value):
if isinstance(value, str):
return value

if isinstance(value, (int, float, bool)):
return str(value)

raise ValueError("Could not convert type {} to a string".format(type(value)))


Expand Down Expand Up @@ -248,7 +247,14 @@ def parse_config(self, args, **options):
return False

# Split arguments if we can have more than 1
arguments = type_string_delimiter(delim)(args) if total > 1 else [args]
if args is not None:
if total > 1:
arguments = type_string_delimiter(delim)(args)
else:
arguments = [args]
else:
arguments = []

length = len(arguments)

# If total number of arguments exceed what is allowed, quit
Expand Down
25 changes: 18 additions & 7 deletions pymdownx/blocks/details.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Details(Block):
Options:
- class: space delimited list of classes
- id: An ID
- type: A type class to use.
Content:
Expand All @@ -21,9 +21,9 @@ class Details(Block):

NAME = 'details'

ARGUMENTS = {'required': 1}
ARGUMENTS = {'optional': 1}
OPTIONS = {
'open': [[], type_boolean],
'open': [False, type_boolean],
'type': ['', type_class]
}

Expand All @@ -36,14 +36,25 @@ def on_create(self, parent):
attributes['open'] = 'open'

# Set classes
if self.options['type']:
attributes['class'] = self.options['type']
dtype = self.options['type']
if dtype:
attributes['class'] = dtype

# Create Detail element
el = etree.SubElement(parent, 'details', attributes)

# Create the summary
summary = etree.SubElement(el, 'summary')
summary.text = self.args[0]
if not self.args:
if not dtype:
summary = None
else:
summary = dtype.capitalize()
else:
summary = self.args[0]

# Create the summary
if summary is not None:
s = etree.SubElement(el, 'summary')
s.text = summary

return el
4 changes: 3 additions & 1 deletion pymdownx/blocks/tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ def on_add(self, parent):
self.tab_content = list(d)[-1]
return self.tab_content

return parent
# This shouldn't happen, but if it does, just return the parent.
# This can only happen if something else comes in and destroys are structure.
return parent # pragma: no cover
else:
return self.tab_content

Expand Down
1 change: 1 addition & 0 deletions tests/test_extensions/test_blocks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Test blocks."""
105 changes: 105 additions & 0 deletions tests/test_extensions/test_blocks/test_admonitions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""Test cases for Blocks (admonitions)."""
from ... import util


class TestBlocksAdmonitions(util.MdCase):
"""Test Blocks admonitions cases."""

extension = ['pymdownx.blocks']

def test_optional_title(self):
"""Test that tab is not processed if title is omitted."""

self.check_markdown(
R'''
/// admonition
Some *content*
///
''',
r'''
<div class="admonition">
<p>Some <em>content</em></p>
</div>
''', # noqa: E501
True
)

def test_type_no_title(self):
"""Test test type as title."""

self.check_markdown(
R'''
/// admonition
type: note
attributes:
class: other
Some *content*
///
''',
r'''
<div class="admonition note other">
<p class="admonition-title">Note</p>
<p>Some <em>content</em></p>
</div>
''', # noqa: E501
True
)

def test_admonition(self):
"""Test admonition with title."""

self.check_markdown(
R'''
/// admonition | A Title
Some *content*
///
''',
r'''
<div class="admonition">
<p class="admonition-title">A Title</p>
<p>Some <em>content</em></p>
</div>
''', # noqa: E501
True
)

def test_note_no_title(self):
"""Test note with no title."""

self.check_markdown(
R'''
/// note
Some *content*
///
''',
r'''
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Some <em>content</em></p>
</div>
''', # noqa: E501
True
)

def test_note_with_title(self):
"""Test note with no title."""

self.check_markdown(
R'''
/// note | A Title
Some *content*
///
''',
r'''
<div class="admonition note">
<p class="admonition-title">A Title</p>
<p>Some <em>content</em></p>
</div>
''', # noqa: E501
True
)
87 changes: 87 additions & 0 deletions tests/test_extensions/test_blocks/test_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Test cases for Blocks (details)."""
from ... import util


class TestBlocksDetails(util.MdCase):
"""Test Blocks details cases."""

extension = ['pymdownx.blocks']

def test_optional_title(self):
"""Test that tab is not processed if title is omitted."""

self.check_markdown(
R'''
/// details
Some *content*
///
''',
r'''
<details>
<p>Some <em>content</em></p>
</details>
''', # noqa: E501
True
)

def test_type_no_title(self):
"""Test test type as title."""

self.check_markdown(
R'''
/// details
type: note
attributes:
class: other
Some *content*
///
''',
r'''
<details class="note other">
<summary>Note</summary>
<p>Some <em>content</em></p>
</details>
''', # noqa: E501
True
)

def test_details(self):
"""Test details with title."""

self.check_markdown(
R'''
/// details | A Title
Some *content*
///
''',
r'''
<details>
<summary>A Title</summary>
<p>Some <em>content</em></p>
</details>
''', # noqa: E501
True
)

def test_details_open(self):
"""Test details forced open."""

self.check_markdown(
R'''
/// details | A Title
open: true
Some *content*
///
''',
r'''
<details open="open">
<summary>A Title</summary>
<p>Some <em>content</em></p>
</details>
''', # noqa: E501
True
)
Loading

0 comments on commit 3ac9422

Please sign in to comment.