Merge lp:~jjacobs/methanal/util-tests into lp:methanal

Proposed by Jonathan Jacobs
Status: Merged
Approved by: Tristan Seligmann
Approved revision: 112
Merged at revision: not available
Proposed branch: lp:~jjacobs/methanal/util-tests
Merge into: lp:methanal
Diff against target: 454 lines
5 files modified
methanal/js/Methanal/Tests/DOMUtil.js (+0/-75)
methanal/js/Methanal/Tests/MockBrowser.js (+102/-0)
methanal/js/Methanal/Tests/TestUtil.js (+178/-5)
methanal/js/Methanal/Tests/TestView.js (+2/-2)
methanal/js/Methanal/Util.js (+16/-7)
To merge this branch: bzr merge lp:~jjacobs/methanal/util-tests
Reviewer Review Type Date Requested Status
Tristan Seligmann Approve
Review via email: mp+13234@code.launchpad.net

This proposal supersedes a proposal from 2009-10-12.

To post a comment you must log in.
Revision history for this message
Tristan Seligmann (mithrandi) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'methanal/js/Methanal/Tests/DOMUtil.js'
2--- methanal/js/Methanal/Tests/DOMUtil.js 2009-10-10 10:28:01 +0000
3+++ methanal/js/Methanal/Tests/DOMUtil.js 1970-01-01 00:00:00 +0000
4@@ -1,75 +0,0 @@
5-// import Divmod.MockBrowser
6-
7-
8-
9-/**
10- * HTMLSelectElement mock implementation.
11- */
12-Divmod.MockBrowser.Element.subclass(
13- Methanal.Tests.DOMUtil, 'MockHTMLSelectElement').methods(
14- function __init__(self) {
15- Methanal.Tests.DOMUtil.MockHTMLSelectElement.upcall(
16- self, '__init__', 'select');
17- self.options = [];
18- },
19-
20-
21- /**
22- * Add a new element to the collection of OPTION elements for this SELECT.
23- */
24- function add(self, element, before) {
25- var index = Methanal.Util.arrayIndexOf(self.options, before);
26- if (index == -1) {
27- index = self.options.length;
28- self.options.push(element);
29- } else {
30- self.options.splice(index, 0, element);
31- }
32- element.index = index;
33- });
34-
35-
36-
37-/**
38- * HTMLDocument mock implementation.
39- */
40-Divmod.MockBrowser.Document.subclass(
41- Methanal.Tests.DOMUtil, 'Document').methods(
42- function __init__(self) {
43- self._elementTags = {};
44- Methanal.Tests.DOMUtil.Document.upcall(self, '__init__');
45- },
46-
47-
48- /**
49- * Register a new type for a tag name.
50- */
51- function registerElementTag(self, tagName, type) {
52- var old = self._elementTags[tagName];
53- self._elementTags[tagName] = type;
54- return old;
55- },
56-
57-
58- function createElement(self, tagName) {
59- var el;
60- if (self._elementTags[tagName]) {
61- el = self._elementTags[tagName]();
62- } else {
63- el = Divmod.MockBrowser.Element(tagName);
64- }
65- el._setOwnerDocument(self);
66- self._allElements.push(el);
67- return el;
68- });
69-
70-
71-
72-// Only override Divmod's mock document.
73-if (document instanceof Divmod.MockBrowser.Document) {
74- if (!(document instanceof Methanal.Tests.DOMUtil.Document)) {
75- document = Methanal.Tests.DOMUtil.Document();
76- document.registerElementTag(
77- 'select', Methanal.Tests.DOMUtil.MockHTMLSelectElement);
78- }
79-}
80
81=== added file 'methanal/js/Methanal/Tests/MockBrowser.js'
82--- methanal/js/Methanal/Tests/MockBrowser.js 1970-01-01 00:00:00 +0000
83+++ methanal/js/Methanal/Tests/MockBrowser.js 2009-10-12 17:10:19 +0000
84@@ -0,0 +1,102 @@
85+// import Divmod.MockBrowser
86+
87+
88+
89+Divmod.MockBrowser.Element.subclass(
90+ Methanal.Tests.MockBrowser, 'Element').methods(
91+ function __init__(self, tagName) {
92+ Methanal.Tests.MockBrowser.Element.upcall(self, '__init__', tagName);
93+ self._updateChildProperties();
94+ },
95+
96+
97+ function _updateChildProperties(self) {
98+ self.firstChild = self.childNodes[0] || null;
99+ self.lastChild = self.childNodes[self.childNodes.length - 1] || null;
100+ },
101+
102+
103+ function appendChild(self, child) {
104+ Methanal.Tests.MockBrowser.Element.upcall(self, 'appendChild', child);
105+ self._updateChildProperties();
106+ },
107+
108+
109+ function removeChild(self, child) {
110+ Methanal.Tests.MockBrowser.Element.upcall(self, 'removeChild', child);
111+ self._updateChildProperties();
112+ });
113+
114+
115+
116+/**
117+ * HTMLSelectElement mock implementation.
118+ */
119+Methanal.Tests.MockBrowser.Element.subclass(
120+ Methanal.Tests.MockBrowser, 'MockHTMLSelectElement').methods(
121+ function __init__(self) {
122+ Methanal.Tests.MockBrowser.MockHTMLSelectElement.upcall(
123+ self, '__init__', 'select');
124+ self.options = [];
125+ },
126+
127+
128+ /**
129+ * Add a new element to the collection of OPTION elements for this SELECT.
130+ */
131+ function add(self, element, before) {
132+ var index = Methanal.Util.arrayIndexOf(self.options, before);
133+ if (index == -1) {
134+ index = self.options.length;
135+ self.options.push(element);
136+ } else {
137+ self.options.splice(index, 0, element);
138+ }
139+ element.index = index;
140+ });
141+
142+
143+
144+/**
145+ * HTMLDocument mock implementation.
146+ */
147+Divmod.MockBrowser.Document.subclass(
148+ Methanal.Tests.MockBrowser, 'Document').methods(
149+ function __init__(self) {
150+ self._elementTags = {};
151+ Methanal.Tests.MockBrowser.Document.upcall(self, '__init__');
152+ },
153+
154+
155+ /**
156+ * Register a new type for a tag name.
157+ */
158+ function registerElementTag(self, tagName, type) {
159+ var old = self._elementTags[tagName];
160+ self._elementTags[tagName] = type;
161+ return old;
162+ },
163+
164+
165+ function createElement(self, tagName) {
166+ var el;
167+ if (self._elementTags[tagName]) {
168+ el = self._elementTags[tagName]();
169+ } else {
170+ el = Methanal.Tests.MockBrowser.Element(tagName);
171+ }
172+ el._setOwnerDocument(self);
173+ self._allElements.push(el);
174+ return el;
175+ });
176+
177+
178+
179+// Only override Divmod's mock document.
180+if (document instanceof Divmod.MockBrowser.Document) {
181+ if (!(document instanceof Methanal.Tests.MockBrowser.Document)) {
182+ document = Methanal.Tests.MockBrowser.Document();
183+ document.registerElementTag(
184+ 'select', Methanal.Tests.MockBrowser.MockHTMLSelectElement);
185+ }
186+}
187
188=== modified file 'methanal/js/Methanal/Tests/TestUtil.js'
189--- methanal/js/Methanal/Tests/TestUtil.js 2009-10-10 10:28:01 +0000
190+++ methanal/js/Methanal/Tests/TestUtil.js 2009-10-12 17:10:19 +0000
191@@ -1,11 +1,184 @@
192 // import Divmod.UnitTest
193-// import Divmod.MockBrowser
194 // import Methanal.Util
195 // import Methanal.Tests.Util
196-
197-
198-
199-Divmod.UnitTest.TestCase.subclass(Methanal.Tests.TestUtil, 'TestUtil').methods(
200+// import Methanal.Tests.MockBrowser
201+
202+
203+
204+Methanal.Tests.Util.TestCase.subclass(
205+ Methanal.Tests.TestUtil, 'TestUtil').methods(
206+ /**
207+ * L{Methanal.Util.addElementClass} and L{Methanal.Util.removeElementClass}
208+ * add and remove values to an element's C{className} attribute.
209+ */
210+ function test_addRemoveElementClass(self) {
211+ var node = document.createElement('div');
212+ var addElementClass = Methanal.Util.addElementClass;
213+ var removeElementClass = Methanal.Util.removeElementClass;
214+
215+ addElementClass(node, 'foo');
216+ self.assertIdentical(node.className, 'foo');
217+ addElementClass(node, 'foo');
218+ self.assertIdentical(node.className, 'foo');
219+
220+ addElementClass(node, 'bar');
221+ self.assertIdentical(node.className, 'foo bar');
222+
223+ removeElementClass(node, 'foo');
224+ self.assertIdentical(node.className, 'bar');
225+
226+ removeElementClass(node, 'bar');
227+ self.assertIdentical(node.className, '');
228+
229+ removeElementClass(node, 'bar');
230+ self.assertIdentical(node.className, '');
231+ },
232+
233+
234+ /**
235+ * Create a DOM node with some children.
236+ */
237+ function _makeNodeWithChildren(self) {
238+ var T = Methanal.Util.DOMBuilder(document);
239+ var node = T('div', {}, [
240+ T('span', {}, ['hello ',
241+ T('strong', {}, 'world')]),
242+ T('em', {}, ['!'])]);
243+ self.assertIdentical(node.childNodes.length, 2);
244+ return node;
245+ },
246+
247+
248+ /**
249+ * L{Methanal.Util.removeNodeContent} removes all of a node's children.
250+ */
251+ function test_removeNodeContent(self) {
252+ var node = self._makeNodeWithChildren();
253+ Methanal.Util.removeNodeContent(node);
254+ self.assertIdentical(node.childNodes.length, 0);
255+ },
256+
257+
258+ /**
259+ * L{Methanal.Util.replaceNodeContent} replaces a node's children with
260+ * some other children.
261+ */
262+ function test_replaceNodeContent(self) {
263+ var T = Methanal.Util.DOMBuilder(document);
264+ var node = self._makeNodeWithChildren();
265+ var children = [T('strong', {}, ['yay'])];
266+ Methanal.Util.replaceNodeContent(node, children);
267+ self.assertArraysEqual(node.childNodes, children);
268+ },
269+
270+
271+ /**
272+ * L{Methanal.Util.replaceNodeText} replaces a node's content with a text
273+ * node.
274+ */
275+ function test_replaceNodeText(self) {
276+ var node = self._makeNodeWithChildren();
277+ Methanal.Util.replaceNodeText(node, 'hey');
278+ self.assertIdentical(node.childNodes.length, 1);
279+ self.assertIsInstanceOf(node.firstChild, Divmod.MockBrowser.TextNode);
280+ },
281+
282+
283+ /**
284+ * L{Methanal.Util.formatDecimal} pretty-prints a number with thousand
285+ * separators.
286+ */
287+ function test_formatDecimal(self) {
288+ var formatDecimal = Methanal.Util.formatDecimal;
289+ self.assertIdentical(formatDecimal(1), '1');
290+ self.assertIdentical(formatDecimal(100), '100');
291+ self.assertIdentical(formatDecimal(1000), '1,000');
292+ self.assertIdentical(formatDecimal(10000), '10,000');
293+ self.assertIdentical(formatDecimal(1000000), '1,000,000');
294+
295+ self.assertIdentical(formatDecimal(1000.25), '1,000.25');
296+ self.assertIdentical(formatDecimal(1000000.66), '1,000,000.66');
297+ },
298+
299+
300+ /**
301+ * L{Methanal.Util.cycle} produces a callable that iterates through
302+ * the original arguments indefinitely.
303+ */
304+ function test_cycle(self) {
305+ var cycler = Methanal.Util.cycle(42, 5144, 'a');
306+ self.assertIdentical(cycler(), 42);
307+ self.assertIdentical(cycler(), 5144);
308+ self.assertIdentical(cycler(), 'a');
309+ self.assertIdentical(cycler(), 42);
310+ },
311+
312+
313+ /**
314+ * L{Methanal.Util.arrayIndexOf} finds the first index of an element in an
315+ * array, or C{-1} if no such element exists.
316+ */
317+ function test_arrayIndexOf(self) {
318+ var arrayIndexOf = Methanal.Util.arrayIndexOf;
319+ var a = ['x', 'y', 'z', 'x'];
320+ self.assertIdentical(arrayIndexOf(a, 'x'), 0);
321+ self.assertIdentical(arrayIndexOf(a, 'y'), 1);
322+ self.assertIdentical(arrayIndexOf(a, 'z'), 2);
323+ self.assertIdentical(arrayIndexOf(a, 'a'), -1);
324+ },
325+
326+
327+ /**
328+ * L{Methanal.Util.nodeInserted} calls a widget's C{nodeInserted} method
329+ * and the C{nodeInserted} method of each child widget.
330+ */
331+ function test_nodeInserted(self) {
332+ function makeWidget(childWidgets) {
333+ return {
334+ 'childWidgets': childWidgets,
335+ 'nodeInserted': function () {
336+ this.nodeInserted = true;
337+ }};
338+ };
339+
340+ var childWidgets = [];
341+ for (var i = 0; i < 5; ++i) {
342+ childWidgets.push(makeWidget([]));
343+ }
344+ var widget = makeWidget(childWidgets);
345+
346+ Methanal.Util.nodeInserted(widget);
347+ self.assertIdentical(widget.nodeInserted, true);
348+ for (var i = 0; i < childWidgets.length; ++i) {
349+ self.assertIdentical(childWidgets[i].nodeInserted, true);
350+ }
351+ },
352+
353+
354+ /**
355+ * L{Methanal.Util.repr} converts an object to a human-readable string.
356+ */
357+ function test_repr(self) {
358+ var repr = Methanal.Util.repr;
359+ self.assertIdentical(repr('a'), '"a"');
360+ self.assertIdentical(repr('a"b"c'), '"a\\"b\\"c"');
361+ self.assertIdentical(repr(1), '1');
362+ self.assertIdentical(repr(null), 'null');
363+ self.assertIdentical(repr(undefined), 'undefined');
364+ self.assertIdentical(repr(repr), '<function repr>');
365+ var a = [1, 2, 3, 'a', ['b', '"c"']];
366+ self.assertIdentical(repr(a), '[1, 2, 3, "a", ["b", "\\"c\\""]]');
367+ var o = {a: 1};
368+ self.assertIdentical(repr(o), '{"a": 1}');
369+ var o2 = {a: 1, b: 2};
370+ self.assertIdentical(repr(o2), '{"a": 1, "b": 2}');
371+
372+ var type = Divmod.Class.subclass('Foo');
373+ var i = type();
374+ self.assertIdentical(repr(i), i.toString());
375+ },
376+
377+
378 /**
379 * L{Methanal.Util.strToInt} converts a base-10 integer value, represented
380 * as a C{String}, to an C{Integer}.
381
382=== modified file 'methanal/js/Methanal/Tests/TestView.js'
383--- methanal/js/Methanal/Tests/TestView.js 2009-10-10 10:28:01 +0000
384+++ methanal/js/Methanal/Tests/TestView.js 2009-10-12 17:10:19 +0000
385@@ -3,7 +3,7 @@
386 // import Methanal.View
387 // import Methanal.Util
388 // import Methanal.Tests.Util
389-// import Methanal.Tests.DOMUtil
390+// import Methanal.Tests.MockBrowser
391
392
393
394@@ -374,7 +374,7 @@
395 /**
396 * Mimic Internet Explorer's broken C{HTMLSelectElement.add} behaviour.
397 */
398-Methanal.Tests.DOMUtil.MockHTMLSelectElement.subclass(
399+Methanal.Tests.MockBrowser.MockHTMLSelectElement.subclass(
400 Methanal.Tests.TestView, 'MockIEHTMLSelectElement').methods(
401 function add(self, element, before) {
402 if (before === null) {
403
404=== modified file 'methanal/js/Methanal/Util.js'
405--- methanal/js/Methanal/Util.js 2009-10-10 10:28:01 +0000
406+++ methanal/js/Methanal/Util.js 2009-10-12 17:10:19 +0000
407@@ -1,7 +1,3 @@
408-// import Nevow.Athena
409-
410-
411-
412 /**
413 * Add a class to an element's "className" attribute.
414 *
415@@ -95,7 +91,7 @@
416 *
417 * @type node: DOM node
418 *
419- * @type children: C{Array}
420+ * @type children: C{Array} of C{DOM nodes}
421 */
422 Methanal.Util.replaceNodeContent = function replaceNodeContent(node, children) {
423 Methanal.Util.removeNodeContent(node);
424@@ -107,7 +103,7 @@
425
426
427 /**
428- * Replace a node's text node with new text.
429+ * Replace all of a node's content with text.
430 *
431 * @type node: DOM node
432 *
433@@ -308,7 +304,20 @@
434 return '<function ' + o.name + '>';
435 }
436 } else if (o instanceof Array) {
437- return o.toSource();
438+ var names = Methanal.Util.map(Methanal.Util.repr, o);
439+ return '[' + names.join(', ') + ']';
440+ } else {
441+ if (o.constructor !== undefined && o.constructor.name !== undefined) {
442+ var typeName = o.constructor.name;
443+ if (typeName == 'Object') {
444+ var names = [];
445+ var repr = Methanal.Util.repr;
446+ for (var key in o) {
447+ names.push(repr(key) + ': ' + repr(o[key]));
448+ }
449+ return '{' + names.join(', ') + '}';
450+ }
451+ }
452 }
453 return o.toString();
454 };

Subscribers

People subscribed via source and target branches