UNPKG

34.8 kBJavaScriptView Raw
1var 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; } // skip these tests on IE <= 10
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 // WebKit nightly had this bug, fixed in https://bugs.webkit.org/show_bug.cgi?id=143659
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 // WebKit nightly had this bug, fixed in https://bugs.webkit.org/show_bug.cgi?id=143659
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 // WebKit nightly had this bug, fixed in https://bugs.webkit.org/show_bug.cgi?id=143659
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 // eslint-disable-next-line no-template-curly-in-string
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 // eslint-disable-next-line no-template-curly-in-string
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&quot;baz&quot;">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&quot;red&quot;green">foo</font>');
898 });
899 it('has #fontsize', function () {
900 expect('foo'.fontsize('10"large"small')).to.equal('<font size="10&quot;large&quot;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&quot;http://&quot;">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
923describe('clean Object.prototype', function () {
924 return runStringTests.call(this, it);
925});
926
927describe('polluted Object.prototype', function () {
928 var shimmedIt = function () {
929 /* eslint-disable no-extend-native */
930 Object.prototype[1] = 42;
931 /* eslint-enable no-extend-native */
932 it.apply(this, arguments);
933 delete Object.prototype[1];
934 };
935 shimmedIt.skip = it.skip;
936 return runStringTests.call(this, shimmedIt);
937});