Skip to content

Commit

Permalink
Add unit tests for compiler implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
fdintino committed Feb 22, 2016
1 parent e74ab5c commit 6d3e470
Show file tree
Hide file tree
Showing 19 changed files with 250 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ docs/_build/
coverage/
tests/static/
tests/assets/js/dummy.js
tests/node_modules/
.tox/
.DS_Store
.idea
Expand All @@ -21,3 +22,6 @@ tests/assets/js/dummy.js
.pydevproject
.ropeproject
__pycache__
npm-debug.log
tests/npm-cache
django-pipeline-*/
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ recursive-include pipeline/jinja2 *.html *.jinja
include AUTHORS LICENSE README.rst HISTORY.rst
recursive-include tests *
recursive-exclude tests *.pyc *.pyo
recursive-exclude tests/node_modules *
recursive-exclude tests/npm-cache *
recursive-exclude tests/npm *
include docs/Makefile docs/make.bat docs/conf.py
recursive-include docs *.rst
12 changes: 12 additions & 0 deletions tests/assets/compilers/coffee/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(function() {
var cube, square;

square = function(x) {
return x * x;
};

cube = function(x) {
return square(x) * x;
};

}).call(this);
2 changes: 2 additions & 0 deletions tests/assets/compilers/coffee/input.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
square = (x) -> x * x
cube = (x) -> square(x) * x
27 changes: 27 additions & 0 deletions tests/assets/compilers/es6/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use strict";

// Expression bodies
var odds = evens.map(function (v) {
return v + 1;
});
var nums = evens.map(function (v, i) {
return v + i;
});

// Statement bodies
nums.forEach(function (v) {
if (v % 5 === 0) fives.push(v);
});

// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends: function printFriends() {
var _this = this;

this._friends.forEach(function (f) {
return console.log(_this._name + " knows " + f);
});
}
};
19 changes: 19 additions & 0 deletions tests/assets/compilers/es6/input.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);

// Statement bodies
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});

// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
};
3 changes: 3 additions & 0 deletions tests/assets/compilers/less/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.a {
width: 1px;
}
5 changes: 5 additions & 0 deletions tests/assets/compilers/less/input.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@a: 1;

.a {
width: (@a + 0px);
}
6 changes: 6 additions & 0 deletions tests/assets/compilers/livescript/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(function(){
var times;
times = function(x, y){
return x * y;
};
}).call(this);
2 changes: 2 additions & 0 deletions tests/assets/compilers/livescript/input.ls
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
times = (x, y) ->
x * y
5 changes: 5 additions & 0 deletions tests/assets/compilers/scss/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.a .b {
display: none; }

.c .d {
display: block; }
10 changes: 10 additions & 0 deletions tests/assets/compilers/scss/input.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.a {
.b {
display: none;
}
}
.c {
.d {
display: block;
}
}
3 changes: 3 additions & 0 deletions tests/assets/compilers/stylus/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.a {
color: #000;
}
2 changes: 2 additions & 0 deletions tests/assets/compilers/stylus/input.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.a
color: black
22 changes: 22 additions & 0 deletions tests/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "django-pipeline-tests",
"private": true,
"version": "1.0.0",
"description": "Pipeline is an asset packaging library for Django.",
"author": "Timothée Peignier <timothee.peignier@tryphon.org>",
"license": "MIT",
"readmeFilename": "../README.rst",
"repository": {
"type": "git",
"url": "git://github.com/jazzband/django-pipeline.git"
},
"dependencies": {
"babel-cli": "^6.4.5",
"babel-preset-es2015": "^6.3.13",
"coffee-script": "^1.10.0",
"less": "^2.5.3",
"livescript": "^1.4.0",
"node-sass": "^3.4.2",
"stylus": "^0.53.0"
}
}
42 changes: 42 additions & 0 deletions tests/scripts/npm_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python
"""
A cross-platform compatible `npm install` call, checking whether npm is
in fact installed on the system first (and on windows, checking that the
npm version is at least 3.0 because of a bug in 2.x with MAX_PATH)
"""
import distutils.spawn
import os
from pkg_resources import parse_version
import re
import subprocess
import sys


def main():
tests_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
if os.name == 'nt':
try:
npm_paths = subprocess.check_output(['where', 'npm.cmd'])
except subprocess.CalledProcessError:
return
else:
npm_bin = re.split(r'\r?\n', npm_paths)[0]
else:
npm_bin = distutils.spawn.find_executable('npm')
if not npm_bin:
return
if os.name == 'nt':
os.environ.setdefault('APPDATA', '.')
npm_version = subprocess.check_output([npm_bin, '--version']).strip()
# Skip on windows if npm version is less than 3 because of
# MAX_PATH issues in version 2
if parse_version(npm_version) < parse_version('3.0'):
return
pipe = subprocess.Popen([npm_bin, 'install'],
cwd=tests_dir, stdout=sys.stdout, stderr=sys.stderr)
pipe.communicate()
sys.exit(pipe.returncode)


