|
1 /* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* Any copyright is dedicated to the Public Domain. |
|
4 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
5 |
|
6 const Cu = Components.utils; |
|
7 Cu.import("resource://gre/modules/devtools/Loader.jsm"); |
|
8 const {parseDeclarations} = devtools.require("devtools/styleinspector/css-parsing-utils"); |
|
9 |
|
10 const TEST_DATA = [ |
|
11 // Simple test |
|
12 { |
|
13 input: "p:v;", |
|
14 expected: [{name: "p", value: "v", priority: ""}] |
|
15 }, |
|
16 // Simple test |
|
17 { |
|
18 input: "this:is;a:test;", |
|
19 expected: [ |
|
20 {name: "this", value: "is", priority: ""}, |
|
21 {name: "a", value: "test", priority: ""} |
|
22 ] |
|
23 }, |
|
24 // Test a single declaration with semi-colon |
|
25 { |
|
26 input: "name:value;", |
|
27 expected: [{name: "name", value: "value", priority: ""}] |
|
28 }, |
|
29 // Test a single declaration without semi-colon |
|
30 { |
|
31 input: "name:value", |
|
32 expected: [{name: "name", value: "value", priority: ""}] |
|
33 }, |
|
34 // Test multiple declarations separated by whitespaces and carriage returns and tabs |
|
35 { |
|
36 input: "p1 : v1 ; \t\t \n p2:v2; \n\n\n\n\t p3 : v3;", |
|
37 expected: [ |
|
38 {name: "p1", value: "v1", priority: ""}, |
|
39 {name: "p2", value: "v2", priority: ""}, |
|
40 {name: "p3", value: "v3", priority: ""}, |
|
41 ] |
|
42 }, |
|
43 // Test simple priority |
|
44 { |
|
45 input: "p1: v1; p2: v2 !important;", |
|
46 expected: [ |
|
47 {name: "p1", value: "v1", priority: ""}, |
|
48 {name: "p2", value: "v2", priority: "important"} |
|
49 ] |
|
50 }, |
|
51 // Test simple priority |
|
52 { |
|
53 input: "p1: v1 !important; p2: v2", |
|
54 expected: [ |
|
55 {name: "p1", value: "v1", priority: "important"}, |
|
56 {name: "p2", value: "v2", priority: ""} |
|
57 ] |
|
58 }, |
|
59 // Test simple priority |
|
60 { |
|
61 input: "p1: v1 ! important; p2: v2 ! important;", |
|
62 expected: [ |
|
63 {name: "p1", value: "v1", priority: "important"}, |
|
64 {name: "p2", value: "v2", priority: "important"} |
|
65 ] |
|
66 }, |
|
67 // Test invalid priority |
|
68 { |
|
69 input: "p1: v1 important;", |
|
70 expected: [ |
|
71 {name: "p1", value: "v1 important", priority: ""} |
|
72 ] |
|
73 }, |
|
74 // Test various types of background-image urls |
|
75 { |
|
76 input: "background-image: url(../../relative/image.png)", |
|
77 expected: [{name: "background-image", value: "url(\"../../relative/image.png\")", priority: ""}] |
|
78 }, |
|
79 { |
|
80 input: "background-image: url(http://site.com/test.png)", |
|
81 expected: [{name: "background-image", value: "url(\"http://site.com/test.png\")", priority: ""}] |
|
82 }, |
|
83 { |
|
84 input: "background-image: url(wow.gif)", |
|
85 expected: [{name: "background-image", value: "url(\"wow.gif\")", priority: ""}] |
|
86 }, |
|
87 // Test that urls with :;{} characters in them are parsed correctly |
|
88 { |
|
89 input: "background: red url(\"http://site.com/image{}:;.png?id=4#wat\") repeat top right", |
|
90 expected: [ |
|
91 {name: "background", value: "red url(\"http://site.com/image{}:;.png?id=4#wat\") repeat top right", priority: ""} |
|
92 ] |
|
93 }, |
|
94 // Test that an empty string results in an empty array |
|
95 {input: "", expected: []}, |
|
96 // Test that a string comprised only of whitespaces results in an empty array |
|
97 {input: " \n \n \n \n \t \t\t\t ", expected: []}, |
|
98 // Test that a null input throws an exception |
|
99 {input: null, throws: true}, |
|
100 // Test that a undefined input throws an exception |
|
101 {input: undefined, throws: true}, |
|
102 // Test that :;{} characters in quoted content are not parsed as multiple declarations |
|
103 { |
|
104 input: "content: \";color:red;}selector{color:yellow;\"", |
|
105 expected: [ |
|
106 {name: "content", value: "\";color:red;}selector{color:yellow;\"", priority: ""} |
|
107 ] |
|
108 }, |
|
109 // Test that rules aren't parsed, just declarations. So { and } found after a |
|
110 // property name should be part of the property name, same for values. |
|
111 { |
|
112 input: "body {color:red;} p {color: blue;}", |
|
113 expected: [ |
|
114 {name: "body {color", value: "red", priority: ""}, |
|
115 {name: "} p {color", value: "blue", priority: ""}, |
|
116 {name: "}", value: "", priority: ""} |
|
117 ] |
|
118 }, |
|
119 // Test unbalanced : and ; |
|
120 { |
|
121 input: "color :red : font : arial;", |
|
122 expected : [ |
|
123 {name: "color", value: "red : font : arial", priority: ""} |
|
124 ] |
|
125 }, |
|
126 {input: "background: red;;;;;", expected: [{name: "background", value: "red", priority: ""}]}, |
|
127 {input: "background:;", expected: [{name: "background", value: "", priority: ""}]}, |
|
128 {input: ";;;;;", expected: []}, |
|
129 {input: ":;:;", expected: []}, |
|
130 // Test name only |
|
131 {input: "color", expected: [ |
|
132 {name: "color", value: "", priority: ""} |
|
133 ]}, |
|
134 // Test trailing name without : |
|
135 {input: "color:blue;font", expected: [ |
|
136 {name: "color", value: "blue", priority: ""}, |
|
137 {name: "font", value: "", priority: ""} |
|
138 ]}, |
|
139 // Test trailing name with : |
|
140 {input: "color:blue;font:", expected: [ |
|
141 {name: "color", value: "blue", priority: ""}, |
|
142 {name: "font", value: "", priority: ""} |
|
143 ]}, |
|
144 // Test leading value |
|
145 {input: "Arial;color:blue;", expected: [ |
|
146 {name: "", value: "Arial", priority: ""}, |
|
147 {name: "color", value: "blue", priority: ""} |
|
148 ]}, |
|
149 // Test hex colors |
|
150 {input: "color: #333", expected: [{name: "color", value: "#333", priority: ""}]}, |
|
151 {input: "color: #456789", expected: [{name: "color", value: "#456789", priority: ""}]}, |
|
152 {input: "wat: #XYZ", expected: [{name: "wat", value: "#XYZ", priority: ""}]}, |
|
153 // Test string/url quotes escaping |
|
154 {input: "content: \"this is a 'string'\"", expected: [{name: "content", value: "\"this is a 'string'\"", priority: ""}]}, |
|
155 {input: 'content: "this is a \\"string\\""', expected: [{name: "content", value: '\'this is a "string"\'', priority: ""}]}, |
|
156 {input: "content: 'this is a \"string\"'", expected: [{name: "content", value: '\'this is a "string"\'', priority: ""}]}, |
|
157 {input: "content: 'this is a \\'string\\'", expected: [{name: "content", value: '"this is a \'string\'"', priority: ""}]}, |
|
158 {input: "content: 'this \\' is a \" really strange string'", expected: [{name: "content", value: '"this \' is a \" really strange string"', priority: ""}]}, |
|
159 { |
|
160 input: "content: \"a not s\\\ |
|
161 o very long title\"", |
|
162 expected: [ |
|
163 {name: "content", value: '"a not s\ |
|
164 o very long title"', priority: ""} |
|
165 ] |
|
166 } |
|
167 ]; |
|
168 |
|
169 function run_test() { |
|
170 for (let test of TEST_DATA) { |
|
171 do_print("Test input string " + test.input); |
|
172 let output; |
|
173 try { |
|
174 output = parseDeclarations(test.input); |
|
175 } catch (e) { |
|
176 do_print("parseDeclarations threw an exception with the given input string"); |
|
177 if (test.throws) { |
|
178 do_print("Exception expected"); |
|
179 do_check_true(true); |
|
180 } else { |
|
181 do_print("Exception unexpected\n" + e); |
|
182 do_check_true(false); |
|
183 } |
|
184 } |
|
185 if (output) { |
|
186 assertOutput(output, test.expected); |
|
187 } |
|
188 } |
|
189 } |
|
190 |
|
191 function assertOutput(actual, expected) { |
|
192 if (actual.length === expected.length) { |
|
193 for (let i = 0; i < expected.length; i ++) { |
|
194 do_check_true(!!actual[i]); |
|
195 do_print("Check that the output item has the expected name, value and priority"); |
|
196 do_check_eq(expected[i].name, actual[i].name); |
|
197 do_check_eq(expected[i].value, actual[i].value); |
|
198 do_check_eq(expected[i].priority, actual[i].priority); |
|
199 } |
|
200 } else { |
|
201 for (let prop of actual) { |
|
202 do_print("Actual output contained: {name: "+prop.name+", value: "+prop.value+", priority: "+prop.priority+"}"); |
|
203 } |
|
204 do_check_eq(actual.length, expected.length); |
|
205 } |
|
206 } |