Skip to content

Commit

Permalink
Merge pull request #345 from abnerpc/master
Browse files Browse the repository at this point in the history
Restructured cssformatter and added tests
  • Loading branch information
akalongman authored Nov 14, 2017
2 parents 3d7d2b7 + eb11992 commit 727321f
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ install:
- pip install -r dev-requirements.pip

script:
- pytest
- make test
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
clean:
@find . -name "*.pyc" | xargs rm -rf
@find . -name "*.pyo" | xargs rm -rf
@find . -name "__pycache__" -type d | xargs rm -rf
@find . -name ".cache" -type d | xargs rm -rf

test: clean
pytest
92 changes: 42 additions & 50 deletions codeformatter/cssformatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,54 @@ class CssFormatter:

def __init__(self, formatter):
self.formatter = formatter
self.opts = formatter.settings.get('codeformatter_css_options')
self.options = cssbeautifier.default_options()

# parse custom options from settings file
self.fill_custom_options(formatter.settings.get('codeformatter_css_options'))

def fill_custom_options(self, options):

if not options:
return

# map of key, value if key exists and value if key not exists
custom_options = [
('indent_size', None, 4),
('indent_char', None, ' '),
('indent_with_tabs', True, False),
('selector_separator_newline', True, False),
('end_with_newline', True, False),
('eol', None, '\n'),
('space_around_combinator', True, False),
('newline_between_rules', True, False),
('format_on_save', None, False)
]

casters = {'indent_char': str}

for key, on_value, off_value in custom_options:

if key not in options:
value = off_value
else:
value = options[key]
if value and on_value:
value = on_value
else:
cast = casters.get(key)
if cast:
value = cast(value)

setattr(self.options, key, value)

def format(self, text):

text = text.decode('utf-8')
stderr = ''
stdout = ''
options = cssbeautifier.default_options()

if ('indent_size' in self.opts and self.opts['indent_size']):
options.indent_size = self.opts['indent_size']
else:
options.indent_size = 4

if ('indent_char' in self.opts and self.opts['indent_char']):
options.indent_char = self.opts['indent_char']
else:
options.indent_char = ' '

if ('indent_with_tabs' in self.opts and self.opts['indent_with_tabs']):
options.indent_with_tabs = True
else:
options.indent_with_tabs = False

if (
'selector_separator_newline' in self.opts and
self.opts['selector_separator_newline']
):
options.selector_separator_newline = True
else:
options.selector_separator_newline = False

if ('end_with_newline' in self.opts and self.opts['end_with_newline']):
options.end_with_newline = True
else:
options.end_with_newline = False

if ('eol' in self.opts and self.opts['eol']):
options.eol = self.opts['eol']
else:
options.eol = '\n'

if ('space_around_combinator' in self.opts and self.opts['space_around_combinator']):
options.space_around_combinator = True
else:
options.space_around_combinator = False

if ('newline_between_rules' in self.opts and self.opts['newline_between_rules']):
options.newline_between_rules = True
else:
options.newline_between_rules = False

try:
stdout = cssbeautifier.beautify(text, options)
stdout = cssbeautifier.beautify(text, self.options)
except Exception as e:
stderr = str(e)

Expand All @@ -74,9 +68,7 @@ def format(self, text):
return stdout, stderr

def format_on_save_enabled(self, file_name):
format_on_save = False
if ('format_on_save' in self.opts and self.opts['format_on_save']):
format_on_save = self.opts['format_on_save']
if (isinstance(format_on_save, str)):
format_on_save = getattr(self.options, 'format_on_save', False)
if isinstance(format_on_save, str):
format_on_save = re.search(format_on_save, file_name) is not None
return format_on_save
13 changes: 13 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import os
import sys
import pytest
from unittest.mock import Mock

# mocking sublime
mocked_sublime = Mock()
mocked_sublime.version = Mock(return_value=3001)
sys.modules['sublime'] = mocked_sublime

# adding lib folder to syspath
directory = os.path.dirname(os.path.realpath(__file__))
libs_path = os.path.join(directory, '..', 'codeformatter', 'lib')
if libs_path not in sys.path:
sys.path.append(libs_path)


@pytest.fixture
def php_view():
Expand Down
8 changes: 8 additions & 0 deletions tests/scenarios.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

format_on_save_scenarios = [
({}, '', False),
({'format_on_save': True}, '', True),
({'format_on_save': False}, '', False),
({'format_on_save': '.test$'}, 'file.txt', False),
({'format_on_save': '.test$'}, 'file.test', True)
]
12 changes: 1 addition & 11 deletions tests/test_coldfusionformatter.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import sys
import pytest
from unittest.mock import patch, Mock, call

sys.modules['coldfusionbeautifier'] = Mock()
from .scenarios import format_on_save_scenarios


@patch('codeformatter.coldfusionformatter.coldfusionbeautifier')
Expand Down Expand Up @@ -131,15 +130,6 @@ def test_coldfusion_formatter_format_empty_exception(coldfusionbeautifier):
assert err == 'Formatting error!'


format_on_save_scenarios = [
({}, '', False),
({'format_on_save': True}, '', True),
({'format_on_save': False}, '', False),
({'format_on_save': '.test$'}, 'file.txt', False),
({'format_on_save': '.test$'}, 'file.test', True)
]