if __name__ == '__main__':
main()
23 changes: 23 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import distutils.spawn


def local_path(path):
Expand Down Expand Up @@ -118,6 +119,28 @@ def local_path(path):
}
}

NODE_MODULES_PATH = local_path('node_modules')
NODE_BIN_PATH = os.path.join(NODE_MODULES_PATH, '.bin')
NODE_EXE_PATH = distutils.spawn.find_executable('node')
HAS_NODE = os.path.exists(NODE_BIN_PATH) and NODE_EXE_PATH

if HAS_NODE:
def node_exe_path(command):
exe_ext = '.cmd' if os.name == 'nt' else ''
return os.path.join(NODE_BIN_PATH, "%s%s" % (command, exe_ext))

PIPELINE.update({
'SASS_BINARY': node_exe_path('node-sass'),
'COFFEE_SCRIPT_BINARY': node_exe_path('coffee'),
'COFFEE_SCRIPT_ARGUMENTS': ['--no-header'],
'LESS_BINARY': node_exe_path('lessc'),
'BABEL_BINARY': node_exe_path('babel'),
'BABEL_ARGUMENTS': ['--presets', 'es2015'],
'STYLUS_BINARY': node_exe_path('stylus'),
'LIVE_SCRIPT_BINARY': node_exe_path('lsc'),
'LIVE_SCRIPT_ARGUMENTS': ['--no-header'],
})

TEMPLATE_DIRS = (
local_path('templates'),
)
Expand Down
60 changes: 59 additions & 1 deletion tests/tests/test_compiler.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from __future__ import unicode_literals

import sys
from unittest import skipIf
from unittest import skipIf, skipUnless

from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage
from django.test import TestCase
from django.test.client import RequestFactory
from django.utils.encoding import smart_bytes

from pipeline.collector import default_collector
from pipeline.compilers import Compiler, CompilerBase, SubProcessCompiler
from pipeline.exceptions import CompilerError
from pipeline.utils import to_class

from tests.utils import _, pipeline_settings

Expand Down Expand Up @@ -169,3 +174,56 @@ def test_compile(self):

def tearDown(self):
default_collector.clear()


@skipUnless(settings.HAS_NODE, "requires node")
class CompilerImplementation(TestCase):

def setUp(self):
self.compiler = Compiler()
default_collector.collect(RequestFactory().get('/'))

def tearDown(self):
default_collector.clear()

def _test_compiler(self, compiler_cls_str, infile, expected):
compiler_cls = to_class(compiler_cls_str)
compiler = compiler_cls(verbose=False, storage=staticfiles_storage)
infile_path = staticfiles_storage.path(infile)
outfile_path = compiler.output_path(infile_path, compiler.output_extension)
compiler.compile_file(_(infile_path), _(outfile_path), force=True)
with open(outfile_path) as f:
result = f.read()
with staticfiles_storage.open(expected) as f:
expected = f.read()
self.assertEqual(smart_bytes(result), expected)

def test_sass(self):
self._test_compiler('pipeline.compilers.sass.SASSCompiler',
'pipeline/compilers/scss/input.scss',
'pipeline/compilers/scss/expected.css')

def test_coffeescript(self):
self._test_compiler('pipeline.compilers.coffee.CoffeeScriptCompiler',
'pipeline/compilers/coffee/input.coffee',
'pipeline/compilers/coffee/expected.js')

def test_less(self):
self._test_compiler('pipeline.compilers.less.LessCompiler',
'pipeline/compilers/less/input.less',
'pipeline/compilers/less/expected.css')

def test_es6(self):
self._test_compiler('pipeline.compilers.es6.ES6Compiler',
'pipeline/compilers/es6/input.es6',
'pipeline/compilers/es6/expected.js')

def test_stylus(self):
self._test_compiler('pipeline.compilers.stylus.StylusCompiler',
'pipeline/compilers/stylus/input.styl',
'pipeline/compilers/stylus/expected.css')

def test_livescript(self):
self._test_compiler('pipeline.compilers.livescript.LiveScriptCompiler',
'pipeline/compilers/livescript/input.ls',
'pipeline/compilers/livescript/expected.js')
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ setenv =
DJANGO_SETTINGS_MODULE = tests.settings
PYTHONPATH = {toxinidir}
commands =
{toxinidir}/tests/scripts/npm_install.py
{envbindir}/django-admin.py test {posargs:tests}

[testenv:docs]
Expand Down

0 comments on commit 6d3e470

Please sign in to comment.