test_analyze_input_string.js (6440B)
1 // Any copyright is dedicated to the Public Domain. 2 // http://creativecommons.org/publicdomain/zero/1.0/ 3 4 "use strict"; 5 const { 6 analyzeInputString, 7 } = require("resource://devtools/shared/webconsole/analyze-input-string.js"); 8 9 add_task(() => { 10 const tests = [ 11 { 12 desc: "simple property access", 13 input: `var a = {b: 1};a.b`, 14 expected: { 15 isElementAccess: false, 16 isPropertyAccess: true, 17 expressionBeforePropertyAccess: `var a = {b: 1};a`, 18 lastStatement: "a.b", 19 mainExpression: `a`, 20 matchProp: `b`, 21 }, 22 }, 23 { 24 desc: "deep property access", 25 input: `a.b.c`, 26 expected: { 27 isElementAccess: false, 28 isPropertyAccess: true, 29 expressionBeforePropertyAccess: `a.b`, 30 lastStatement: "a.b.c", 31 mainExpression: `a.b`, 32 matchProp: `c`, 33 }, 34 }, 35 { 36 desc: "element access", 37 input: `a["b`, 38 expected: { 39 isElementAccess: true, 40 isPropertyAccess: true, 41 expressionBeforePropertyAccess: `a`, 42 lastStatement: `a["b`, 43 mainExpression: `a`, 44 matchProp: `"b`, 45 }, 46 }, 47 { 48 desc: "element access without quotes", 49 input: `a[b`, 50 expected: { 51 isElementAccess: true, 52 isPropertyAccess: true, 53 expressionBeforePropertyAccess: `a`, 54 lastStatement: `a[b`, 55 mainExpression: `a`, 56 matchProp: `b`, 57 }, 58 }, 59 { 60 desc: "simple optional chaining access", 61 input: `a?.b`, 62 expected: { 63 isElementAccess: false, 64 isPropertyAccess: true, 65 expressionBeforePropertyAccess: `a`, 66 lastStatement: `a?.b`, 67 mainExpression: `a`, 68 matchProp: `b`, 69 }, 70 }, 71 { 72 desc: "deep optional chaining access", 73 input: `a?.b?.c`, 74 expected: { 75 isElementAccess: false, 76 isPropertyAccess: true, 77 expressionBeforePropertyAccess: `a?.b`, 78 lastStatement: `a?.b?.c`, 79 mainExpression: `a?.b`, 80 matchProp: `c`, 81 }, 82 }, 83 { 84 desc: "optional chaining element access", 85 input: `a?.["b`, 86 expected: { 87 isElementAccess: true, 88 isPropertyAccess: true, 89 expressionBeforePropertyAccess: `a`, 90 lastStatement: `a?.["b`, 91 mainExpression: `a`, 92 matchProp: `"b`, 93 }, 94 }, 95 { 96 desc: "optional chaining element access without quotes", 97 input: `a?.[b`, 98 expected: { 99 isElementAccess: true, 100 isPropertyAccess: true, 101 expressionBeforePropertyAccess: `a`, 102 lastStatement: `a?.[b`, 103 mainExpression: `a`, 104 matchProp: `b`, 105 }, 106 }, 107 { 108 desc: "deep optional chaining element access with quotes", 109 input: `var a = {b: 1, c: ["."]}; a?.["b"]?.c?.["d[.`, 110 expected: { 111 isElementAccess: true, 112 isPropertyAccess: true, 113 expressionBeforePropertyAccess: `var a = {b: 1, c: ["."]}; a?.["b"]?.c`, 114 lastStatement: `a?.["b"]?.c?.["d[.`, 115 mainExpression: `a?.["b"]?.c`, 116 matchProp: `"d[.`, 117 }, 118 }, 119 { 120 desc: "literal arrays with newline", 121 input: `[1,2,3,\n4\n].`, 122 expected: { 123 isElementAccess: false, 124 isPropertyAccess: true, 125 expressionBeforePropertyAccess: `[1,2,3,\n4\n]`, 126 lastStatement: `[1,2,3,4].`, 127 mainExpression: `[1,2,3,4]`, 128 matchProp: ``, 129 }, 130 }, 131 { 132 desc: "number literal with newline", 133 input: `1\n.`, 134 expected: { 135 isElementAccess: false, 136 isPropertyAccess: true, 137 expressionBeforePropertyAccess: `1\n`, 138 lastStatement: `1\n.`, 139 mainExpression: `1`, 140 matchProp: ``, 141 }, 142 }, 143 { 144 desc: "string literal", 145 input: `"abc".`, 146 expected: { 147 isElementAccess: false, 148 isPropertyAccess: true, 149 expressionBeforePropertyAccess: `"abc"`, 150 lastStatement: `"abc".`, 151 mainExpression: `"abc"`, 152 matchProp: ``, 153 }, 154 }, 155 { 156 desc: "string literal containing backslash", 157 input: `"\\n".`, 158 expected: { 159 isElementAccess: false, 160 isPropertyAccess: true, 161 expressionBeforePropertyAccess: `"\\n"`, 162 lastStatement: `"\\n".`, 163 mainExpression: `"\\n"`, 164 matchProp: ``, 165 }, 166 }, 167 { 168 desc: "single quote string literal containing backslash", 169 input: `'\\r'.`, 170 expected: { 171 isElementAccess: false, 172 isPropertyAccess: true, 173 expressionBeforePropertyAccess: `'\\r'`, 174 lastStatement: `'\\r'.`, 175 mainExpression: `'\\r'`, 176 matchProp: ``, 177 }, 178 }, 179 { 180 desc: "template string literal containing backslash", 181 input: "`\\\\`.", 182 expected: { 183 isElementAccess: false, 184 isPropertyAccess: true, 185 expressionBeforePropertyAccess: "`\\\\`", 186 lastStatement: "`\\\\`.", 187 mainExpression: "`\\\\`", 188 matchProp: ``, 189 }, 190 }, 191 { 192 desc: "unterminated double quote string literal", 193 input: `"\n`, 194 expected: { 195 err: "unterminated string literal", 196 }, 197 }, 198 { 199 desc: "unterminated single quote string literal", 200 input: `'\n`, 201 expected: { 202 err: "unterminated string literal", 203 }, 204 }, 205 { 206 desc: "string literal with surrogate pair character", 207 input: `"🧑".c`, 208 expected: { 209 isElementAccess: false, 210 isPropertyAccess: true, 211 expressionBeforePropertyAccess: `"🧑"`, 212 lastStatement: `"🧑".c`, 213 mainExpression: `"🧑"`, 214 matchProp: `c`, 215 }, 216 }, 217 { 218 desc: "optional chaining operator with spaces", 219 input: `test ?. ["propA"] ?. [0] ?. ["propB"] ?. ['to`, 220 expected: { 221 isElementAccess: true, 222 isPropertyAccess: true, 223 expressionBeforePropertyAccess: `test ?. ["propA"] ?. [0] ?. ["propB"] `, 224 lastStatement: `test ?. ["propA"] ?. [0] ?. ["propB"] ?. ['to`, 225 mainExpression: `test ?. ["propA"] ?. [0] ?. ["propB"]`, 226 matchProp: `'to`, 227 }, 228 }, 229 ]; 230 231 for (const { input, desc, expected } of tests) { 232 const result = analyzeInputString(input); 233 for (const [key, value] of Object.entries(expected)) { 234 Assert.equal(value, result[key], `${desc} | ${key} has expected value`); 235 } 236 } 237 });