@pytest.mark.parametrize('options,filename,expected', format_on_save_scenarios)
@patch('codeformatter.coldfusionformatter.coldfusionbeautifier')
def test_coldfusion_formatter_format_on_save_enabled(
Expand Down
181 changes: 181 additions & 0 deletions tests/test_cssformatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import pytest
from unittest.mock import patch, Mock, call

from .scenarios import format_on_save_scenarios


@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_instance_creation(cssbeautifier):

cssbeautifier.default_options = Mock(
return_value={'band': 'beatles'})
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
mocked_formatter.settings = {
'codeformatter_css_options': 'a day in the life'}

with patch.object(CssFormatter, 'fill_custom_options'):
cf = CssFormatter(mocked_formatter)
assert cf.formatter == mocked_formatter
assert cf.options == {'band': 'beatles'}
cf.fill_custom_options.assert_called_once_with('a day in the life')


# options map to generate scenarios
options_to_test = [
('indent_size', (10, 10), (40, 40), (1, 1), 4),
('indent_char', ('a', 'a'), (1, '1'), (True, 'True'), ' '),
('indent_with_tabs', (True, True), ('a', True), (False, False), False),
('selector_separator_newline', (True, True), ('a', True), (False, False), False),
('end_with_newline', (True, True), ('a', True), (False, False), False),
('eol', (1, 1), ('a', 'a'), (False, False), '\n'),
('space_around_combinator', (True, True), ('a', True), (False, False), False),
('newline_between_rules', (True, True), ('a', True), (False, False), False),
]


# scenarios of not used properties
def get_not_used_scenarios(key):
values = []
for option in options_to_test:
if key == option[0]:
continue
values.append((option[0], option[-1]))
return values

# scenarios with partialy the values
options_scenarios_partialy = []
for key, t1, t2, t3, _ in options_to_test:
not_used_scenarios = get_not_used_scenarios(key)
options_scenarios_partialy.append((key, t1[0], t1[1], not_used_scenarios))
options_scenarios_partialy.append((key, t2[0], t2[1], not_used_scenarios))
options_scenarios_partialy.append((key, t3[0], t3[1], not_used_scenarios))


@pytest.mark.parametrize(
'key,value,expected,not_used_scenarios', options_scenarios_partialy)
@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_fill_custom_options_partialy(
cssbeautifier, key, value, expected, not_used_scenarios
):

fake_options = type('fake_obj', (object,), {})
cssbeautifier.default_options = Mock(return_value=fake_options)
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
curr_options = {}
curr_options[key] = value

mocked_formatter.settings = {'codeformatter_css_options': curr_options}

CssFormatter(mocked_formatter)
assert getattr(fake_options, key) == expected
for key, expected in not_used_scenarios:
assert getattr(fake_options, key, None) == expected


# scenarios with full the values
full_options_1, full_options_2, full_options_3 = [], [], []
for key, t1, t2, t3, _ in options_to_test:
full_options_1.append((key, t1[0], t1[1]))
full_options_2.append((key, t2[0], t2[1]))
full_options_3.append((key, t3[0], t3[1]))
options_scenarios_full = [full_options_1, full_options_2, full_options_3]


@pytest.mark.parametrize('full_options', options_scenarios_full)
@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_fill_custom_options_full(
cssbeautifier, full_options
):
fake_options = type('fake_obj', (object,), {})
cssbeautifier.default_options = Mock(return_value=fake_options)
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
curr_values = {}
curr_expected = []
for key, value, expected in full_options:
curr_values[key] = value
curr_expected.append((key, expected))

mocked_formatter.settings = {'codeformatter_css_options': curr_values}

CssFormatter(mocked_formatter)
for key, expected in curr_expected:
assert getattr(fake_options, key, None) == expected


@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_format(cssbeautifier):

cssbeautifier.default_options = Mock(return_value={})
cssbeautifier.beautify = Mock(return_value='graham nash')
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
mocked_formatter.settings = {'codeformatter_css_options': {}}

input_text = 'test'.encode('utf8')
cff = CssFormatter(mocked_formatter)
out, err = cff.format(input_text)

assert cssbeautifier.beautify.called_with(
call(input_text.decode('utf-8'), {}))
assert out == 'graham nash'
assert err == ''


@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_format_exception(cssbeautifier):

cssbeautifier.beautify = Mock(
side_effect=Exception('looks like it failed'))
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
mocked_formatter.settings = {'codeformatter_css_options': {}}

input_text = 'test'.encode('utf8')
cff = CssFormatter(mocked_formatter)

out, err = cff.format(input_text)
assert out == ''
assert err == 'looks like it failed'


@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_format_empty_exception(cssbeautifier):

cssbeautifier.beautify = Mock(side_effect=Exception(''))
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
mocked_formatter.settings = {'codeformatter_css_options': {}}

input_text = 'test'.encode('utf8')
cff = CssFormatter(mocked_formatter)

out, err = cff.format(input_text)
assert out == ''
assert err == 'Formatting error!'


@pytest.mark.parametrize('options,filename,expected', format_on_save_scenarios)
@patch('codeformatter.cssformatter.cssbeautifier')
def test_css_formatter_format_on_save_enabled(
cssbeautifier, options, filename, expected
):

fake_options = type('fake_obj', (object,), {})
cssbeautifier.default_options = Mock(return_value=fake_options)
from codeformatter.cssformatter import CssFormatter

mocked_formatter = Mock()
mocked_formatter.settings = {'codeformatter_css_options': options}

cff = CssFormatter(mocked_formatter)
res = cff.format_on_save_enabled(filename)
assert res is expected
7 changes: 0 additions & 7 deletions tests/test_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ def fill_module_mocks(formatter, settings):
formatter.ColdfusionFormatter = mf_coldfusion


def setup_function(function):
mocked_sublime = Mock()
mocked_sublime.version = Mock(return_value=3001)
import sys
sys.modules['sublime'] = mocked_sublime


def test_formatter_instance(default_settings, php_view):
from codeformatter import formatter
fill_module_mocks(formatter, default_settings)
Expand Down

0 comments on commit 727321f

Please sign in to comment.