index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. var test = require('tape');
  3. var isSymbol = require('../index');
  4. var forEach = function (arr, func) {
  5. var i;
  6. for (i = 0; i < arr.length; ++i) {
  7. func(arr[i], i, arr);
  8. }
  9. };
  10. var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol';
  11. var debug = function (value, msg) {
  12. var output = '';
  13. if (hasSymbols) {
  14. try { output += String(value); }
  15. catch (e) { output += Symbol.prototype.toString.call(value); }
  16. if (output === '') {
  17. output = JSON.stringify(value);
  18. }
  19. }
  20. var type = Object.prototype.toString.call(value).toLowerCase().slice(8, -1);
  21. output += ' (' + type;
  22. var typeOf = typeof value;
  23. if (type !== typeOf) {
  24. output += ', typeof: ' + typeOf;
  25. }
  26. return output + ') ' + msg;
  27. };
  28. test('non-symbol values', function (t) {
  29. var nonSymbols = [
  30. true,
  31. false,
  32. Object(true),
  33. Object(false),
  34. null,
  35. undefined,
  36. {},
  37. [],
  38. /a/g,
  39. 'string',
  40. 42,
  41. new Date(),
  42. function () {},
  43. NaN
  44. ];
  45. t.plan(nonSymbols.length);
  46. forEach(nonSymbols, function (nonSymbol) {
  47. t.equal(false, isSymbol(nonSymbol), debug(nonSymbol, 'is not a symbol'));
  48. });
  49. t.end();
  50. });
  51. test('faked symbol values', function (t) {
  52. t.test('real symbol valueOf', { skip: !hasSymbols }, function (st) {
  53. var fakeSymbol = { valueOf: function () { return Symbol('foo'); } };
  54. st.equal(false, isSymbol(fakeSymbol), 'object with valueOf returning a symbol is not a symbol');
  55. st.end();
  56. });
  57. t.test('faked @@toStringTag', { skip: !hasSymbols || !Symbol.toStringTag }, function (st) {
  58. var fakeSymbol = { valueOf: function () { return Symbol('foo'); } };
  59. fakeSymbol[Symbol.toStringTag] = 'Symbol';
  60. st.equal(false, isSymbol(fakeSymbol), 'object with fake Symbol @@toStringTag and valueOf returning a symbol is not a symbol');
  61. var notSoFakeSymbol = { valueOf: function () { return 42; } };
  62. notSoFakeSymbol[Symbol.toStringTag] = 'Symbol';
  63. st.equal(false, isSymbol(notSoFakeSymbol), 'object with fake Symbol @@toStringTag and valueOf not returning a symbol is not a symbol');
  64. st.end();
  65. });
  66. var fakeSymbolString = { toString: function () { return 'Symbol(foo)'; } };
  67. t.equal(false, isSymbol(fakeSymbolString), 'object with toString returning Symbol(foo) is not a symbol');
  68. t.end();
  69. });
  70. test('Symbol support', { skip: !hasSymbols }, function (t) {
  71. t.test('well-known Symbols', function (st) {
  72. var wellKnownSymbols = Object.getOwnPropertyNames(Symbol).filter(function filterer(name) {
  73. return name !== 'for' && name !== 'keyFor' && !(name in filterer);
  74. });
  75. wellKnownSymbols.forEach(function (name) {
  76. var sym = Symbol[name];
  77. st.equal(true, isSymbol(sym), debug(sym, ' is a symbol'));
  78. });
  79. st.end();
  80. });
  81. t.test('user-created symbols', function (st) {
  82. var symbols = [
  83. Symbol(),
  84. Symbol('foo'),
  85. Symbol.for('foo'),
  86. Object(Symbol('object'))
  87. ];
  88. symbols.forEach(function (sym) {
  89. st.equal(true, isSymbol(sym), debug(sym, ' is a symbol'));
  90. });
  91. st.end();
  92. });
  93. t.end();
  94. });