1 | var runStringTests = function (it) {
|
2 | 'use strict';
|
3 |
|
4 | var functionsHaveNames = (function foo() {}).name === 'foo';
|
5 | var ifFunctionsHaveNamesIt = functionsHaveNames ? it : it.skip;
|
6 | var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
|
7 | var hasSymbols = typeof Symbol === 'function' && typeof Symbol['for'] === 'function' && typeof Symbol.iterator === 'symbol';
|
8 | var ifSymbolsDescribe = hasSymbols ? describe : describe.skip;
|
9 |
|
10 | describe('String', function () {
|
11 | var hasStrictMode = (function () { return this === null; }.call(null));
|
12 | var testObjectCoercible = function (methodName) {
|
13 | var fn = String.prototype[methodName];
|
14 | if (!hasStrictMode) { return; }
|
15 | expect(function () { return fn.call(undefined); }).to['throw'](TypeError);
|
16 | expect(function () { return fn.call(null); }).to['throw'](TypeError);
|
17 | expect(function () { return fn.apply(undefined); }).to['throw'](TypeError);
|
18 | expect(function () { return fn.apply(null); }).to['throw'](TypeError);
|
19 | };
|
20 |
|
21 | ifShimIt('is on the exported object', function () {
|
22 | var exported = require('../');
|
23 | expect(exported.String).to.equal(String);
|
24 | });
|
25 |
|
26 | describe('#repeat()', function () {
|
27 | if (!Object.prototype.hasOwnProperty.call(String.prototype, 'repeat')) {
|
28 | return it('exists', function () {
|
29 | expect(String.prototype).to.have.property('repeat');
|
30 | });
|
31 | }
|
32 |
|
33 | ifFunctionsHaveNamesIt('has the right name', function () {
|
34 | expect(String.prototype.repeat).to.have.property('name', 'repeat');
|
35 | });
|
36 |
|
37 | it('is not enumerable', function () {
|
38 | expect(String.prototype).ownPropertyDescriptor('repeat').to.have.property('enumerable', false);
|
39 | });
|
40 |
|
41 | it('has the right arity', function () {
|
42 | expect(String.prototype.repeat).to.have.property('length', 1);
|
43 | });
|
44 |
|
45 | it('should throw a TypeError when called on null or undefined', function () {
|
46 | testObjectCoercible('repeat');
|
47 | });
|
48 |
|
49 | it('should throw a RangeError when negative or infinite', function () {
|
50 | expect(function negativeOne() { return 'test'.repeat(-1); }).to['throw'](RangeError);
|
51 | expect(function infinite() { return 'test'.repeat(Infinity); }).to['throw'](RangeError);
|
52 | });
|
53 |
|
54 | it('should coerce to an integer', function () {
|
55 | expect('test'.repeat(null)).to.eql('');
|
56 | expect('test'.repeat(false)).to.eql('');
|
57 | expect('test'.repeat('')).to.eql('');
|
58 | expect('test'.repeat(NaN)).to.eql('');
|
59 | expect('test'.repeat({})).to.eql('');
|
60 | expect('test'.repeat([])).to.eql('');
|
61 | expect('test'.repeat({
|
62 | valueOf: function () { return 2; }
|
63 | })).to.eql('testtest');
|
64 | });
|
65 | it('should work', function () {
|
66 | expect('test'.repeat(3)).to.eql('testtesttest');
|
67 | });
|
68 | it('should work on integers', function () {
|
69 | expect(String.prototype.repeat.call(2, 3)).to.eql('222');
|
70 | });
|
71 | it('should work on booleans', function () {
|
72 | expect(String.prototype.repeat.call(true, 3)).to.eql('truetruetrue');
|
73 | });
|
74 | it('should work on dates', function () {
|
75 | var d = new Date();
|
76 | expect(String.prototype.repeat.call(d, 3)).to.eql([d, d, d].join(''));
|
77 | });
|
78 | });
|
79 |
|
80 | describe('#startsWith()', function () {
|
81 | if (!Object.prototype.hasOwnProperty.call(String.prototype, 'startsWith')) {
|
82 | return it('exists', function () {
|
83 | expect(String.prototype).to.have.property('startsWith');
|
84 | });
|
85 | }
|
86 |
|
87 | ifFunctionsHaveNamesIt('has the right name', function () {
|
88 | expect(String.prototype.startsWith).to.have.property('name', 'startsWith');
|
89 | });
|
90 |
|
91 | it('is not enumerable', function () {
|
92 | expect(String.prototype).ownPropertyDescriptor('startsWith').to.have.property('enumerable', false);
|
93 | });
|
94 |
|
95 | it('has the right arity', function () {
|
96 |
|
97 | expect(String.prototype.startsWith).to.have.property('length', 1);
|
98 | });
|
99 |
|
100 | it('should throw a TypeError when called on null or undefined', function () {
|
101 | testObjectCoercible('startsWith');
|
102 | });
|
103 |
|
104 | it('should throw a TypeError when called on null or undefined', function () {
|
105 | testObjectCoercible('startsWith');
|
106 | });
|
107 |
|
108 | it('should be truthy on correct results', function () {
|
109 | expect('test'.startsWith('te')).to.equal(true);
|
110 | expect('test'.startsWith('st')).to.equal(false);
|
111 | expect(''.startsWith('/')).to.equal(false);
|
112 | expect('#'.startsWith('/')).to.equal(false);
|
113 | expect('##'.startsWith('///')).to.equal(false);
|
114 |
|
115 | expect('abc'.startsWith('abc')).to.equal(true);
|
116 | expect('abcd'.startsWith('abc')).to.equal(true);
|
117 | expect('abc'.startsWith('a')).to.equal(true);
|
118 | expect('abc'.startsWith('abcd')).to.equal(false);
|
119 | expect('abc'.startsWith('bcde')).to.equal(false);
|
120 | expect('abc'.startsWith('b')).to.equal(false);
|
121 | expect('abc'.startsWith('abc', 0)).to.equal(true);
|
122 | expect('abc'.startsWith('bc', 0)).to.equal(false);
|
123 | expect('abc'.startsWith('bc', 1)).to.equal(true);
|
124 | expect('abc'.startsWith('c', 1)).to.equal(false);
|
125 | expect('abc'.startsWith('abc', 1)).to.equal(false);
|
126 | expect('abc'.startsWith('c', 2)).to.equal(true);
|
127 | expect('abc'.startsWith('d', 2)).to.equal(false);
|
128 | expect('abc'.startsWith('dcd', 2)).to.equal(false);
|
129 | expect('abc'.startsWith('a', NaN)).to.equal(true);
|
130 | expect('abc'.startsWith('b', NaN)).to.equal(false);
|
131 | expect('abc'.startsWith('ab', -43)).to.equal(true);
|
132 | expect('abc'.startsWith('ab', -Infinity)).to.equal(true);
|
133 | expect('abc'.startsWith('bc', -42)).to.equal(false);
|
134 | expect('abc'.startsWith('bc', -Infinity)).to.equal(false);
|
135 | if (hasStrictMode) {
|
136 | expect(function () {
|
137 | return ''.startsWith.call(null, 'nu');
|
138 | }).to['throw'](TypeError);
|
139 | expect(function () {
|
140 | return ''.startsWith.call(undefined, 'un');
|
141 | }).to['throw'](TypeError);
|
142 | }
|
143 | var myobj = {
|
144 | toString: function () { return 'abc'; },
|
145 | startsWith: String.prototype.startsWith
|
146 | };
|
147 | expect(myobj.startsWith('abc')).to.equal(true);
|
148 | expect(myobj.startsWith('bc')).to.equal(false);
|
149 |
|
150 | var gotStr = false;
|
151 | var gotPos = false;
|
152 |
|
153 | myobj = {
|
154 | toString: function () {
|
155 | expect(gotPos).to.equal(false);
|
156 | gotStr = true;
|
157 | return 'xyz';
|
158 | },
|
159 | startsWith: String.prototype.startsWith
|
160 | };
|
161 | var idx = {
|
162 | valueOf: function () {
|
163 | expect(gotStr).to.equal(true);
|
164 | gotPos = true;
|
165 | return 42;
|
166 | }
|
167 | };
|
168 | myobj.startsWith('elephant', idx);
|
169 | expect(gotPos).to.equal(true);
|
170 | });
|
171 |
|
172 | it('should handle large positions', function () {
|
173 | expect('abc'.startsWith('a', 42)).to.equal(false);
|
174 | expect('abc'.startsWith('a', Infinity)).to.equal(false);
|
175 | });
|
176 |
|
177 | it('should coerce to a string', function () {
|
178 | expect('abcd'.startsWith({ toString: function () { return 'ab'; } })).to.equal(true);
|
179 | expect('abcd'.startsWith({ toString: function () { return 'foo'; } })).to.equal(false);
|
180 | });
|
181 |
|
182 | it('should not allow a regex', function () {
|
183 | expect(function () { return 'abcd'.startsWith(/abc/); }).to['throw'](TypeError);
|
184 | expect(function () { return 'abcd'.startsWith(new RegExp('abc')); }).to['throw'](TypeError);
|
185 | });
|
186 |
|
187 | ifSymbolsDescribe('Symbol.match', function () {
|
188 | if (!hasSymbols || !Symbol.match) {
|
189 | return it('exists', function () {
|
190 | expect(Symbol).to.have.property('match');
|
191 | });
|
192 | }
|
193 |
|
194 | it('allows a regex with Symbol.match set to a falsy value', function () {
|
195 | var re = /a/g;
|
196 | re[Symbol.match] = false;
|
197 | expect(function () { return 'abcd'.startsWith(re); }).not.to['throw']();
|
198 | expect('abcd'.startsWith(re)).to.equal('abcd'.startsWith(String(re)));
|
199 | });
|
200 | });
|
201 | });
|
202 |
|
203 | describe('#endsWith()', function () {
|
204 | if (!Object.prototype.hasOwnProperty.call(String.prototype, 'endsWith')) {
|
205 | return it('exists', function () {
|
206 | expect(String.prototype).to.have.property('endsWith');
|
207 | });
|
208 | }
|
209 |
|
210 | ifFunctionsHaveNamesIt('has the right name', function () {
|
211 | expect(String.prototype.endsWith).to.have.property('name', 'endsWith');
|
212 | });
|
213 |
|
214 | it('is not enumerable', function () {
|
215 | expect(String.prototype).ownPropertyDescriptor('endsWith').to.have.property('enumerable', false);
|
216 | });
|
217 |
|
218 | it('has the right arity', function () {
|
219 |
|
220 | expect(String.prototype.endsWith).to.have.property('length', 1);
|
221 | });
|
222 |
|
223 | it('should throw a TypeError when called on null or undefined', function () {
|
224 | testObjectCoercible('endsWith');
|
225 | });
|
226 |
|
227 | it('should be truthy on correct results', function () {
|
228 | expect('test'.endsWith('st')).to.equal(true);
|
229 | expect('test'.endsWith('te')).to.equal(false);
|
230 | expect(''.endsWith('/')).to.equal(false);
|
231 | expect('#'.endsWith('/')).to.equal(false);
|
232 | expect('##'.endsWith('///')).to.equal(false);
|
233 |
|
234 | expect('abc'.endsWith('abc')).to.equal(true);
|
235 | expect('abcd'.endsWith('bcd')).to.equal(true);
|
236 | expect('abc'.endsWith('c')).to.equal(true);
|
237 | expect('abc'.endsWith('abcd')).to.equal(false);
|
238 | expect('abc'.endsWith('bbc')).to.equal(false);
|
239 | expect('abc'.endsWith('b')).to.equal(false);
|
240 | expect('abc'.endsWith('abc', 3)).to.equal(true);
|
241 | expect('abc'.endsWith('bc', 3)).to.equal(true);
|
242 | expect('abc'.endsWith('a', 3)).to.equal(false);
|
243 | expect('abc'.endsWith('bc', 3)).to.equal(true);
|
244 | expect('abc'.endsWith('a', 1)).to.equal(true);
|
245 | expect('abc'.endsWith('abc', 1)).to.equal(false);
|
246 | expect('abc'.endsWith('b', 2)).to.equal(true);
|
247 | expect('abc'.endsWith('d', 2)).to.equal(false);
|
248 | expect('abc'.endsWith('dcd', 2)).to.equal(false);
|
249 | expect('abc'.endsWith('bc', undefined)).to.equal(true);
|
250 | expect('abc'.endsWith('bc', NaN)).to.equal(false);
|
251 | if (hasStrictMode) {
|
252 | expect(function () {
|
253 | return ''.endsWith.call(null, 'ull');
|
254 | }).to['throw'](TypeError);
|
255 | expect(function () {
|
256 | return ''.endsWith.call(undefined, 'ned');
|
257 | }).to['throw'](TypeError);
|
258 | }
|
259 |
|
260 | var myobj = {
|
261 | toString: function () { return 'abc'; },
|
262 | endsWith: String.prototype.endsWith
|
263 | };
|
264 | expect(myobj.endsWith('abc')).to.equal(true);
|
265 | expect(myobj.endsWith('ab')).to.equal(false);
|
266 | var gotStr = false;
|
267 | var gotPos = false;
|
268 |
|
269 | myobj = {
|
270 | toString: function () {
|
271 | expect(gotPos).to.equal(false);
|
272 | gotStr = true;
|
273 | return 'xyz';
|
274 | },
|
275 | endsWith: String.prototype.endsWith
|
276 | };
|
277 | var idx = {
|
278 | valueOf: function () {
|
279 | expect(gotStr).to.equal(true);
|
280 | gotPos = true;
|
281 | return 42;
|
282 | }
|
283 | };
|
284 | myobj.endsWith('elephant', idx);
|
285 | expect(gotPos).to.equal(true);
|
286 | });
|
287 |
|
288 | it('should coerce to a string', function () {
|
289 | expect('abcd'.endsWith({ toString: function () { return 'cd'; } })).to.equal(true);
|
290 | expect('abcd'.endsWith({ toString: function () { return 'foo'; } })).to.equal(false);
|
291 | });
|
292 |
|
293 | it('should not allow a regex', function () {
|
294 | expect(function () { return 'abcd'.endsWith(/abc/); }).to['throw'](TypeError);
|
295 | expect(function () { return 'abcd'.endsWith(new RegExp('abc')); }).to['throw'](TypeError);
|
296 | });
|
297 |
|
298 | it('should handle negative and zero endPositions properly', function () {
|
299 | expect('abcd'.endsWith('bcd', 0)).to.equal(false);
|
300 | expect('abcd'.endsWith('bcd', -2)).to.equal(false);
|
301 | expect('abcd'.endsWith('b', -2)).to.equal(false);
|
302 | expect('abcd'.endsWith('ab', -2)).to.equal(false);
|
303 | expect('abc'.endsWith('bc', -43)).to.equal(false);
|
304 | expect('abc'.endsWith('bc', -Infinity)).to.equal(false);
|
305 | });
|
306 |
|
307 | it('should handle large endPositions properly', function () {
|
308 | expect('abc'.endsWith('a', 42)).to.equal(false);
|
309 | expect('abc'.endsWith('bc', Infinity)).to.equal(true);
|
310 | expect('abc'.endsWith('a', Infinity)).to.equal(false);
|
311 | });
|
312 |
|
313 | ifSymbolsDescribe('Symbol.match', function () {
|
314 | if (!hasSymbols || !Symbol.match) {
|
315 | return it('exists', function () {
|
316 | expect(Symbol).to.have.property('match');
|
317 | });
|
318 | }
|
319 |
|
320 | it('allows a regex with Symbol.match set to a falsy value', function () {
|
321 | var re = /a/g;
|
322 | re[Symbol.match] = false;
|
323 | expect(function () { return 'abcd'.startsWith(re); }).not.to['throw']();
|
324 | expect('abcd'.endsWith(re)).to.equal('abcd'.endsWith(String(re)));
|
325 | });
|
326 | });
|
327 | });
|
328 |
|
329 | describe('#includes()', function () {
|
330 | if (!Object.prototype.hasOwnProperty.call(String.prototype, 'includes')) {
|
331 | return it('exists', function () {
|
332 | expect(String.prototype).to.have.property('includes');
|
333 | });
|
334 | }
|
335 |
|
336 | ifFunctionsHaveNamesIt('has the right name', function () {
|
337 | expect(String.prototype.includes).to.have.property('name', 'includes');
|
338 | });
|
339 |
|
340 | it('is not enumerable', function () {
|
341 | expect(String.prototype).ownPropertyDescriptor('includes').to.have.property('enumerable', false);
|
342 | });
|
343 |
|
344 | it('has the right arity', function () {
|
345 |
|
346 | expect(String.prototype.includes).to.have.property('length', 1);
|
347 | });
|
348 |
|
349 | it('should throw a TypeError when called on null or undefined', function () {
|
350 | testObjectCoercible('includes');
|
351 | });
|
352 |
|
353 | it('throws a TypeError when given a regex', function () {
|
354 | expect(function () { 'foo'.includes(/a/g); }).to['throw'](TypeError);
|
355 | });
|
356 |
|
357 | it('should be truthy on correct results', function () {
|
358 | expect('test'.includes('es')).to.equal(true);
|
359 | expect('abc'.includes('a')).to.equal(true);
|
360 | expect('abc'.includes('b')).to.equal(true);
|
361 | expect('abc'.includes('abc')).to.equal(true);
|
362 | expect('abc'.includes('bc')).to.equal(true);
|
363 | expect('abc'.includes('d')).to.equal(false);
|
364 | expect('abc'.includes('abcd')).to.equal(false);
|
365 | expect('abc'.includes('ac')).to.equal(false);
|
366 | expect('abc'.includes('abc', 0)).to.equal(true);
|
367 | expect('abc'.includes('bc', 0)).to.equal(true);
|
368 | expect('abc'.includes('de', 0)).to.equal(false);
|
369 | expect('abc'.includes('bc', 1)).to.equal(true);
|
370 | expect('abc'.includes('c', 1)).to.equal(true);
|
371 | expect('abc'.includes('a', 1)).to.equal(false);
|
372 | expect('abc'.includes('abc', 1)).to.equal(false);
|
373 | expect('abc'.includes('c', 2)).to.equal(true);
|
374 | expect('abc'.includes('d', 2)).to.equal(false);
|
375 | expect('abc'.includes('dcd', 2)).to.equal(false);
|
376 | expect('abc'.includes('ab', NaN)).to.equal(true);
|
377 | expect('abc'.includes('cd', NaN)).to.equal(false);
|
378 |
|
379 | var myobj = {
|
380 | toString: function () { return 'abc'; },
|
381 | includes: String.prototype.includes
|
382 | };
|
383 |
|
384 | expect(myobj.includes('abc')).to.equal(true);
|
385 | expect(myobj.includes('cd')).to.equal(false);
|
386 |
|
387 | var gotStr = false;
|
388 | var gotPos = false;
|
389 |
|
390 | myobj = {
|
391 | toString: function () {
|
392 | expect(gotPos).to.equal(false);
|
393 | gotStr = true;
|
394 | return 'xyz';
|
395 | },
|
396 |
|
397 | includes: String.prototype.includes
|
398 | };
|
399 |
|
400 | var idx = {
|
401 | valueOf: function () {
|
402 | expect(gotStr).to.equal(true);
|
403 | gotPos = true;
|
404 | return 42;
|
405 | }
|
406 | };
|
407 |
|
408 | myobj.includes('elephant', idx);
|
409 | expect(gotPos).to.equal(true);
|
410 | });
|
411 |
|
412 | it('should handle large positions', function () {
|
413 | expect('abc'.includes('a', 42)).to.equal(false);
|
414 | expect('abc'.includes('a', Infinity)).to.equal(false);
|
415 | });
|
416 |
|
417 | it('should handle negative positions', function () {
|
418 | expect('abc'.includes('ab', -43)).to.equal(true);
|
419 | expect('abc'.includes('cd', -42)).to.equal(false);
|
420 | expect('abc'.includes('ab', -Infinity)).to.equal(true);
|
421 | expect('abc'.includes('cd', -Infinity)).to.equal(false);
|
422 | });
|
423 |
|
424 | it('should be falsy on incorrect results', function () {
|
425 | expect('test'.includes('1290')).to.equal(false);
|
426 | });
|
427 |
|
428 | ifSymbolsDescribe('Symbol.match', function () {
|
429 | if (!hasSymbols || !Symbol.match) {
|
430 | return it('exists', function () {
|
431 | expect(Symbol).to.have.property('match');
|
432 | });
|
433 | }
|
434 |
|
435 | it('allows a regex with Symbol.match set to a falsy value', function () {
|
436 | var re = /a/g;
|
437 | re[Symbol.match] = false;
|
438 | expect(function () { return 'abcd'.includes(re); }).not.to['throw']();
|
439 | expect('abcd'.includes(re)).to.equal('abcd'.includes(String(re)));
|
440 | });
|
441 | });
|
442 | });
|
443 |
|
444 | describe('.fromCodePoint()', function () {
|
445 | if (!Object.prototype.hasOwnProperty.call(String, 'fromCodePoint')) {
|
446 | return it('exists', function () {
|
447 | expect(String).to.have.property('fromCodePoint');
|
448 | });
|
449 | }
|
450 |
|
451 | ifFunctionsHaveNamesIt('has the right name', function () {
|
452 | expect(String.fromCodePoint).to.have.property('name', 'fromCodePoint');
|
453 | });
|
454 |
|
455 | it('is not enumerable', function () {
|
456 | expect(String).ownPropertyDescriptor('fromCodePoint').to.have.property('enumerable', false);
|
457 | });
|
458 |
|
459 | it('has the right arity', function () {
|
460 | expect(String.fromCodePoint).to.have.property('length', 1);
|
461 | });
|
462 |
|
463 | it('throws a RangeError', function () {
|
464 | var invalidValues = [
|
465 | 'abc',
|
466 | {},
|
467 | -1,
|
468 | 0x10FFFF + 1
|
469 | ];
|
470 | invalidValues.forEach(function (value) {
|
471 | expect(function () { return String.fromCodePoint(value); }).to['throw'](RangeError);
|
472 | });
|
473 | });
|
474 |
|
475 | it('returns the empty string with no args', function () {
|
476 | expect(String.fromCodePoint()).to.equal('');
|
477 | });
|
478 |
|
479 | it('works', function () {
|
480 | var codePoints = [];
|
481 | var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789…?!';
|
482 | for (var i = 0; i < chars.length; ++i) {
|
483 | codePoints.push(chars.charCodeAt(i));
|
484 | expect(String.fromCodePoint(chars.charCodeAt(i))).to.equal(chars[i]);
|
485 | }
|
486 | expect(String.fromCodePoint.apply(String, codePoints)).to.equal(chars);
|
487 | });
|
488 |
|
489 | it('works with unicode', function () {
|
490 | expect(String.fromCodePoint(0x2500)).to.equal('\u2500');
|
491 | expect(String.fromCodePoint(0x010000)).to.equal('\ud800\udc00');
|
492 | expect(String.fromCodePoint(0x10FFFF)).to.equal('\udbff\udfff');
|
493 | });
|
494 | });
|
495 |
|
496 | describe('#codePointAt()', function () {
|
497 | if (!Object.prototype.hasOwnProperty.call(String.prototype, 'codePointAt')) {
|
498 | return it('exists', function () {
|
499 | expect(String.prototype).to.have.property('codePointAt');
|
500 | });
|
501 | }
|
502 |
|
503 | ifFunctionsHaveNamesIt('has the right name', function () {
|
504 | expect(String.prototype.codePointAt).to.have.property('name', 'codePointAt');
|
505 | });
|
506 |
|
507 | it('is not enumerable', function () {
|
508 | expect(String.prototype).ownPropertyDescriptor('codePointAt').to.have.property('enumerable', false);
|
509 | });
|
510 |
|
511 | it('has the right arity', function () {
|
512 | expect(String.prototype.codePointAt).to.have.property('length', 1);
|
513 | });
|
514 |
|
515 | it('should throw a TypeError when called on null or undefined', function () {
|
516 | testObjectCoercible('codePointAt');
|
517 | });
|
518 |
|
519 | it('should work', function () {
|
520 | var str = 'abc';
|
521 | expect(str.codePointAt(0)).to.equal(97);
|
522 | expect(str.codePointAt(1)).to.equal(98);
|
523 | expect(str.codePointAt(2)).to.equal(99);
|
524 | });
|
525 |
|
526 | it('should work with unicode', function () {
|
527 | expect('\u2500'.codePointAt(0)).to.equal(0x2500);
|
528 | expect('\ud800\udc00'.codePointAt(0)).to.equal(0x10000);
|
529 | expect('\udbff\udfff'.codePointAt(0)).to.equal(0x10ffff);
|
530 | expect('\ud800\udc00\udbff\udfff'.codePointAt(0)).to.equal(0x10000);
|
531 | expect('\ud800\udc00\udbff\udfff'.codePointAt(1)).to.equal(0xdc00);
|
532 | expect('\ud800\udc00\udbff\udfff'.codePointAt(2)).to.equal(0x10ffff);
|
533 | expect('\ud800\udc00\udbff\udfff'.codePointAt(3)).to.equal(0xdfff);
|
534 | });
|
535 |
|
536 | it('should return undefined when pos is negative or too large', function () {
|
537 | var str = 'abc';
|
538 | expect(str.codePointAt(-1)).to.equal(undefined);
|
539 | expect(str.codePointAt(str.length)).to.equal(undefined);
|
540 | });
|
541 | });
|
542 |
|
543 | describe('#[Symbol.iterator]()', function () {
|
544 | if (!Object.prototype.hasOwnProperty.call(Array, 'from')) {
|
545 | return it('requires Array.from to test', function () {
|
546 | expect(Array).to.have.property('from');
|
547 | });
|
548 | }
|
549 |
|
550 | it('should work with plain strings', function () {
|
551 | var str = 'abc';
|
552 | expect(Array.from(str)).to.eql(['a', 'b', 'c']);
|
553 | });
|
554 |
|
555 | it('should work with surrogate characters', function () {
|
556 | var str = '\u2500\ud800\udc00\udbff\udfff\ud800';
|
557 | expect(Array.from(str)).to.eql(['\u2500', '\ud800\udc00', '\udbff\udfff', '\ud800']);
|
558 | });
|
559 | });
|
560 |
|
561 | describe('.raw()', function () {
|
562 | if (!Object.prototype.hasOwnProperty.call(String, 'raw')) {
|
563 | return it('exists', function () {
|
564 | expect(String).to.have.property('raw');
|
565 | });
|
566 | }
|
567 |
|
568 | ifFunctionsHaveNamesIt('has the right name', function () {
|
569 | expect(String.raw).to.have.property('name', 'raw');
|
570 | });
|
571 |
|
572 | it('is not enumerable', function () {
|
573 | expect(String).ownPropertyDescriptor('raw').to.have.property('enumerable', false);
|
574 | });
|
575 |
|
576 | it('has the right arity', function () {
|
577 | expect(String.raw).to.have.property('length', 1);
|
578 | });
|
579 |
|
580 | it('works with template.raw: Array', function () {
|
581 | var template = {};
|
582 |
|
583 | var str = 'The total is 10 ($11 with tax)';
|
584 | template.raw = ['The total is ', ' ($', ' with tax)'];
|
585 | expect(String.raw(template, 10, 11)).to.eql(str);
|
586 |
|
587 |
|
588 | str = 'The total is {total} (${total * 1.01} with tax)';
|
589 | template.raw = ['The total is ', ' ($', ' with tax)'];
|
590 | expect(String.raw(template, '{total}', '{total * 1.01}')).to.eql(str);
|
591 | });
|
592 |
|
593 | it('works with template.raw: array-like object', function () {
|
594 | var template = {};
|
595 |
|
596 | var str = 'The total is 10 ($11 with tax)';
|
597 | template.raw = { 0: 'The total is ', 1: ' ($', 2: ' with tax)', length: 3 };
|
598 | expect(String.raw(template, 10, 11)).to.eql(str);
|
599 |
|
600 |
|
601 | str = 'The total is {total} (${total * 1.01} with tax)';
|
602 | template.raw = { 0: 'The total is ', 1: ' ($', 2: ' with tax)', length: 3 };
|
603 | expect(String.raw(template, '{total}', '{total * 1.01}')).to.eql(str);
|
604 | });
|
605 |
|
606 | it('works with template.raw: empty Objects', function () {
|
607 | var template = { raw: {} };
|
608 | expect(String.raw(template, '{total}', '{total * 1.01}')).to.eql('');
|
609 | expect(String.raw(template)).to.equal('');
|
610 | });
|
611 |
|
612 | it('ReturnIfAbrupt - Less Substitutions', function () {
|
613 | var template = {
|
614 | raw: { 0: 'The total is ', 1: ' ($', 2: ' with tax)', length: 3 }
|
615 | };
|
616 | var str = 'The total is 10 ($ with tax)';
|
617 | expect(String.raw(template, 10)).to.equal(str);
|
618 | });
|
619 |
|
620 | ifSymbolsDescribe('Symbol substitutions', function () {
|
621 | it('throws', function () {
|
622 | var template = {
|
623 | raw: { 0: 'The total is ', 1: ' ($', 2: ' with tax)', length: 3 }
|
624 | };
|
625 | var str = 'The total is 10 ($ with tax)';
|
626 | expect(function () { String.raw(template, Symbol()); }).to['throw'](TypeError);
|
627 | });
|
628 | });
|
629 | });
|
630 |
|
631 | describe('#trim()', function () {
|
632 | if (!Object.prototype.hasOwnProperty.call(String.prototype, 'trim')) {
|
633 | return it('exists', function () {
|
634 | expect(String.prototype).to.have.property('trim');
|
635 | });
|
636 | }
|
637 |
|
638 | ifFunctionsHaveNamesIt('has the right name', function () {
|
639 | expect(String.prototype.trim).to.have.property('name', 'trim');
|
640 | });
|
641 |
|
642 | it('is not enumerable', function () {
|
643 | expect(String.prototype).ownPropertyDescriptor('trim').to.have.property('enumerable', false);
|
644 | });
|
645 |
|
646 | it('has the right arity', function () {
|
647 | expect(String.prototype.trim).to.have.property('length', 0);
|
648 | });
|
649 |
|
650 | it('should trim the correct characters', function () {
|
651 | var whitespace = [
|
652 | '\u0009',
|
653 | '\u000b',
|
654 | '\u000c',
|
655 | '\u0020',
|
656 | '\u00a0',
|
657 | '\u1680',
|
658 | '\u2000',
|
659 | '\u2001',
|
660 | '\u2002',
|
661 | '\u2003',
|
662 | '\u2004',
|
663 | '\u2005',
|
664 | '\u2006',
|
665 | '\u2007',
|
666 | '\u2008',
|
667 | '\u2009',
|
668 | '\u200A',
|
669 | '\u202f',
|
670 | '\u205f',
|
671 | '\u3000'
|
672 | ].join('');
|
673 |
|
674 | var lineTerminators = [
|
675 | '\u000a',
|
676 | '\u000d',
|
677 | '\u2028',
|
678 | '\u2029'
|
679 | ].join('');
|
680 |
|
681 | var trimmed = (whitespace + lineTerminators).trim();
|
682 | expect(trimmed).to.have.property('length', 0);
|
683 | expect(trimmed).to.equal('');
|
684 | });
|
685 |
|
686 | it('should not trim U+0085', function () {
|
687 | var trimmed = '\u0085'.trim();
|
688 | expect(trimmed).to.have.property('length', 1);
|
689 | expect(trimmed).to.equal('\u0085');
|
690 | });
|
691 |
|
692 | it('should trim on both sides', function () {
|
693 | var trimmed = ' a '.trim();
|
694 | expect(trimmed).to.have.property('length', 1);
|
695 | expect(trimmed).to.equal('a');
|
696 | });
|
697 | });
|
698 |
|
699 | describe('#search()', function () {
|
700 | it('works with strings', function () {
|
701 | expect('abc'.search('a')).to.equal(0);
|
702 | expect('abc'.search('b')).to.equal(1);
|
703 | expect('abc'.search('c')).to.equal(2);
|
704 | expect('abc'.search('d')).to.equal(-1);
|
705 | });
|
706 |
|
707 | it('works with regexes', function () {
|
708 | expect('abc'.search(/a/)).to.equal(0);
|
709 | expect('abc'.search(/b/)).to.equal(1);
|
710 | expect('abc'.search(/c/)).to.equal(2);
|
711 | expect('abc'.search(/d/)).to.equal(-1);
|
712 | });
|
713 |
|
714 | ifSymbolsDescribe('Symbol.search', function () {
|
715 | it('is a symbol', function () {
|
716 | expect(typeof Symbol.search).to.equal('symbol');
|
717 | });
|
718 |
|
719 | if (!hasSymbols || typeof Symbol.search !== 'symbol') {
|
720 | return;
|
721 | }
|
722 |
|
723 | it('is nonconfigurable', function () {
|
724 | expect(Symbol).ownPropertyDescriptor('search').to.have.property('configurable', false);
|
725 | });
|
726 |
|
727 | it('is nonenumerable', function () {
|
728 | expect(Symbol).ownPropertyDescriptor('search').to.have.property('enumerable', false);
|
729 | });
|
730 |
|
731 | it('is nonwritable', function () {
|
732 | expect(Symbol).ownPropertyDescriptor('search').to.have.property('writable', false);
|
733 | });
|
734 |
|
735 | it('is respected', function () {
|
736 | var str = Object('a');
|
737 | var obj = {};
|
738 | obj[Symbol.search] = function (string) { return string === str && this === obj; };
|
739 | expect(str.search(obj)).to.equal(true);
|
740 | });
|
741 | });
|
742 | });
|
743 |
|
744 | describe('#replace()', function () {
|
745 | it('works', function () {
|
746 | expect('abcabc'.replace('c', 'd')).to.equal('abdabc');
|
747 | expect('abcabc'.replace(/c/, 'd')).to.equal('abdabc');
|
748 | expect('abcabc'.replace(/c/g, 'd')).to.equal('abdabd');
|
749 | expect('abcabc'.replace(/C/ig, 'd')).to.equal('abdabd');
|
750 | });
|
751 |
|
752 | ifSymbolsDescribe('Symbol.replace', function () {
|
753 | it('is a symbol', function () {
|
754 | expect(typeof Symbol.replace).to.equal('symbol');
|
755 | });
|
756 |
|
757 | if (!hasSymbols || typeof Symbol.replace !== 'symbol') {
|
758 | return;
|
759 | }
|
760 |
|
761 | it('is nonconfigurable', function () {
|
762 | expect(Symbol).ownPropertyDescriptor('replace').to.have.property('configurable', false);
|
763 | });
|
764 |
|
765 | it('is nonenumerable', function () {
|
766 | expect(Symbol).ownPropertyDescriptor('replace').to.have.property('enumerable', false);
|
767 | });
|
768 |
|
769 | it('is nonwritable', function () {
|
770 | expect(Symbol).ownPropertyDescriptor('replace').to.have.property('writable', false);
|
771 | });
|
772 |
|
773 | it('respects Symbol.replace', function () {
|
774 | var str = Object('a');
|
775 | var replaceVal = Object('replaceValue');
|
776 | var obj = {};
|
777 | obj[Symbol.replace] = function (string, replaceValue) {
|
778 | return string === str && replaceValue === replaceVal && this === obj;
|
779 | };
|
780 | expect(str.replace(obj, replaceVal)).to.equal(true);
|
781 | });
|
782 | });
|
783 | });
|
784 |
|
785 | describe('#split()', function () {
|
786 | it('works', function () {
|
787 | expect('abcabc'.split('b')).to.eql(['a', 'ca', 'c']);
|
788 | expect('abcabc'.split('b', 2)).to.eql(['a', 'ca']);
|
789 | expect('abcabc'.split(/b.?/)).to.eql(['a', 'a', '']);
|
790 | expect('abcabc'.split(/b.?/, 2)).to.eql(['a', 'a']);
|
791 | expect('abcabc'.split(/b/)).to.eql(['a', 'ca', 'c']);
|
792 | expect('abcabc'.split(/b/, 2)).to.eql(['a', 'ca']);
|
793 | expect('abcabc'.split(/b/g)).to.eql(['a', 'ca', 'c']);
|
794 | expect('abcabc'.split(/b/g, 2)).to.eql(['a', 'ca']);
|
795 | expect('abcabc'.split(/B/i)).to.eql(['a', 'ca', 'c']);
|
796 | expect('abcabc'.split(/B/i, 2)).to.eql(['a', 'ca']);
|
797 | expect('abcabc'.split(/B/gi)).to.eql(['a', 'ca', 'c']);
|
798 | expect('abcabc'.split(/B/gi, 2)).to.eql(['a', 'ca']);
|
799 | });
|
800 |
|
801 | ifSymbolsDescribe('Symbol.split', function () {
|
802 | it('is a symbol', function () {
|
803 | expect(typeof Symbol.split).to.equal('symbol');
|
804 | });
|
805 |
|
806 | if (!hasSymbols || typeof Symbol.split !== 'symbol') {
|
807 | return;
|
808 | }
|
809 |
|
810 | it('is nonconfigurable', function () {
|
811 | expect(Symbol).ownPropertyDescriptor('split').to.have.property('configurable', false);
|
812 | });
|
813 |
|
814 | it('is nonenumerable', function () {
|
815 | expect(Symbol).ownPropertyDescriptor('split').to.have.property('enumerable', false);
|
816 | });
|
817 |
|
818 | it('is nonwritable', function () {
|
819 | expect(Symbol).ownPropertyDescriptor('split').to.have.property('writable', false);
|
820 | });
|
821 |
|
822 | it('respects Symbol.split', function () {
|
823 | var str = Object('a');
|
824 | var limitVal = Object(42);
|
825 | var obj = {};
|
826 | obj[Symbol.split] = function (string, limit) { return string === str && limit === limitVal && this === obj; };
|
827 | expect(str.split(obj, limitVal)).to.equal(true);
|
828 | });
|
829 | });
|
830 | });
|
831 |
|
832 | describe('#match()', function () {
|
833 | it('works with a string', function () {
|
834 | var str = 'abca';
|
835 | var match = str.match('a');
|
836 | expect(match.index).to.equal(0);
|
837 | expect(match.input).to.equal(str);
|
838 | expect(Array.prototype.slice.call(match)).to.eql(['a']);
|
839 | });
|
840 |
|
841 | it('works with a regex', function () {
|
842 | var str = 'abca';
|
843 | var match = str.match(/a/);
|
844 | expect(match.index).to.equal(0);
|
845 | expect(match.input).to.equal(str);
|
846 | expect(Array.prototype.slice.call(match)).to.eql(['a']);
|
847 | });
|
848 |
|
849 | ifSymbolsDescribe('Symbol.match', function () {
|
850 | it('is a symbol', function () {
|
851 | expect(typeof Symbol.match).to.equal('symbol');
|
852 | });
|
853 |
|
854 | if (!hasSymbols || typeof Symbol.match !== 'symbol') {
|
855 | return;
|
856 | }
|
857 |
|
858 | it('is nonconfigurable', function () {
|
859 | expect(Symbol).ownPropertyDescriptor('match').to.have.property('configurable', false);
|
860 | });
|
861 |
|
862 | it('is nonenumerable', function () {
|
863 | expect(Symbol).ownPropertyDescriptor('match').to.have.property('enumerable', false);
|
864 | });
|
865 |
|
866 | it('is nonwritable', function () {
|
867 | expect(Symbol).ownPropertyDescriptor('match').to.have.property('writable', false);
|
868 | });
|
869 |
|
870 | it('respects Symbol.match', function () {
|
871 | var str = Object('a');
|
872 | var obj = {};
|
873 | obj[Symbol.match] = function (string) { return string === str && this === obj; };
|
874 | expect(str.match(obj)).to.equal(true);
|
875 | });
|
876 | });
|
877 | });
|
878 | });
|
879 |
|
880 | describe('Annex B', function () {
|
881 | it('has #anchor', function () {
|
882 | expect('foo'.anchor('bar"baz"')).to.equal('<a name="bar"baz"">foo</a>');
|
883 | });
|
884 | it('has #big', function () {
|
885 | expect('foo'.big()).to.equal('<big>foo</big>');
|
886 | });
|
887 | it('has #blink', function () {
|
888 | expect('foo'.blink()).to.equal('<blink>foo</blink>');
|
889 | });
|
890 | it('has #bold', function () {
|
891 | expect('foo'.bold()).to.equal('<b>foo</b>');
|
892 | });
|
893 | it('has #fixed', function () {
|
894 | expect('foo'.fixed()).to.equal('<tt>foo</tt>');
|
895 | });
|
896 | it('has #fontcolor', function () {
|
897 | expect('foo'.fontcolor('blue"red"green')).to.equal('<font color="blue"red"green">foo</font>');
|
898 | });
|
899 | it('has #fontsize', function () {
|
900 | expect('foo'.fontsize('10"large"small')).to.equal('<font size="10"large"small">foo</font>');
|
901 | });
|
902 | it('has #italics', function () {
|
903 | expect('foo'.italics()).to.equal('<i>foo</i>');
|
904 | });
|
905 | it('has #link', function () {
|
906 | expect('foo'.link('url"http://"')).to.equal('<a href="url"http://"">foo</a>');
|
907 | });
|
908 | it('has #small', function () {
|
909 | expect('foo'.small()).to.equal('<small>foo</small>');
|
910 | });
|
911 | it('has #strike', function () {
|
912 | expect('foo'.strike()).to.equal('<strike>foo</strike>');
|
913 | });
|
914 | it('has #sub', function () {
|
915 | expect('foo'.sub()).to.equal('<sub>foo</sub>');
|
916 | });
|
917 | it('has #sup', function () {
|
918 | expect('foo'.sup()).to.equal('<sup>foo</sup>');
|
919 | });
|
920 | });
|
921 | };
|
922 |
|
923 | describe('clean Object.prototype', function () {
|
924 | return runStringTests.call(this, it);
|
925 | });
|
926 |
|
927 | describe('polluted Object.prototype', function () {
|
928 | var shimmedIt = function () {
|
929 |
|
930 | Object.prototype[1] = 42;
|
931 |
|
932 | it.apply(this, arguments);
|
933 | delete Object.prototype[1];
|
934 | };
|
935 | shimmedIt.skip = it.skip;
|
936 | return runStringTests.call(this, shimmedIt);
|
937 | });
|