1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 const { Trait } = require('sdk/deprecated/traits');
9 exports['test:simple compose'] = function(assert) {
10 let List = Trait.compose({
12 constructor: function List() {
15 list: function list() this._list.slice(0),
16 add: function add(item) this._list.push(item),
17 remove: function remove(item) {
18 let list = this._list;
19 let index = list.indexOf(item);
20 if (0 <= index) list.slice(index, 1);
24 assert.notEqual(undefined, List, 'should not be undefined');
25 assert.equal('function', typeof List, 'type should be function');
29 'should inherit static compose'
34 'should inherit static override'
39 'should inherit static required'
44 'should inherit static resolve'
48 !('_list' in List.prototype),
49 'should not expose private API'
52 exports['test: compose trait instance and create instance'] = function(assert) {
53 let List = Trait.compose({
54 constructor: function List(options) {
56 this._public.publicMember = options.publicMember;
59 get privateMember() this._privateMember,
60 get list() this._list.slice(0),
61 add: function add(item) this._list.push(item),
62 remove: function remove(item) {
64 let index = list.indexOf(item)
65 if (0 <= index) list.slice(index, 1)
68 let list = List({ publicMember: true });
70 assert.equal('object', typeof list, 'should return an object')
74 'should be instance of a List'
80 'instance should not expose private API'
86 'privates are accessible by public API'
89 list._privateMember = false;
94 'property changes on instance must not affect privates'
99 'instance should not expose private members'
105 'public members are exposed'
122 'exposed public API should be able of modifying privates'
127 exports['test:instances must not be hackable'] = function(assert) {
128 let SECRET = 'There is no secret!',
131 let Class = Trait.compose({
133 protect: function(data) this._secret = data
141 (function() this._secret).call(i1),
142 'call / apply can\'t access private state'
145 let proto = Object.getPrototypeOf(i1);
147 proto.reveal = function() this._secret;
148 secret = i1.reveal();
153 'public __proto__ changes should not affect privates'
157 let Class2 = Trait.compose({
159 protect: function(data) this._secret = data
164 Object.prototype.reveal = function() this._secret;
165 secret = i2.reveal();
170 'Object.prototype changes must not affect instances'
174 exports['test:instanceof'] = function(assert) {
175 const List = Trait.compose({
179 constructor: function List() {
182 get length() this._list.length,
183 add: function add(item) this._list.push(item),
184 remove: function remove(item) {
185 let list = this._list;
186 let index = list.indexOf(item);
187 if (0 <= index) list.slice(index, 1);
191 assert.ok(List() instanceof List, 'Must be instance of List');
192 assert.ok(new List() instanceof List, 'Must be instance of List');
195 exports['test:privates are unaccessible'] = function(assert) {
196 const List = Trait.compose({
200 constructor: function List() {
203 get length() this._list.length,
204 add: function add(item) this._list.push(item),
205 remove: function remove(item) {
206 let list = this._list;
207 let index = list.indexOf(item);
208 if (0 <= index) list.slice(index, 1);
213 assert.ok(!('_list' in list), 'no privates on instance');
215 !('_list' in List.prototype),
216 'no privates on prototype'
220 exports['test:public API can access private API'] = function(assert) {
221 const List = Trait.compose({
225 constructor: function List() {
228 get length() this._list.length,
229 add: function add(item) this._list.push(item),
230 remove: function remove(item) {
231 let list = this._list;
232 let index = list.indexOf(item);
233 if (0 <= index) list.slice(index, 1);
243 'should be able to add element and access it from public getter'
247 exports['test:required'] = function(assert) {
248 const Enumerable = Trait.compose({
249 list: Trait.required,
250 forEach: function forEach(consumer) {
251 return this.list.forEach(consumer);
256 let i = Enumerable();
257 assert.fail('should throw when creating instance with required properties');
260 'Error: Missing required property: list',
262 'required prop error'
267 exports['test:compose with required'] = function(assert) {
268 const List = Trait.compose({
272 constructor: function List() {
275 get length() this._list.length,
276 add: function add(item) this._list.push(item),
277 remove: function remove(item) {
278 let list = this._list;
279 let index = list.indexOf(item);
280 if (0 <= index) list.slice(index, 1);
284 const Enumerable = Trait.compose({
285 list: Trait.required,
286 forEach: function forEach(consumer) {
287 return this.list.forEach(consumer);
291 const EnumerableList = Enumerable.compose({
292 get list() this._list.slice(0)
295 let array = [1,2, 'ab']
296 let l = EnumerableList(array);
297 array.forEach(function(element) l.add(element));
299 l.forEach(function(element, index) {
301 assert.equal(array[index], element, 'should mach array element')
306 'should perform as many asserts as elements in array'
310 exports['test:resolve'] = function(assert) {
311 const List = Trait.compose({
315 constructor: function List() {
318 get length() this._list.length,
319 add: function add(item) this._list.push(item),
320 remove: function remove(item) {
321 let list = this._list;
322 let index = list.indexOf(item);
323 if (0 <= index) list.slice(index, 1);
327 const Range = List.resolve({
333 get list() this._list.slice(0),
334 constructor: function Range(min, max) {
339 add: function(item) {
340 if (item <= this.max && item >= this.min)
345 let r = Range(0, 10);
350 'constructor must have set min'
355 'constructor must have set max'
361 'should not contain any elements'
369 'should add `5` to list'
377 'should not add `12` to list'
381 exports['test:custom iterator'] = function(assert) {
382 let Sub = Trait.compose({
386 __iterator__: function() {
393 let (i = 0, sub = Sub()) {
394 for (let item in sub)
395 assert.equal(++i, item, "iterated item has the right value");
399 require('sdk/test').run(exports);