string_at.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  7. const StringPrototype = String.prototype;
  8. const at = StringPrototype.at;
  9. const call = Function.call.bind(Function.call); // (fn: Function, thisArg: any, ...args: any[]) => any
  10. const tests = [
  11. {
  12. name: "Existnce of String.prototype.at",
  13. body: function () {
  14. assert.isTrue(typeof at === "function", "String.prototype.at should be a function");
  15. }
  16. },
  17. {
  18. name: "String.prototype.at's descriptor",
  19. body: function () {
  20. const desc = Object.getOwnPropertyDescriptor(StringPrototype, "at");
  21. assert.areEqual(desc.configurable, true, "String.prototype.at should be configurable");
  22. assert.areEqual(desc.writable, true, "String.prototype.at should be writable");
  23. assert.areEqual(desc.enumerable, false, "String.prototype.at should not be enumerable");
  24. }
  25. },
  26. {
  27. name: "Properties of String.prototype.at",
  28. body: function () {
  29. const nameDesc = Object.getOwnPropertyDescriptor(at, "name");
  30. assert.areEqual(at.name, "at", 'String.prototype.at.name should be "at"');
  31. assert.areEqual(nameDesc.configurable, true, "String.prototype.at.name should be configurable");
  32. assert.areEqual(nameDesc.writable, false, "String.prototype.at.name should not be writable");
  33. assert.areEqual(nameDesc.enumerable, false, "String.prototype.at.name should not be enumerable");
  34. const lengthDesc = Object.getOwnPropertyDescriptor(at, "length");
  35. assert.areEqual(at.length, 1, 'String.prototype.at.length should be 1');
  36. assert.areEqual(lengthDesc.configurable, true, "String.prototype.at.length should be configurable");
  37. assert.areEqual(lengthDesc.writable, false, "String.prototype.at.length should not be writable");
  38. assert.areEqual(lengthDesc.enumerable, false, "String.prototype.at.length should not be enumerable");
  39. }
  40. },
  41. {
  42. name: "String.prototype.at called on invalid object",
  43. body: function () {
  44. // on object without toString() should throw
  45. assert.throws(() => { call(at, Object.create(null)) }, TypeError);
  46. assert.throws(() => { call(at, null) }, TypeError);
  47. assert.throws(() => { call(at, undefined) }, TypeError);
  48. }
  49. },
  50. {
  51. name: "Indexation of string with non-numerical argument",
  52. body: function () {
  53. const string = "01";
  54. assert.areEqual(string.at(false), "0", '"01".at(false) should be "0"');
  55. assert.areEqual(string.at(null), "0", '"01".at(null) should be "0"');
  56. assert.areEqual(string.at(undefined), "0", '"01".at(undefined) should be "0"');
  57. assert.areEqual(string.at(""), "0", '"01".at("") should be "0"');
  58. assert.areEqual(string.at(function () { }), "0", '"01".at(function() {}) should be "0"');
  59. assert.areEqual(string.at([]), "0", '"01".at([]) should be "0"');
  60. assert.areEqual(string.at(true), "1", '"01".at(true) should be "1"');
  61. assert.areEqual(string.at("1"), "1", '"01".at("1") should be "1"');
  62. }
  63. },
  64. {
  65. name: "Indexation of string with negative numerical argument",
  66. body: function () {
  67. const string = "0\u26052";
  68. assert.areEqual(string.at(0), "0", '"0\u26052".at(0) should be "0"');
  69. assert.areEqual(string.at(-1), "2", '"0\u26052".at(-1) should be "2"');
  70. assert.areEqual(string.at(-2), "\u2605", '"0\u26052".at(-2) should be "\u2605"');
  71. }
  72. },
  73. {
  74. name: "Indexation of string with positive numerical argument",
  75. body: function () {
  76. const string = "0\u26052";
  77. assert.areEqual(string.at(0), "0", '"0\u26052".at(0) should be "0"');
  78. assert.areEqual(string.at(1), "\u2605", '"0\u26052".at(-1) should be "\u2605"');
  79. assert.areEqual(string.at(2), "2", '"0\u26052".at(-2) should be "2"');
  80. }
  81. },
  82. {
  83. name: "Out of bounds",
  84. body: function () {
  85. const string = "";
  86. assert.areEqual(string.at(0), undefined, `"".at(0) should be undefined`);
  87. assert.areEqual(string.at(-1), undefined, `"".at(-1) should be undefined`);
  88. assert.areEqual(string.at(2), undefined, `"".at(2) should be undefined`);
  89. }
  90. },
  91. {
  92. name: "Argument ToInteger()",
  93. body: function () {
  94. let count = 0;
  95. const index = {
  96. valueOf() {
  97. count++;
  98. return 1;
  99. }
  100. };
  101. const string = "123";
  102. assert.areEqual(string.at(index), "2", 'result of string.at(index) should be "2"');
  103. assert.areEqual(count, 1, 'The value of count should be 1');
  104. }
  105. },
  106. {
  107. name: "String.prototype.at called on to-stringable object",
  108. body: function () {
  109. const object = {
  110. toString() {
  111. return "Test";
  112. }
  113. }
  114. assert.areEqual(call(at, object, 0), "T", 'call(at, object, 0) should be "T"');
  115. assert.areEqual(call(at, object, -1), "t", 'call(at, object, -1) should be "t"');
  116. assert.areEqual(call(at, object, 1), "e", 'call(at, object, 1) should be "e"');
  117. assert.areEqual(call(at, object, 2), "s", 'call(at, object, 2) should be "T"');
  118. }
  119. }
  120. ];
  121. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });