summaryrefslogtreecommitdiff
path: root/scss/tests/test_expression.py
blob: 713504232ca1b0074d2cda7a3bf5f0425c8291bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
from scss.expression import Calculator
from scss.rule import Namespace
from scss.types import NumberValue
from scss.util import to_str

import pytest


def test_reference_operations():
    """Test the example expressions in the reference document:

    http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#operations
    """
    # TODO: break this into its own file and add the entire reference guide
    ns = Namespace()
    calc = lambda expr: Calculator(ns).evaluate_expression(expr).render()

    # Simple example
    assert calc('1in + 8pt') == '1.11111in'

    # Division
    ns.set_variable('$width', '1000px')
    ns.set_variable('$font-size', '12px')
    ns.set_variable('$line-height', '30px')
    assert calc('10px/8px') == '10px / 8px' # plain CSS; no division
    assert calc('$width/2') == '500px'      # uses a variable; does division
    assert calc('(500px/2)') == '250px'     # uses parens; does division
    assert calc('5px + 8px/2px') == '9px'   # uses +; does division
    assert calc('#{$font-size}/#{$line-height}') == '12px/30px'
                                            # uses #{}; does no division

    # Color operations
    ns.set_variable('$translucent-red', 'rgba(255, 0, 0, 0.5)')
    ns.set_variable('$green', '#00ff00')
    assert calc('#010203 + #040506') == '#050709'
    assert calc('#010203 * 2') == '#020406'
    assert calc('rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75)') == 'rgba(255, 255, 0, 0.75)'
    assert calc('opacify($translucent-red, 0.3)') == 'rgba(255, 0, 0, 0.9)'
    assert calc('transparentize($translucent-red, 0.25)') == 'rgba(255, 0, 0, 0.25)'
    assert calc("progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}')"
                ) == "progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr=#FF00FF00, endColorstr=#80FF0000)"

    # String operations
    ns.set_variable('$value', 'null')
    assert calc('e + -resize') == 'e-resize'
    assert calc('"Foo " + Bar') == '"Foo Bar"'
    assert calc('sans- + "serif"') == 'sans-serif'
    assert calc('3px + 4px auto') == '7px auto'
    assert calc('"I ate #{5 + 10} pies!"') == '"I ate 15 pies!"'
    assert calc('"I ate #{$value} pies!"') == '"I ate  pies!"'



# Operators: arithmetic (+ - * / %), unary (+ -), comparison (== != < > <= >=), boolean
# Types: numbers, colors, strings, booleans, lists
# Test them all!

def test_addition():
    calc = lambda expr: to_str(Calculator(Namespace()).calculate(expr))

    assert calc('123 + 456') == '579'

    assert calc('1px + 2px') == '3px'

    assert calc('123 + abc') == '123abc'
    assert calc('abc + 123') == 'abc123'

    assert calc('abc + def') == 'abcdef'
    assert calc('abc + "def"') == 'abcdef'
    assert calc('"abc" + def') == '"abcdef"'
    assert calc('"abc" + "def"') == '"abcdef"'

    assert calc('#010305 + #050301') == '#060606'
    assert calc('#ffffff + #ffffff') == '#ffffff'

def test_subtraction():
    calc = lambda expr: to_str(Calculator(Namespace()).calculate(expr))

    assert calc('123 - 456') == '-333'
    assert calc('456 - 123') == '333'
    # TODO test that subtracting e.g. strings doesn't work

    assert calc('#0f0f0f - #050505') == '#0a0a0a'

def test_division():
    calc = Calculator(Namespace()).calculate

    assert calc('(5px / 5px)') == NumberValue(1)

def test_comparison_numeric():
    calc = Calculator(Namespace()).calculate

    assert calc('123 < 456')
    assert calc('123 <= 456')
    assert calc('123 <= 123')
    assert calc('456 > 123')
    assert calc('456 >= 123')
    assert calc('456 >= 456')
    assert calc('123 == 123')
    assert calc('123 != 456')

    # Same tests, negated
    assert not calc('123 > 456')
    assert not calc('123 >= 456')
    assert not calc('456 < 123')
    assert not calc('456 <= 123')
    assert not calc('123 != 123')
    assert not calc('123 == 456')

def test_comparison_stringerific():
    calc = Calculator(Namespace()).calculate

    assert calc('"abc" == "abc"')
    assert calc('"abc" != "xyz"')

    # Same tests, negated
    assert not calc('"abc" != "abc"')
    assert not calc('"abc" == "xyz"')

    # Interaction with other types
    assert calc('123 != "123"')

    # Sass strings don't support ordering
    for expression in (
            '"abc" < "xyz"',
            '"abc" <= "xyz"',
            '"abc" <= "abc"',
            '"xyz" > "abc"',
            '"xyz" >= "abc"',
            '"xyz" >= "xyz"',
            '123 < "456"'):

        with pytest.raises(TypeError):
            calc(expression)

def test_comparison_null():
    calc = Calculator(Namespace()).calculate

    assert calc('null == null')
    assert calc('null != 0')

    with pytest.raises(TypeError):
        calc('null < null')



# TODO write more!  i'm lazy.