Changeset 266317 in webkit
- Timestamp:
- Aug 28, 2020, 6:39:46 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 40 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r266300 r266317 1 2020-08-28 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Audit: should be able to create/edit imported audits 4 https://bugs.webkit.org/show_bug.cgi?id=215555 5 <rdar://problem/67255483> 6 7 Reviewed by Devin Rousso. 8 9 * inspector/model/auditTestGroup.html: 10 * inspector/model/auditTestGroup-expected.txt: 11 Add tests that check how `disabled` and `supported` (via `supports`) is propagated in groups. 12 13 * inspector/audit/run.html: 14 * inspector/audit/run-expected.txt: 15 Add tests for `WebInspectorAudit` before `Audit.setup` is called. 16 17 * inspector/audit/manager-start-setup.html: 18 Renaming function call. 19 20 * inspector/audit/basic-async.html: 21 * inspector/audit/basic-boolean.html: 22 * inspector/audit/basic-debugger.html: 23 * inspector/audit/basic-error.html: 24 * inspector/audit/basic-object.html: 25 * inspector/audit/basic-promise.html: 26 * inspector/audit/basic-string.html: 27 * inspector/audit/basic-timeout.html: 28 * inspector/audit/run-resources.html: 29 Drive-by: remove `InspectorTest.debug()`. 30 1 31 2020-08-28 Hector Lopez <hector_i_lopez@apple.com> 2 32 -
trunk/LayoutTests/inspector/audit/basic-async.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-boolean.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-debugger.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-error.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-object.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-promise.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-string.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/basic-timeout.html
r245257 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.Basic"); 15 13 -
trunk/LayoutTests/inspector/audit/manager-start-setup.html
r245914 r266317 15 15 16 16 async function wrapTest(audit, expected, {getResultCallback} = {}) { 17 WI.auditManager. _addTest(audit);17 WI.auditManager.addTest(audit); 18 18 19 19 let [result] = await WI.auditManager.start([audit]); -
trunk/LayoutTests/inspector/audit/run-expected.txt
r245909 r266317 7 7 PASS: Run should send back 42. 8 8 9 -- Running test case: Audit.run.Valid.InjectedObject 9 -- Running test case: Audit.run.Valid.InjectedObject.BeforeSetup 10 Audit run "function() { return WebInspectorAudit; }"... 11 PASS: The injected WebInspectorAudit should be undefined. 12 13 -- Running test case: Audit.run.Valid.InjectedObject.AfterSetup 10 14 Audit setup... 11 15 Audit run "function() { return WebInspectorAudit; }"... -
trunk/LayoutTests/inspector/audit/run-resources.html
r242941 r266317 10 10 function test() 11 11 { 12 InspectorTest.debug();13 14 12 let suite = InspectorTest.Audit.createSuite("Audit.run.Resources"); 15 13 -
trunk/LayoutTests/inspector/audit/run.html
r251227 r266317 32 32 33 33 suite.addTestCase({ 34 name: "Audit.run.Valid.InjectedObject", 34 name: "Audit.run.Valid.InjectedObject.BeforeSetup", 35 description: "Check that an error is not thrown if trying to reference the injected object without calling setup.", 36 async test() { 37 await auditRun(`function() { return WebInspectorAudit; }`, (result) => { 38 InspectorTest.expectEqual(result.type, "undefined", "The injected WebInspectorAudit should be undefined."); 39 }); 40 }, 41 }); 42 43 suite.addTestCase({ 44 name: "Audit.run.Valid.InjectedObject.AfterSetup", 35 45 description: "Check that an object is injected into the function that is executed.", 36 46 async test() { -
trunk/LayoutTests/inspector/model/auditTestGroup-expected.txt
r245914 r266317 110 110 } 111 111 112 -- Running test case: AuditTestGroup.Disabled.Constructor.Enabled 113 PASS: Group should not be disabled. 114 PASS: Test1 should not be disabled. 115 PASS: Test2 should not be disabled. 116 117 -- Running test case: AuditTestGroup.Disabled.Constructor.Disabled 118 PASS: Group should be disabled. 119 PASS: Test1 should be disabled. 120 PASS: Test2 should be disabled. 121 122 -- Running test case: AuditTestGroup.Disabled.ChangeGroup.Enabled 123 PASS: Group should not be disabled. 124 PASS: Test1 should not be disabled. 125 PASS: Test2 should not be disabled. 126 127 Marking group as disabled... 128 PASS: Group should be disabled. 129 PASS: Test1 should be disabled. 130 PASS: Test2 should be disabled. 131 132 -- Running test case: AuditTestGroup.Disabled.ChangeGroup.DisabledGroup 133 PASS: Group should be disabled. 134 PASS: Test1 should be disabled. 135 PASS: Test2 should be disabled. 136 137 Marking group as enabled... 138 PASS: Group should not be disabled. 139 PASS: Test1 should not be disabled. 140 PASS: Test2 should not be disabled. 141 142 -- Running test case: AuditTestGroup.Disabled.ChangeGroup.DisabledTests 143 PASS: Group should be disabled. 144 PASS: Test1 should be disabled. 145 PASS: Test2 should be disabled. 146 147 Marking group as enabled... 148 PASS: Group should not be disabled. 149 PASS: Test1 should not be disabled. 150 PASS: Test2 should not be disabled. 151 152 -- Running test case: AuditTestGroup.Disabled.ChangeTests.Enabled 153 PASS: Group should not be disabled. 154 PASS: Test1 should not be disabled. 155 PASS: Test2 should not be disabled. 156 157 Marking Test1 as disabled... 158 PASS: Group should not be disabled. 159 PASS: Test1 should be disabled. 160 PASS: Test2 should not be disabled. 161 162 Marking Test2 as disabled... 163 PASS: Group should be disabled. 164 PASS: Test1 should be disabled. 165 PASS: Test2 should be disabled. 166 167 -- Running test case: AuditTestGroup.Disabled.ChangeTests.DisabledGroup 168 PASS: Group should be disabled. 169 PASS: Test1 should be disabled. 170 PASS: Test2 should be disabled. 171 172 Marking test as enabled 1... 173 PASS: Group should not be disabled. 174 PASS: Test1 should not be disabled. 175 PASS: Test2 should be disabled. 176 177 Marking test as enabled 2... 178 PASS: Group should not be disabled. 179 PASS: Test1 should not be disabled. 180 PASS: Test2 should not be disabled. 181 182 -- Running test case: AuditTestGroup.Disabled.ChangeTests.DisabledTests 183 PASS: Group should be disabled. 184 PASS: Test1 should be disabled. 185 PASS: Test2 should be disabled. 186 187 Marking test as enabled 1... 188 PASS: Group should not be disabled. 189 PASS: Test1 should not be disabled. 190 PASS: Test2 should be disabled. 191 192 Marking test as enabled 2... 193 PASS: Group should not be disabled. 194 PASS: Test1 should not be disabled. 195 PASS: Test2 should not be disabled. 196 197 -- Running test case: AuditTestGroup.Supports.Constructor.Supported 198 PASS: Group should be supported. 199 PASS: Test1 should be supported. 200 PASS: Test2 should be supported. 201 202 -- Running test case: AuditTestGroup.Supports.Constructor.Unsupported 203 WARN: Audit Warning: "Group" is too new to run in this Web Inspector 204 PASS: Group should not be supported. 205 PASS: Test1 should not be supported. 206 PASS: Test2 should not be supported. 207 208 -- Running test case: AuditTestGroup.Supports.ChangeGroup.Supported 209 PASS: Group should be supported. 210 PASS: Test1 should be supported. 211 PASS: Test2 should be supported. 212 213 Marking group as unsupported... 214 PASS: Group should not be supported. 215 PASS: Test1 should not be supported. 216 PASS: Test2 should not be supported. 217 218 -- Running test case: AuditTestGroup.Supports.ChangeGroup.UnsupportedGroup 219 WARN: Audit Warning: "Group" is too new to run in this Web Inspector 220 PASS: Group should not be supported. 221 PASS: Test1 should not be supported. 222 PASS: Test2 should not be supported. 223 224 Marking group as supported... 225 PASS: Group should be supported. 226 PASS: Test1 should be supported. 227 PASS: Test2 should be supported. 228 229 -- Running test case: AuditTestGroup.Supports.ChangeGroup.UnsupportedTests 230 WARN: Audit Warning: "Test1" is too new to run in this Web Inspector 231 WARN: Audit Warning: "Test2" is too new to run in this Web Inspector 232 PASS: Group should not be supported. 233 PASS: Test1 should not be supported. 234 PASS: Test2 should not be supported. 235 236 Marking group as supported... 237 PASS: Group should not be supported. 238 PASS: Test1 should not be supported. 239 PASS: Test2 should not be supported. 240 241 -- Running test case: AuditTestGroup.Supports.ChangeTests.Supported 242 PASS: Group should be supported. 243 PASS: Test1 should be supported. 244 PASS: Test2 should be supported. 245 246 Marking Test1 as unsupported... 247 PASS: Group should be supported. 248 PASS: Test1 should not be supported. 249 PASS: Test2 should be supported. 250 251 Marking Test2 as unsupported... 252 PASS: Group should not be supported. 253 PASS: Test1 should not be supported. 254 PASS: Test2 should not be supported. 255 256 -- Running test case: AuditTestGroup.Supports.ChangeTests.UnsupportedGroup 257 WARN: Audit Warning: "Group" is too new to run in this Web Inspector 258 PASS: Group should not be supported. 259 PASS: Test1 should not be supported. 260 PASS: Test2 should not be supported. 261 262 Marking Test1 as supported... 263 PASS: Group should not be supported. 264 PASS: Test1 should not be supported. 265 PASS: Test2 should not be supported. 266 267 Marking Test2 as supported... 268 PASS: Group should not be supported. 269 PASS: Test1 should not be supported. 270 PASS: Test2 should not be supported. 271 272 -- Running test case: AuditTestGroup.Supports.ChangeTests.UnsupportedTests 273 WARN: Audit Warning: "Test1" is too new to run in this Web Inspector 274 WARN: Audit Warning: "Test2" is too new to run in this Web Inspector 275 PASS: Group should not be supported. 276 PASS: Test1 should not be supported. 277 PASS: Test2 should not be supported. 278 279 Marking Test1 as supported... 280 PASS: Group should be supported. 281 PASS: Test1 should be supported. 282 PASS: Test2 should not be supported. 283 284 Marking Test2 as supported... 285 PASS: Group should be supported. 286 PASS: Test1 should be supported. 287 PASS: Test2 should be supported. 288 -
trunk/LayoutTests/inspector/model/auditTestGroup.html
r242808 r266317 151 151 payloadTests.forEach(addPayloadTest); 152 152 153 suite.addTestCase({ 154 name: "AuditTestGroup.Disabled.Constructor.Enabled", 155 description: "Check that `disabled` constructor option properly propagates.", 156 async test() { 157 let group = new WI.AuditTestGroup("Group", [ 158 new WI.AuditTestCase("Test1", "function() {}"), 159 new WI.AuditTestCase("Test2", "function() {}"), 160 ]); 161 162 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 163 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 164 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 165 }, 166 }); 167 168 suite.addTestCase({ 169 name: "AuditTestGroup.Disabled.Constructor.Disabled", 170 description: "Check that `disabled` constructor option properly propagates.", 171 async test() { 172 let group = new WI.AuditTestGroup("Group", [ 173 new WI.AuditTestCase("Test1", "function() {}"), 174 new WI.AuditTestCase("Test2", "function() {}"), 175 ], {disabled: true}); 176 177 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 178 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 179 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 180 }, 181 }); 182 183 suite.addTestCase({ 184 name: "AuditTestGroup.Disabled.ChangeGroup.Enabled", 185 description: "Check that `disabled` is propagated to tests when set on group.", 186 async test() { 187 let group = new WI.AuditTestGroup("Group", [ 188 new WI.AuditTestCase("Test1", "function() {}"), 189 new WI.AuditTestCase("Test2", "function() {}"), 190 ]); 191 192 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 193 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 194 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 195 196 InspectorTest.newline(); 197 InspectorTest.log("Marking group as disabled..."); 198 199 group.disabled = true; 200 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 201 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 202 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 203 }, 204 }); 205 206 suite.addTestCase({ 207 name: "AuditTestGroup.Disabled.ChangeGroup.DisabledGroup", 208 description: "Check that `disabled` is propagated to tests when set on group.", 209 async test() { 210 let group = new WI.AuditTestGroup("Group", [ 211 new WI.AuditTestCase("Test1", "function() {}"), 212 new WI.AuditTestCase("Test2", "function() {}"), 213 ], {disabled: true}); 214 215 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 216 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 217 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 218 219 InspectorTest.newline(); 220 InspectorTest.log("Marking group as enabled..."); 221 222 group.disabled = false; 223 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 224 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 225 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 226 }, 227 }); 228 229 suite.addTestCase({ 230 name: "AuditTestGroup.Disabled.ChangeGroup.DisabledTests", 231 description: "Check that `disabled` is propagated to tests when set on group.", 232 async test() { 233 let group = new WI.AuditTestGroup("Group", [ 234 new WI.AuditTestCase("Test1", "function() {}", {disabled: true}), 235 new WI.AuditTestCase("Test2", "function() {}", {disabled: true}), 236 ]); 237 238 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 239 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 240 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 241 242 InspectorTest.newline(); 243 InspectorTest.log("Marking group as enabled..."); 244 245 group.disabled = false; 246 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 247 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 248 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 249 }, 250 }); 251 252 suite.addTestCase({ 253 name: "AuditTestGroup.Disabled.ChangeTests.Enabled", 254 description: "Check that `disabled` is propagated to group when set on tests.", 255 async test() { 256 let group = new WI.AuditTestGroup("Group", [ 257 new WI.AuditTestCase("Test1", "function() {}"), 258 new WI.AuditTestCase("Test2", "function() {}"), 259 ]); 260 261 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 262 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 263 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 264 265 InspectorTest.newline(); 266 InspectorTest.log("Marking Test1 as disabled..."); 267 268 group.tests[0].disabled = true; 269 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 270 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 271 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 272 273 InspectorTest.newline(); 274 InspectorTest.log("Marking Test2 as disabled..."); 275 276 group.tests[1].disabled = true; 277 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 278 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 279 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 280 }, 281 }); 282 283 suite.addTestCase({ 284 name: "AuditTestGroup.Disabled.ChangeTests.DisabledGroup", 285 description: "Check that `disabled` is propagated to group when set on tests.", 286 async test() { 287 let group = new WI.AuditTestGroup("Group", [ 288 new WI.AuditTestCase("Test1", "function() {}"), 289 new WI.AuditTestCase("Test2", "function() {}"), 290 ], {disabled: true}); 291 292 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 293 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 294 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 295 296 InspectorTest.newline(); 297 InspectorTest.log("Marking test as enabled 1..."); 298 299 group.tests[0].disabled = false; 300 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 301 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 302 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 303 304 InspectorTest.newline(); 305 InspectorTest.log("Marking test as enabled 2..."); 306 307 group.tests[1].disabled = false; 308 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 309 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 310 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 311 }, 312 }); 313 314 suite.addTestCase({ 315 name: "AuditTestGroup.Disabled.ChangeTests.DisabledTests", 316 description: "Check that `disabled` is propagated to group when set on tests.", 317 async test() { 318 let group = new WI.AuditTestGroup("Group", [ 319 new WI.AuditTestCase("Test1", "function() {}", {disabled: true}), 320 new WI.AuditTestCase("Test2", "function() {}", {disabled: true}), 321 ]); 322 323 InspectorTest.expectTrue(group.disabled, "Group should be disabled."); 324 InspectorTest.expectTrue(group.tests[0].disabled, "Test1 should be disabled."); 325 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 326 327 InspectorTest.newline(); 328 InspectorTest.log("Marking test as enabled 1..."); 329 330 group.tests[0].disabled = false; 331 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 332 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 333 InspectorTest.expectTrue(group.tests[1].disabled, "Test2 should be disabled."); 334 335 InspectorTest.newline(); 336 InspectorTest.log("Marking test as enabled 2..."); 337 338 group.tests[1].disabled = false; 339 InspectorTest.expectFalse(group.disabled, "Group should not be disabled."); 340 InspectorTest.expectFalse(group.tests[0].disabled, "Test1 should not be disabled."); 341 InspectorTest.expectFalse(group.tests[1].disabled, "Test2 should not be disabled."); 342 }, 343 }); 344 345 suite.addTestCase({ 346 name: "AuditTestGroup.Supports.Constructor.Supported", 347 description: "Check that `supported` properly propagates with `supports` constructor option.", 348 async test() { 349 let group = new WI.AuditTestGroup("Group", [ 350 new WI.AuditTestCase("Test1", "function() {}"), 351 new WI.AuditTestCase("Test2", "function() {}"), 352 ]); 353 354 InspectorTest.expectTrue(group.supported, "Group should be supported."); 355 InspectorTest.expectTrue(group.tests[0].supported, "Test1 should be supported."); 356 InspectorTest.expectTrue(group.tests[1].supported, "Test2 should be supported."); 357 }, 358 }); 359 360 suite.addTestCase({ 361 name: "AuditTestGroup.Supports.Constructor.Unsupported", 362 description: "Check that `supported` properly propagates with `supports` constructor option.", 363 async test() { 364 let group = new WI.AuditTestGroup("Group", [ 365 new WI.AuditTestCase("Test1", "function() {}"), 366 new WI.AuditTestCase("Test2", "function() {}"), 367 ], {supports: WI.AuditTestBase.Version + 1}); 368 369 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 370 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 371 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 372 }, 373 }); 374 375 suite.addTestCase({ 376 name: "AuditTestGroup.Supports.ChangeGroup.Supported", 377 description: "Check that `supported` properly propagates to tests when `supports` is set on group.", 378 async test() { 379 let group = new WI.AuditTestGroup("Group", [ 380 new WI.AuditTestCase("Test1", "function() {}"), 381 new WI.AuditTestCase("Test2", "function() {}"), 382 ]); 383 384 InspectorTest.expectTrue(group.supported, "Group should be supported."); 385 InspectorTest.expectTrue(group.tests[0].supported, "Test1 should be supported."); 386 InspectorTest.expectTrue(group.tests[1].supported, "Test2 should be supported."); 387 388 InspectorTest.newline(); 389 InspectorTest.log("Marking group as unsupported..."); 390 391 group.supports = WI.AuditTestBase.Version + 1; 392 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 393 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 394 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 395 }, 396 }); 397 398 suite.addTestCase({ 399 name: "AuditTestGroup.Supports.ChangeGroup.UnsupportedGroup", 400 description: "Check that `supported` properly propagates to tests when `supports` is set on group.", 401 async test() { 402 let group = new WI.AuditTestGroup("Group", [ 403 new WI.AuditTestCase("Test1", "function() {}"), 404 new WI.AuditTestCase("Test2", "function() {}"), 405 ], {supports: WI.AuditTestBase.Version + 1}); 406 407 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 408 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 409 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 410 411 InspectorTest.newline(); 412 InspectorTest.log("Marking group as supported..."); 413 414 group.supports = NaN; 415 InspectorTest.expectTrue(group.supported, "Group should be supported."); 416 InspectorTest.expectTrue(group.tests[0].supported, "Test1 should be supported."); 417 InspectorTest.expectTrue(group.tests[1].supported, "Test2 should be supported."); 418 }, 419 }); 420 421 suite.addTestCase({ 422 name: "AuditTestGroup.Supports.ChangeGroup.UnsupportedTests", 423 description: "Check that `supported` properly propagates to tests when `supports` is set on group.", 424 async test() { 425 let group = new WI.AuditTestGroup("Group", [ 426 new WI.AuditTestCase("Test1", "function() {}", {supports: WI.AuditTestBase.Version + 1}), 427 new WI.AuditTestCase("Test2", "function() {}", {supports: WI.AuditTestBase.Version + 1}), 428 ]); 429 430 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 431 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 432 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 433 434 InspectorTest.newline(); 435 InspectorTest.log("Marking group as supported..."); 436 437 group.supports = NaN; 438 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 439 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 440 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 441 }, 442 }); 443 444 suite.addTestCase({ 445 name: "AuditTestGroup.Supports.ChangeTests.Supported", 446 description: "Check that `supported` properly propagates to group when `supports` is set on tests.", 447 async test() { 448 let group = new WI.AuditTestGroup("Group", [ 449 new WI.AuditTestCase("Test1", "function() {}"), 450 new WI.AuditTestCase("Test2", "function() {}"), 451 ]); 452 453 InspectorTest.expectTrue(group.supported, "Group should be supported."); 454 InspectorTest.expectTrue(group.tests[0].supported, "Test1 should be supported."); 455 InspectorTest.expectTrue(group.tests[1].supported, "Test2 should be supported."); 456 457 InspectorTest.newline(); 458 InspectorTest.log("Marking Test1 as unsupported..."); 459 460 group.tests[0].supports = WI.AuditTestBase.Version + 1; 461 InspectorTest.expectTrue(group.supported, "Group should be supported."); 462 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 463 InspectorTest.expectTrue(group.tests[1].supported, "Test2 should be supported."); 464 465 InspectorTest.newline(); 466 InspectorTest.log("Marking Test2 as unsupported..."); 467 468 group.tests[1].supports = WI.AuditTestBase.Version + 1; 469 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 470 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 471 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 472 }, 473 }); 474 475 suite.addTestCase({ 476 name: "AuditTestGroup.Supports.ChangeTests.UnsupportedGroup", 477 description: "Check that `supported` properly propagates to group when `supports` is set on tests.", 478 async test() { 479 let group = new WI.AuditTestGroup("Group", [ 480 new WI.AuditTestCase("Test1", "function() {}"), 481 new WI.AuditTestCase("Test2", "function() {}"), 482 ], {supports: WI.AuditTestBase.Version + 1}); 483 484 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 485 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 486 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 487 488 InspectorTest.newline(); 489 InspectorTest.log("Marking Test1 as supported..."); 490 491 group.tests[0].supports = NaN; 492 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 493 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 494 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 495 496 InspectorTest.newline(); 497 InspectorTest.log("Marking Test2 as supported..."); 498 499 group.tests[1].supports = NaN; 500 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 501 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 502 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 503 }, 504 }); 505 506 suite.addTestCase({ 507 name: "AuditTestGroup.Supports.ChangeTests.UnsupportedTests", 508 description: "Check that `supported` properly propagates to group when `supports` is set on tests.", 509 async test() { 510 let group = new WI.AuditTestGroup("Group", [ 511 new WI.AuditTestCase("Test1", "function() {}", {supports: WI.AuditTestBase.Version + 1}), 512 new WI.AuditTestCase("Test2", "function() {}", {supports: WI.AuditTestBase.Version + 1}), 513 ]); 514 515 InspectorTest.expectFalse(group.supported, "Group should not be supported."); 516 InspectorTest.expectFalse(group.tests[0].supported, "Test1 should not be supported."); 517 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 518 519 InspectorTest.newline(); 520 InspectorTest.log("Marking Test1 as supported..."); 521 522 group.tests[0].supports = NaN; 523 InspectorTest.expectTrue(group.supported, "Group should be supported."); 524 InspectorTest.expectTrue(group.tests[0].supported, "Test1 should be supported."); 525 InspectorTest.expectFalse(group.tests[1].supported, "Test2 should not be supported."); 526 527 InspectorTest.newline(); 528 InspectorTest.log("Marking Test2 as supported..."); 529 530 group.tests[1].supports = NaN; 531 InspectorTest.expectTrue(group.supported, "Group should be supported."); 532 InspectorTest.expectTrue(group.tests[0].supported, "Test1 should be supported."); 533 InspectorTest.expectTrue(group.tests[1].supported, "Test2 should be supported."); 534 }, 535 }); 536 153 537 suite.runTestCasesAndFinish(); 154 538 } -
trunk/Source/WebInspectorUI/ChangeLog
r266227 r266317 1 2020-08-28 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Audit: should be able to create/edit imported audits 4 https://bugs.webkit.org/show_bug.cgi?id=215555 5 <rdar://problem/67255483> 6 7 Reviewed by Devin Rousso. 8 9 Extend the existing audit edit mode (which previously only let audits be disabled/deleted) 10 to also allow other JSON properties of audits to be added/edited/removed, meaning that 11 audits can now be completely created/configured from within the Web Inspector UI. \(o.o)/ 12 13 * UserInterface/Models/AuditTestBase.js: 14 (WI.AuditTestBase): 15 (WI.AuditTestBase.prototype.set name): Added. 16 (WI.AuditTestBase.prototype.set description): Added. 17 (WI.AuditTestBase.prototype.get supports): Added. 18 (WI.AuditTestBase.prototype.set supports): Added. 19 (WI.AuditTestBase.prototype.get setup): Added. 20 (WI.AuditTestBase.prototype.set setup): Added. 21 (WI.AuditTestBase.prototype.set disabled): 22 (WI.AuditTestBase.prototype.get editable): Added. 23 (WI.AuditTestBase.prototype.get default): Added. 24 (WI.AuditTestBase.prototype.markAsDefault): Added. 25 (WI.AuditTestBase.prototype.get topLevelTest): Added. 26 (WI.AuditTestBase.prototype.async runSetup): Added. 27 (WI.AuditTestBase.prototype.async start()): 28 (WI.AuditTestBase.prototype.stop()): 29 (WI.AuditTestBase.prototype.async clone): Added. 30 (WI.AuditTestBase.remove): Added. 31 (WI.AuditTestBase.saveIdentityToCookie): 32 (WI.AuditTestBase.toJSON): 33 (WI.AuditTestBase.prototype.determineIfSupported): Added. 34 (WI.AuditTestBase.prototype.updateSupported): Added. 35 (WI.AuditTestBase.prototype.updateResult): Added. 36 (WI.AuditTestBase.prototype.set supported): Deleted. 37 (WI.AuditTestBase.async setup): Deleted. 38 (WI.AuditTestBase.prototype.async setup): Deleted. 39 * UserInterface/Models/AuditTestGroup.js: 40 (WI.AuditTestGroup): 41 (WI.AuditTestGroup.prototype.addTest): Added. 42 (WI.AuditTestGroup.prototype.removeTest): Added. 43 (WI.AuditTestGroup.prototype.clearResult): 44 (WI.AuditTestGroup.prototype.async run): 45 (WI.AuditTestGroup.prototype.determineIfSupported): Added. 46 (WI.AuditTestGroup.prototype.updateSupported): Added. 47 (WI.AuditTestGroup.prototype.updateResult): Added. 48 (WI.AuditTestGroup.prototype._checkDisabled): Added. 49 (WI.AuditTestGroup.prototype._handleTestCompleted): 50 (WI.AuditTestGroup.prototype._handleTestDisabledChanged): 51 (WI.AuditTestGroup.prototype._handleTestSupportedChanged): Added. 52 (WI.AuditTestGroup.prototype._handleTestChanged): Added. 53 (WI.AuditTestGroup.prototype.get supported): Deleted. 54 (WI.AuditTestGroup.prototype.set supported): Deleted. 55 (WI.AuditTestGroup.prototype.get disabled): Deleted. 56 (WI.AuditTestGroup.prototype.set disabled): Deleted. 57 (WI.AuditTestGroup.prototype._updateResult): Deleted. 58 (WI.AuditTestGroup.prototype._updateResult): Deleted. 59 * UserInterface/Models/AuditTestCase.js: 60 (WI.AuditTestCase): 61 (WI.AuditTestCase.stringifyFunction): Added. 62 (WI.AuditTestCase.prototype.set test): Added. 63 (WI.AuditTestCase.prototype.async run): 64 Allow additional JSON keys to be changed in the UI: 65 - `name` 66 - `description` 67 - `supports` (ensure that changes recalculate whether the audit is actually supported) 68 - `setup` 69 - (groups) `tests` (via separate add and remove functions) 70 - (test cases) the actual `test` function 71 These properties are expected to only change in edit mode. 72 73 * UserInterface/Models/AuditTestResultBase.js: 74 (WI.AuditTestResultBase.prototype.get disabled): Added. 75 (WI.AuditTestResultBase.prototype.get editable): Added. 76 Audit results are never disabled and not editable. 77 78 * UserInterface/Controllers/AuditManager.js: 79 (WI.AuditManager): 80 (WI.AuditManager.prototype.set editing): 81 (WI.AuditManager.async start): 82 (WI.AuditManager.prototype.async start): 83 (WI.AuditManager.prototype.stop): 84 (WI.AuditManager.prototype.async processJSON): 85 (WI.AuditManager.prototype.loadStoredTests): 86 (WI.AuditManager.prototype.async addTest): Added. 87 (WI.AuditManager.prototype.removeTest): 88 (WI.AuditManager.prototype._addDefaultTests): 89 (WI.AuditManager.prototype._addDefaultTests.removeWhitespace): 90 (WI.AuditManager.prototype._addTest): Deleted. 91 (WI.AuditManager.prototype._topLevelTestForTest): Deleted. 92 Add helper functions and events for when the audit manager running mode changes to update UI. 93 Also add another default test that demonstrates the `supports` JSON key. 94 95 * UserInterface/Views/AuditNavigationSidebarPanel.js: 96 (WI.AuditNavigationSidebarPanel.prototype.showDefaultContentView): 97 (WI.AuditNavigationSidebarPanel.prototype.willDismissPopover): Added. 98 (WI.AuditNavigationSidebarPanel.prototype.initialLayout): 99 (WI.AuditNavigationSidebarPanel.prototype.matchTreeElementAgainstCustomFilters): 100 (WI.AuditNavigationSidebarPanel.prototype._addTest): 101 (WI.AuditNavigationSidebarPanel.prototype._addResult): 102 (WI.AuditNavigationSidebarPanel.prototype._updateControlNavigationItems): Added. 103 (WI.AuditNavigationSidebarPanel.prototype._updateEditNavigationItems): Added. 104 (WI.AuditNavigationSidebarPanel.prototype._handleAuditManagerEditingChanged): 105 (WI.AuditNavigationSidebarPanel.prototype._handleAuditManagerRunningStateChanged): Added. 106 (WI.AuditNavigationSidebarPanel.prototype._handleAuditTestAdded): 107 (WI.AuditNavigationSidebarPanel.prototype._handleAuditTestCompleted): 108 (WI.AuditNavigationSidebarPanel.prototype._handleAuditTestRemoved): 109 (WI.AuditNavigationSidebarPanel.prototype._handleAuditTestScheduled): 110 (WI.AuditNavigationSidebarPanel.prototype._treeSelectionDidChange): 111 (WI.AuditNavigationSidebarPanel.prototype._handleStartStopButtonNavigationItemClicked): 112 (WI.AuditNavigationSidebarPanel.prototype._handleCreateButtonNavigationItemClicked): Added. 113 (WI.AuditNavigationSidebarPanel.prototype._updateStartStopButtonNavigationItemState): Deleted. 114 (WI.AuditNavigationSidebarPanel.prototype._updateEditButtonNavigationItemState): Deleted. 115 * UserInterface/Views/AuditNavigationSidebarPanel.css: 116 (.sidebar > .panel.navigation.audit .edit-audits:not(.disabled):active): Added. 117 (.sidebar > .panel.navigation.audit .edit-audits:not(.disabled).activated): Added. 118 (.sidebar > .panel.navigation.audit .edit-audits:not(.disabled).activated:active): Added. 119 (.sidebar > .panel.navigation.audit .edit-audits.disabled): Added. 120 (.content-view.audit .message-text-view .navigation-item-help:is(.start-editing-audits, .stop-editing-audits) .navigation-bar): Added. 121 (.content-view.tab.audit .content-view > .audit-version): Added. 122 (.content-view.tab.audit .content-view .reference-page-link-container): Added. 123 (body[dir=ltr] .content-view.tab.audit .content-view .reference-page-link-container): Added. 124 (body[dir=rtl] .content-view.tab.audit .content-view .reference-page-link-container): Added. 125 (.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled):active): Deleted. 126 (.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled).activated): Deleted. 127 (.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled).activated:active): Deleted. 128 (.sidebar > .panel.navigation.audit > .content .edit-audits.disabled): Deleted. 129 (.finish-editing-audits-placeholder.message-text-view .navigation-item-help .navigation-bar): Deleted. 130 (.audit-version): Deleted. 131 Move the "Edit" toggle to be next to the filter bar so that it's always visible. Replace the 132 "[|>] Start" button with a "[+] Create" button when in edit mode, which adds a new audit at 133 the top-level. 134 135 * UserInterface/Views/AuditTestContentView.js: 136 (WI.AuditTestContentView): 137 (WI.AuditTestContentView.get navigationItems): 138 (WI.AuditTestContentView.get supportsSave): 139 (WI.AuditTestContentView.prototype.createNameElement): Added. 140 (WI.AuditTestContentView.prototype.createDescriptionElement): Added. 141 (WI.AuditTestContentView.prototype.createControlsTableElement): Added. 142 (WI.AuditTestContentView.prototype.layout): 143 (WI.AuditTestContentView.prototype.shown): 144 (WI.AuditTestContentView.prototype.hidden): 145 (WI.AuditTestContentView.prototype.handleResultChanged): 146 (WI.AuditTestContentView.prototype.showStoppingPlaceholder): 147 (WI.AuditTestContentView.prototype.showNoResultPlaceholder): 148 (WI.AuditTestContentView.prototype.showNoResultDataPlaceholder): 149 (WI.AuditTestContentView.prototype.showFilteredPlaceholder): 150 (WI.AuditTestContentView.prototype._updateExportNavigationItems): Added. 151 (WI.AuditTestContentView.prototype._updateSupportsInputState): Added. 152 (WI.AuditTestContentView.prototype._createSetupEditor): Added. 153 (WI.AuditTestContentView.prototype._handleEditorKeydown): Added. 154 (WI.AuditTestContentView.prototype._handleExportTestButtonNavigationItemClicked): Added. 155 (WI.AuditTestContentView.prototype._handleExportResultButtonNavigationItemClicked): Added. 156 (WI.AuditTestContentView.prototype._handleTestDisabledChanged): Added. 157 (WI.AuditTestContentView.prototype._handleTestSupportedChanged): Added. 158 (WI.AuditTestContentView.prototype._handleEditingChanged): Added. 159 (WI.AuditTestContentView.prototype._updateExportButtonNavigationItemState): Deleted. 160 (WI.AuditTestContentView.prototype._handleExportButtonNavigationItemClicked): Deleted. 161 * UserInterface/Views/AuditTestContentView.css: 162 (.content-view.audit-test:is(.unsupported, .disabled):not(.manager-editing)): Added. 163 (.content-view.audit-test.manager-editing .editor:not(:empty)): Added. 164 (.content-view.audit-test.manager-editing :is(.content-view.audit-test, header) .editor:not(:empty)): Added. 165 (.content-view.audit-test .CodeMirror): Added. 166 (.content-view.audit-test > header :is(.name, .description):not([contenteditable])): Added. 167 (.content-view.audit-test.manager-editing > header :is(.name, .description)[contenteditable]): Added. 168 (.content-view.audit-test.manager-editing > header .name[contenteditable]:empty): Added. 169 (.content-view.audit-test.manager-editing > header .name[contenteditable]:empty:before): Added. 170 (.content-view.audit-test.manager-editing > header .description[contenteditable]:empty:before): Added. 171 (.content-view.audit-test:not(.manager-editing) > header .description:empty): Added. 172 (.content-view.audit-test:not(.manager-editing) > header .description:empty, .content-view.audit-test:not(.manager-editing) > header table.controls): Added. 173 (.content-view.audit-test > header table.controls, .content-view.audit-test > header table.controls > tr > td): Added. 174 (.content-view.audit-test > header table.controls > tr > th): Added. 175 (.content-view.audit-test > header table.controls > tr.supports input[type="number"]): Added. 176 (.content-view.audit-test > header table.controls > tr.supports .warning): Added. 177 (.content-view.audit-test > header table.controls > tr.supports .warning:not(:empty)::before ): Added. 178 (.content-view.audit-test > header table.controls > tr.setup .editor): Added. 179 (.content-view.audit-test > section > .message-text-view > :is(progress, .indeterminate-progress-spinner)): Added. 180 (@media (prefers-color-scheme: dark) .content-view.audit-test > header table.controls > tr > th): Added. 181 Create helper functions for subclasses that simplify creating the editing UI. When in edit 182 mode, add `contenteditable` to the `name`/`description` and inputs for `supports`/`setup`. 183 184 * UserInterface/Views/AuditTestGroupContentView.js: 185 (WI.AuditTestGroupContentView): 186 (WI.AuditTestGroupContentView.prototype.willDismissPopover): Added. 187 (WI.AuditTestGroupContentView.prototype.createControlsTableElement): Added. 188 (WI.AuditTestGroupContentView.prototype.initialLayout): 189 (WI.AuditTestGroupContentView.prototype.layout): 190 (WI.AuditTestGroupContentView.prototype.shown): 191 (WI.AuditTestGroupContentView.prototype.hidden): 192 (WI.AuditTestGroupContentView.prototype.showRunningPlaceholder): 193 (WI.AuditTestGroupContentView.prototype._updateClassList): Added. 194 (WI.AuditTestGroupContentView.prototype._updateLevelScopeBar): 195 (WI.AuditTestGroupContentView.prototype._addTest): Added. 196 (WI.AuditTestGroupContentView.prototype._handleTestGroupTestAdded): Added. 197 (WI.AuditTestGroupContentView.prototype._handleTestGroupTestRemoved): Added. 198 * UserInterface/Views/AuditTestGroupContentView.css: 199 (.content-view.audit-test-group > section > .audit-test-group > header): Added. 200 (.content-view.audit-test-group.contains-test-case > header): 201 (.content-view.audit-test-group > section > .audit-test-group.contains-test-case > header): Added. 202 (.content-view.audit-test-group.contains-test-case + .audit-test-group.contains-test-case, .content-view.audit-test-group + .content-view.audit-test-case): Added. 203 (.content-view.audit-test-group.contains-test-case + .audit-test-group.contains-test-case): Deleted. 204 When in edit mode, add buttons for removing the audit and adding a new sub-audit (using the 205 new `WI.CreateAuditPopover` popover). 206 207 * UserInterface/Views/AuditTestCaseContentView.js: 208 (WI.AuditTestCaseContentView): 209 (WI.AuditTestCaseContentView.prototype.initialLayout): 210 (WI.AuditTestCaseContentView.prototype.layout): 211 (WI.AuditTestCaseContentView.prototype.showRunningPlaceholder): 212 * UserInterface/Views/AuditTestCaseContentView.css: 213 (.content-view-container > .content-view.audit-test-case): Added. 214 (.content-view-container > .content-view.audit-test-case > header): 215 (.content-view-container > .content-view.audit-test-case.manager-editing > header h1 > img): Added. 216 (.content-view-container > .content-view.audit-test-case > section > :not(.message-text-view, .editor):first-child): Added. 217 (.content-view-container > .content-view.audit-test-case > section): Added. 218 (.content-view-container > .content-view.audit-test-case > section, .content-view-container > .content-view.audit-test-case > section :is(.editor, .CodeMirror)): Added. 219 (.content-view.audit-test-case.manager-editing.disabled:not(.editable) > header h1 > img): Added. 220 (.content-view.audit-test-case > section > :not(.message-text-view, .editor)): Added. 221 (.content-view.audit-test-case > section > :not(.message-text-view, .editor):last-child): Added. 222 (.content-view.audit-test-case > section > :not(.message-text-view, .editor) + :not(.message-text-view, .editor)): Added. 223 (@media (prefers-color-scheme: dark) .content-view.audit-test-case.manager-editing > header h1 > img): Added. 224 (.content-view-container > .content-view.audit-test-case > section > :not(.message-text-view):first-child): Deleted. 225 (.content-view.audit-test-case > section > :not(.message-text-view)): Deleted. 226 (.content-view.audit-test-case > section > :not(.message-text-view):last-child): Deleted. 227 (.content-view.audit-test-case > section > :not(.message-text-view) + :not(.message-text-view)): Deleted. 228 (.content-view.audit-test-case > section .CodeMirror): Deleted. 229 When in edit mode, replace the icon with a (X) to remove the audit and show a `CodeMirror` 230 instance to allow editing the content. 231 232 * UserInterface/Views/AuditTreeElement.js: 233 (WI.AuditTreeElement): 234 (WI.AuditTreeElement.expandedSettingKey): Added. 235 (WI.AuditTreeElement.prototype.onattach): 236 (WI.AuditTreeElement.prototype.ondelete): 237 (WI.AuditTreeElement.prototype.canSelectOnMouseDown): Added. 238 (WI.AuditTreeElement.prototype.populateContextMenu): 239 (WI.AuditTreeElement.prototype._handleTestNameChanged): Added. 240 (WI.AuditTreeElement.prototype._handleTestSupportedChanged): Added. 241 (WI.AuditTreeElement.prototype._handleTestGroupTestAdded): Added. 242 * UserInterface/Views/AuditTreeElement.css: 243 (.tree-outline .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active):hover > .status > img): Added. 244 (body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active).selected:hover > .status > img, body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.audit.test-case.selected > .status > .indeterminate-progress-spinner, body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.audit.test-group.selected > .status > progress): Added. 245 (.tree-outline .item.audit:not(:hover) > .status > img.show-on-hover, .tree-outline .item.audit.test-group.expanded:not(.unsupported, .editing-audits):not(:hover) > .status): Added. 246 (.tree-outline .item.audit.manager-active > .status > img.show-on-hover, .tree-outline .item.audit.manager-active > .status > img.show-on-hover, .tree-outline .item.audit.test-group.expanded:not(.editing-audits):hover > .status > :not(img), .tree-outline .item.audit.test-group-result.expanded > .status, .tree-outline .item.audit.unsupported + .children .item.audit.unsupported > .status > img): Added. 247 (@media (prefers-color-scheme: dark) .tree-outline .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active):hover > .status > img): Added. 248 (.tree-outline .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active) > .status:hover > img): Deleted. 249 (.tree-outline .item.audit > .status:not(:hover) > img.show-on-hover, .tree-outline .item.audit.test-group.expanded:not(.unsupported, .editing-audits) > .status:not(:hover)): Deleted. 250 (.tree-outline .item.audit.manager-active > .status > img.show-on-hover, .tree-outline .item.audit.test-group.expanded:not(.editing-audits) > .status:hover > :not(img), .tree-outline .item.audit.test-group-result.expanded > .status, .tree-outline .item.audit.unsupported + .children .item.audit.unsupported > .status > img): Deleted. 251 Add context menu items for duplicating/deleting tests when in edit mode. Adjust the label 252 and disabled state of existing context menu items for clarity. 253 254 * UserInterface/Views/CreateAuditPopover.js: Added. 255 (WI.CreateAuditPopover): 256 (WI.CreateAuditPopover.prototype.get audit): 257 (WI.CreateAuditPopover.prototype.show): 258 (WI.CreateAuditPopover.prototype.dismiss.const.testFunction): 259 (WI.CreateAuditPopover.prototype.dismiss): 260 (WI.CreateAuditPopover.prototype._presentOverTargetElement): 261 * UserInterface/Views/CreateAuditPopover.css: Added. 262 (.popover .create-audit-content): 263 (.popover .create-audit-content > .editor-wrapper): 264 (.popover .create-audit-content > .editor-wrapper > .reference-page-link): 265 New popover for creating an audit: 266 267 [<select> of group or test case] [<input> for name] (?) 268 269 * UserInterface/Views/Main.css: 270 (.navigation-item-help > .navigation-bar): 271 (.message-text-view > .navigation-item-help + .navigation-item-help): Added. 272 Add styles for when multiple navigation help items are used in the same message text view. 273 274 * UserInterface/Views/Variables.css: 275 (:root): 276 (@media (prefers-color-scheme: dark) :root): 277 Add `--filter-invert` to light mode too. 278 279 * UserInterface/Base/Utilities.js: 280 (HTMLInputElement.prototype.autosize): 281 * UserInterface/Views/CanvasOverviewContentView.js: 282 (WI.CanvasOverviewContentView): 283 (WI.CanvasOverviewContentView.prototype._updateRecordingAutoCaptureInputElementSize): 284 (WI.CanvasOverviewContentView.get recordingAutoCaptureInputMargin): Deleted. 285 * UserInterface/Views/CanvasOverviewContentView.css: 286 (.navigation-bar > .item.canvas-recording-auto-capture > label > input): 287 (.navigation-bar > .item.canvas-recording-auto-capture > label > input::-webkit-inner-spin-button): Deleted. 288 Create a helper function for autosizing an `<input>`. 289 290 * UserInterface/Views/AuditTabContentView.js: 291 (WI.AuditTabContentView): 292 (WI.AuditTabContentView.prototype.initialLayout): 293 Remove the back/foward arrows as they can get into an inconsistent state when editing. 294 Drive-by: update the drop zone text for clarity. 295 296 * UserInterface/Views/SearchSidebarPanel.js: 297 (WI.SearchSidebarPanel.prototype.showDefaultContentView): 298 Drive-by: add period to help text. 299 300 * UserInterface/Main.html: 301 * Localizations/en.lproj/localizedStrings.js: 302 1 303 2020-08-27 Carlos Garcia Campos <cgarcia@igalia.com> 2 304 -
trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
r266227 r266317 109 109 localizedStrings["Add New Watch Expression"] = "Add New Watch Expression"; 110 110 localizedStrings["Add Pattern"] = "Add Pattern"; 111 /* Text of button to add a new audit test case to the currently shown audit group. */ 112 localizedStrings["Add Test Case @ Audit Tab - Group"] = "Add Test Case"; 111 113 localizedStrings["Add a Class"] = "Add a Class"; 112 114 localizedStrings["Add new breakpoint action after this action"] = "Add new breakpoint action after this action"; … … 355 357 localizedStrings["Count"] = "Count"; 356 358 localizedStrings["Create %s Rule"] = "Create %s Rule"; 359 /* Title of button that creates a new audit. */ 360 localizedStrings["Create @ Audit Tab Navigation Sidebar"] = "Create"; 357 361 localizedStrings["Create Breakpoint"] = "Create Breakpoint"; 358 362 localizedStrings["Create Local Override"] = "Create Local Override"; 359 363 localizedStrings["Create Resource"] = "Create Resource"; 364 localizedStrings["Create audit:"] = "Create audit:"; 360 365 localizedStrings["Cross-Origin Restrictions"] = "Cross-Origin Restrictions"; 361 366 localizedStrings["Current"] = "Current"; … … 391 396 localizedStrings["Delay"] = "Delay"; 392 397 localizedStrings["Delete"] = "Delete"; 398 localizedStrings["Delete Audit"] = "Delete Audit"; 393 399 localizedStrings["Delete Blackbox"] = "Delete Blackbox"; 394 400 localizedStrings["Delete Breakpoint"] = "Delete Breakpoint"; … … 408 414 localizedStrings["Diagnoses common accessibility problems affecting screen readers and other assistive technology."] = "Diagnoses common accessibility problems affecting screen readers and other assistive technology."; 409 415 localizedStrings["Dimensions"] = "Dimensions"; 416 localizedStrings["Disable Audit"] = "Disable Audit"; 410 417 localizedStrings["Disable Breakpoint"] = "Disable Breakpoint"; 411 418 localizedStrings["Disable Breakpoints"] = "Disable Breakpoints"; … … 441 448 localizedStrings["Dropped Element"] = "Dropped Element"; 442 449 localizedStrings["Dropped Node"] = "Dropped Node"; 450 localizedStrings["Duplicate Audit"] = "Duplicate Audit"; 443 451 localizedStrings["Duplicate Selector"] = "Duplicate Selector"; 444 452 localizedStrings["Duplicate property"] = "Duplicate property"; … … 454 462 localizedStrings["Edit"] = "Edit"; 455 463 localizedStrings["Edit %s"] = "Edit %s"; 464 localizedStrings["Edit Audit"] = "Edit Audit"; 456 465 localizedStrings["Edit Breakpoint\u2026"] = "Edit Breakpoint\u2026"; 457 466 localizedStrings["Edit Local Override\u2026"] = "Edit Local Override\u2026"; … … 461 470 localizedStrings["Edit configuration"] = "Edit configuration"; 462 471 localizedStrings["Edit custom gradient"] = "Edit custom gradient"; 472 /* Title of icon indiciating that the selected audit is being edited. */ 473 localizedStrings["Editing Audit @ Audit Tab - Test Case"] = "Editing audit"; 463 474 localizedStrings["Editing audits"] = "Editing audits"; 464 475 localizedStrings["Element"] = "Element"; … … 495 506 localizedStrings["Elements Tab Name"] = "Elements"; 496 507 localizedStrings["Emulate User Gesture"] = "Emulate User Gesture"; 508 localizedStrings["Enable Audit"] = "Enable Audit"; 497 509 localizedStrings["Enable Breakpoint"] = "Enable Breakpoint"; 498 510 localizedStrings["Enable Breakpoints"] = "Enable Breakpoints"; … … 528 540 localizedStrings["Entire Recording"] = "Entire Recording"; 529 541 localizedStrings["Error"] = "Error"; 542 /* Title of icon indicating that the selected audit threw an error. */ 543 localizedStrings["Error @ Audit Tab - Test Case"] = "Error"; 530 544 localizedStrings["Error: "] = "Error: "; 531 545 localizedStrings["Errors"] = "Errors"; … … 551 565 localizedStrings["Export"] = "Export"; 552 566 localizedStrings["Export (%s)"] = "Export (%s)"; 567 localizedStrings["Export Audit"] = "Export Audit"; 553 568 localizedStrings["Export HAR"] = "Export HAR"; 554 569 localizedStrings["Export Result"] = "Export Result"; 555 localizedStrings["Export Test"] = "Export Test";556 570 localizedStrings["Export recording (%s)"] = "Export recording (%s)"; 557 571 localizedStrings["Export recording (%s)\nShift-click to export a HTML reduction"] = "Export recording (%s)\nShift-click to export a HTML reduction"; 558 localizedStrings["Export result (%s)"] = "Export result (%s)"; 572 /* Tooltip for button that exports the most recent result after running an audit. */ 573 localizedStrings["Export result (%s) @ Audit Tab"] = "Export result (%s)"; 559 574 localizedStrings["Expression"] = "Expression"; 560 575 localizedStrings["Extension Scripts"] = "Extension Scripts"; … … 564 579 localizedStrings["Extra Style Sheets"] = "Extra Style Sheets"; 565 580 localizedStrings["Fade unexecuted code"] = "Fade unexecuted code"; 581 /* Title of icon indicating that the selected audit failed. */ 582 localizedStrings["Fail @ Audit Tab - Test Case"] = "Fail"; 566 583 localizedStrings["Failed to upgrade"] = "Failed to upgrade"; 567 584 localizedStrings["Failure status code"] = "Failure status code"; … … 629 646 localizedStrings["Graphics Tab Name"] = "Graphics"; 630 647 localizedStrings["Group"] = "Group"; 648 /* Dropdown option inside the popover used to creating an audit group. */ 649 localizedStrings["Group @ Audit Tab Navigation Sidebar"] = "Group"; 631 650 localizedStrings["Group By Resource"] = "Group By Resource"; 632 651 localizedStrings["Group Media Requests"] = "Group Media Requests"; … … 682 701 localizedStrings["Immediate Pause Requested"] = "Immediate Pause Requested"; 683 702 localizedStrings["Import"] = "Import"; 684 localizedStrings["Import Audit "] = "Import Audit";703 localizedStrings["Import Audit or Result"] = "Import Audit or Result"; 685 704 localizedStrings["Import HAR"] = "Import HAR"; 686 705 localizedStrings["Import Recording"] = "Import Recording"; 706 localizedStrings["Import audit or result"] = "Import audit or result"; 687 707 localizedStrings["Imported"] = "Imported"; 688 708 localizedStrings["Imported - %s"] = "Imported - %s"; … … 864 884 localizedStrings["None"] = "None"; 865 885 localizedStrings["Not found"] = "Not found"; 886 /* Title of icon indicating that the selected audit has not been run yet. */ 887 localizedStrings["Not yet run @ Audit Tab - Test Case"] = "Not yet run"; 866 888 localizedStrings["Object Graph"] = "Object Graph"; 867 889 localizedStrings["Object Store"] = "Object Store"; … … 910 932 localizedStrings["Parent"] = "Parent"; 911 933 localizedStrings["Partial Garbage Collection"] = "Partial Garbage Collection"; 934 /* Title of icon indicating that the selected audit passed with no issues. */ 935 localizedStrings["Pass @ Audit Tab - Test Case"] = "Pass"; 912 936 localizedStrings["Passive"] = "Passive"; 913 937 localizedStrings["Path"] = "Path"; … … 933 957 localizedStrings["Prefer indent using:"] = "Prefer indent using:"; 934 958 localizedStrings["Preserve Log"] = "Preserve Log"; 935 localizedStrings["Press %s to import a test or result file"] = "Press %s to import a test or result file"; 959 localizedStrings["Press %s to create a new audit."] = "Press %s to create a new audit."; 960 localizedStrings["Press %s to enable audits."] = "Press %s to enable audits."; 961 localizedStrings["Press %s to import an audit or a result."] = "Press %s to import an audit or a result."; 936 962 localizedStrings["Press %s to load a recording from file."] = "Press %s to load a recording from file."; 937 localizedStrings["Press %s to see recent searches"] = "Press %s to see recent searches"; 938 localizedStrings["Press %s to start running the audit"] = "Press %s to start running the audit"; 939 localizedStrings["Press %s to stop editing"] = "Press %s to stop editing"; 963 localizedStrings["Press %s to see recent searches."] = "Press %s to see recent searches."; 964 localizedStrings["Press %s to start editing audits."] = "Press %s to start editing audits."; 965 localizedStrings["Press %s to start running the audit."] = "Press %s to start running the audit."; 966 localizedStrings["Press %s to stop editing audits."] = "Press %s to stop editing audits."; 967 localizedStrings["Press %s to stop running."] = "Press %s to stop running."; 940 968 localizedStrings["Pressed"] = "Pressed"; 941 969 localizedStrings["Pretty print"] = "Pretty print"; … … 1093 1121 localizedStrings["Security Issue"] = "Security Issue"; 1094 1122 localizedStrings["Security Origin"] = "Security Origin"; 1123 localizedStrings["Select an audit in the navigation sidebar to edit it."] = "Select an audit in the navigation sidebar to edit it."; 1124 localizedStrings["Select an audit in the navigation sidebar to view its results."] = "Select an audit in the navigation sidebar to view its results."; 1095 1125 localizedStrings["Select baseline snapshot"] = "Select baseline snapshot"; 1096 1126 localizedStrings["Select comparison snapshot"] = "Select comparison snapshot"; … … 1186 1216 localizedStrings["Stalled"] = "Stalled"; 1187 1217 localizedStrings["Start"] = "Start"; 1218 localizedStrings["Start Audit"] = "Start Audit"; 1188 1219 localizedStrings["Start Time"] = "Start Time"; 1189 1220 localizedStrings["Start element selection (%s)"] = "Start element selection (%s)"; … … 1238 1269 localizedStrings["Target"] = "Target"; 1239 1270 localizedStrings["Template Content"] = "Template Content"; 1271 /* Dropdown option inside the popover used to creating an audit test case. */ 1272 localizedStrings["Test Case @ Audit Tab Navigation Sidebar"] = "Test Case"; 1240 1273 localizedStrings["Text"] = "Text"; 1241 1274 localizedStrings["Text Frame"] = "Text Frame"; … … 1281 1314 localizedStrings["This resource was loaded from the disk cache"] = "This resource was loaded from the disk cache"; 1282 1315 localizedStrings["This resource was loaded from the memory cache"] = "This resource was loaded from the memory cache"; 1316 localizedStrings["This test should not run because it should be unsupported."] = "This test should not run because it should be unsupported."; 1283 1317 localizedStrings["This test will pass with a variety of accessibility information about the <body> element."] = "This test will pass with a variety of accessibility information about the <body> element."; 1284 1318 localizedStrings["This test will pass with all DOM nodes that have a computed role of \u0022link\u0022."] = "This test will pass with all DOM nodes that have a computed role of \u0022link\u0022."; … … 1350 1384 localizedStrings["Unknown error"] = "Unknown error"; 1351 1385 localizedStrings["Unknown node"] = "Unknown node"; 1386 /* Title of icon indicating that the selected audit is not able to be run (i.e. unsupported). */ 1387 localizedStrings["Unsupported @ Audit Tab - Test Case"] = "Unsupported"; 1352 1388 localizedStrings["Unsupported property name"] = "Unsupported property name"; 1353 1389 localizedStrings["Unsupported property value"] = "Unsupported property value"; … … 1386 1422 localizedStrings["Waiting for frames\u2026"] = "Waiting for frames\u2026"; 1387 1423 localizedStrings["Waiting for transitions created by CSS."] = "Waiting for transitions created by CSS."; 1424 /* Title of icon indicating that the selected audit passed with issues (i.e. warnings). */ 1425 localizedStrings["Warn @ Audit Tab - Test Case"] = "Warn"; 1388 1426 localizedStrings["Warning: "] = "Warning: "; 1389 1427 localizedStrings["Warnings"] = "Warnings"; … … 1472 1510 localizedStrings["\u0022%s\u0022 is not JSON serializable"] = "\u0022%s\u0022 is not JSON serializable"; 1473 1511 localizedStrings["\u0022%s\u0022 is not valid for %s"] = "\u0022%s\u0022 is not valid for %s"; 1512 localizedStrings["\u0022%s\u0022 is too new to run in the inspected page"] = "\u0022%s\u0022 is too new to run in the inspected page"; 1474 1513 localizedStrings["\u0022%s\u0022 is too new to run in this Web Inspector"] = "\u0022%s\u0022 is too new to run in this Web Inspector"; 1475 localizedStrings["\u0022%s\u0022 is too new to run on this inspected page"] = "\u0022%s\u0022 is too new to run on this inspected page";1476 1514 localizedStrings["\u0022%s\u0022 must be a %s"] = "\u0022%s\u0022 must be a %s"; 1477 1515 localizedStrings["\u0022%s\u0022 must be an %s"] = "\u0022%s\u0022 must be an %s"; … … 1505 1543 localizedStrings["times before stopping"] = "times before stopping"; 1506 1544 localizedStrings["toggle"] = "toggle"; 1545 /* Warning text shown if the version number in the 'supports' input is too new. */ 1546 localizedStrings["too new to run in the inspected page @ Audit Tab"] = "too new to run in the inspected page"; 1547 /* Warning text shown if the version number in the 'supports' input is too new. */ 1548 localizedStrings["too new to run in this Web Inspector @ Audit Tab"] = "too new to run in this Web Inspector"; 1507 1549 localizedStrings["unknown %s \u0022%s\u0022"] = "unknown %s \u0022%s\u0022"; 1508 1550 localizedStrings["unsupported %s"] = "unsupported %s"; -
trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js
r262806 r266317 485 485 }); 486 486 487 (function() { 488 const fontSymbol = Symbol("font"); 489 490 Object.defineProperty(HTMLInputElement.prototype, "autosize", 491 { 492 value(extra = 0) 493 { 494 extra += 6; // UserAgent styles add 1px padding and 2px border. 495 if (this.type === "number") 496 extra += 13; // Number input inner spin button width. 497 extra += 2; // Add extra pixels for the cursor. 498 499 WI.ImageUtilities.scratchCanvasContext2D((context) => { 500 this[fontSymbol] ||= window.getComputedStyle(this).font; 501 502 context.font = this[fontSymbol]; 503 let textMetrics = context.measureText(this.value || this.placeholder); 504 this.style.setProperty("width", (textMetrics.width + extra) + "px"); 505 }); 506 }, 507 }); 508 })(); 509 487 510 Object.defineProperty(Event.prototype, "stop", 488 511 { -
trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js
r253241 r266317 104 104 let disabledDefaultTests = []; 105 105 let saveDisabledDefaultTest = (test) => { 106 if (test. disabled)106 if (test.supported && test.disabled) 107 107 disabledDefaultTests.push(test.name); 108 108 … … 114 114 115 115 for (let test of this._tests) { 116 if (test. __default)116 if (test.default) 117 117 saveDisabledDefaultTest(test); 118 118 else … … 142 142 143 143 this._runningState = WI.AuditManager.RunningState.Active; 144 this.dispatchEventToListeners(WI.AuditManager.Event.RunningStateChanged); 145 144 146 this._runningTests = tests; 145 147 for (let test of this._runningTests) … … 157 159 await target.AuditAgent.setup(); 158 160 159 let topLevelTest = t his._topLevelTestForTest(test);161 let topLevelTest = test.topLevelTest; 160 162 console.assert(topLevelTest || window.InspectorTest, "No matching top-level test found", test); 161 163 if (topLevelTest) 162 await topLevelTest. setup();164 await topLevelTest.runSetup(); 163 165 164 166 await test.start(); … … 171 173 172 174 this._runningState = WI.AuditManager.RunningState.Inactive; 175 this.dispatchEventToListeners(WI.AuditManager.Event.RunningStateChanged); 176 173 177 this._runningTests = []; 174 178 … … 191 195 192 196 this._runningState = WI.AuditManager.RunningState.Stopping; 197 this.dispatchEventToListeners(WI.AuditManager.Event.RunningStateChanged); 193 198 194 199 for (let test of this._runningTests) … … 219 224 220 225 if (object instanceof WI.AuditTestBase) { 221 this. _addTest(object);226 this.addTest(object); 222 227 WI.objectStores.audits.putObject(object); 223 228 } else if (object instanceof WI.AuditTestResultBase) … … 258 263 WI.objectStores.audits.associateObject(test, key, payload); 259 264 260 this. _addTest(test);265 this.addTest(test); 261 266 } 262 267 }); 263 268 } 264 269 270 addTest(test) 271 { 272 console.assert(test instanceof WI.AuditTestBase, test); 273 console.assert(!this._tests.includes(test), test); 274 275 this._tests.push(test); 276 277 this.dispatchEventToListeners(WI.AuditManager.Event.TestAdded, {test}); 278 } 279 265 280 removeTest(test) 266 281 { 267 if (test.__default) { 282 console.assert(this.editing); 283 console.assert(test instanceof WI.AuditTestBase, test); 284 console.assert(this._tests.includes(test) || test.default, test); 285 286 if (test.default) { 287 test.clearResult(); 288 268 289 if (test.disabled) { 269 290 InspectorFrontendHost.beep(); … … 280 301 } 281 302 303 console.assert(test.editable, test); 304 282 305 this._tests.remove(test); 283 306 … … 288 311 289 312 // Private 290 291 _addTest(test)292 {293 this._tests.push(test);294 295 this.dispatchEventToListeners(WI.AuditManager.Event.TestAdded, {test});296 }297 313 298 314 _addResult(result) … … 307 323 index: this._results.length - 1, 308 324 }); 309 }310 311 _topLevelTestForTest(test)312 {313 function walk(group) {314 if (group === test)315 return true;316 if (group instanceof WI.AuditTestGroup) {317 for (let subtest of group.tests) {318 if (walk(subtest))319 return true;320 }321 }322 return false;323 }324 325 for (let topLevelTest of this._tests) {326 if (walk(topLevelTest))327 return topLevelTest;328 }329 330 return null;331 325 } 332 326 … … 459 453 let mainResource = resources.find((resource) => resource.url === window.location.href); 460 454 return {level: "pass", mainResource, resourceContent: WebInspectorAudit.Resources.getResourceContent(mainResource.id)}; 455 }; 456 457 const unsupported = function() { 458 throw Error("this test should not be supported."); 461 459 }; 462 460 … … 999 997 1000 998 function removeWhitespace(func) { 1001 return func.toString().replace(/\s+/g, " ");999 return WI.AuditTestCase.stringifyFunction(func, 8); 1002 1000 } 1003 1001 … … 1039 1037 ], {description: WI.UIString("These tests demonstrate how to use %s to get information about loaded resources.").format(WI.unlocalizedString("WebInspectorAudit.Resources")), supports: 2}), 1040 1038 ], {description: WI.UIString("These tests demonstrate how to use %s to access information not normally available to JavaScript.").format(WI.unlocalizedString("WebInspectorAudit")), supports: 1}), 1039 new WI.AuditTestCase("unsupported", removeWhitespace(unsupported), {description: WI.UIString("This test should not run because it should be unsupported."), supports: Infinity}), 1041 1040 ], {description: WI.UIString("These tests serve as a demonstration of the functionality and structure of audits.")}), 1042 1041 new WI.AuditTestGroup(WI.UIString("Accessibility"), [ … … 1067 1066 1068 1067 let checkDisabledDefaultTest = (test) => { 1068 test.markAsDefault(); 1069 1069 1070 if (this._disabledDefaultTestsSetting.value.includes(test.name)) 1070 1071 test.disabled = true; … … 1079 1080 checkDisabledDefaultTest(test); 1080 1081 1081 test.__default = true; 1082 this._addTest(test); 1082 this.addTest(test); 1083 1083 } 1084 1084 } … … 1094 1094 WI.AuditManager.Event = { 1095 1095 EditingChanged: "audit-manager-editing-changed", 1096 RunningStateChanged: "audit-manager-running-state-changed", 1096 1097 TestAdded: "audit-manager-test-added", 1097 1098 TestCompleted: "audit-manager-test-completed", -
trunk/Source/WebInspectorUI/UserInterface/Main.html
r266074 r266317 83 83 <link rel="stylesheet" href="Views/CookiePopover.css"> 84 84 <link rel="stylesheet" href="Views/CookieStorageContentView.css"> 85 <link rel="stylesheet" href="Views/CreateAuditPopover.css"> 85 86 <link rel="stylesheet" href="Views/DOMBreakpointTreeElement.css"> 86 87 <link rel="stylesheet" href="Views/DOMEventsBreakdownView.css"> … … 652 653 <script src="Views/CookieStorageContentView.js"></script> 653 654 <script src="Views/CookieStorageTreeElement.js"></script> 655 <script src="Views/CreateAuditPopover.js"></script> 654 656 <script src="Views/DOMBreakpointTreeElement.js"></script> 655 657 <script src="Views/DOMEventsBreakdownView.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestBase.js
r251227 r266317 28 28 constructor(name, {description, supports, setup, disabled} = {}) 29 29 { 30 console.assert(typeof name === "string" );31 console.assert(!description || typeof description === "string" );32 console.assert(supports === undefined || typeof supports === "number" );33 console.assert(!setup || typeof setup === "string" );34 console.assert(disabled === undefined || typeof disabled === "boolean" );30 console.assert(typeof name === "string", name); 31 console.assert(!description || typeof description === "string", description); 32 console.assert(supports === undefined || typeof supports === "number", supports); 33 console.assert(!setup || typeof setup === "string", setup); 34 console.assert(disabled === undefined || typeof disabled === "boolean", disabled); 35 35 36 36 super(); 37 37 38 38 // This class should not be instantiated directly. Create a concrete subclass instead. 39 console.assert(this.constructor !== WI.AuditTestBase && this instanceof WI.AuditTestBase );39 console.assert(this.constructor !== WI.AuditTestBase && this instanceof WI.AuditTestBase, this); 40 40 41 41 this._name = name; 42 this._description = description || null; 43 this._supports = supports; 44 this._setup = setup || null; 45 46 this._supported = true; 47 if (typeof this._supports === "number") { 48 if (this._supports > WI.AuditTestBase.Version) { 49 WI.AuditManager.synthesizeWarning(WI.UIString("\u0022%s\u0022 is too new to run in this Web Inspector").format(this.name)); 50 this._supported = false; 51 } else if (this._supports > InspectorBackend.getVersion("Audit")) { 52 WI.AuditManager.synthesizeWarning(WI.UIString("\u0022%s\u0022 is too new to run on this inspected page").format(this.name)); 53 this._supported = false; 54 } 55 } 56 57 if (!this.supported) 58 disabled = true; 42 this._description = description || ""; 43 this._supports = supports ?? NaN; 44 this._setup = setup || ""; 45 46 this.determineIfSupported({warn: true}); 59 47 60 48 this._runningState = disabled ? WI.AuditManager.RunningState.Disabled : WI.AuditManager.RunningState.Inactive; 61 49 this._result = null; 50 51 this._parent = null; 52 53 this._default = false; 62 54 } 63 55 64 56 // Public 65 57 66 get name() { return this._name; }67 get description() { return this._description; }68 58 get runningState() { return this._runningState; } 69 59 get result() { return this._result; } 70 71 get supported() 72 { 73 return this._supported; 74 } 75 76 set supported(supported) 77 { 78 this._supported = supported; 79 if (!this._supported) 80 this.disabled = true; 60 get supported() { return this._supported; } 61 62 get name() 63 { 64 return this._name; 65 } 66 67 set name(name) 68 { 69 console.assert(this.editable); 70 console.assert(WI.auditManager.editing); 71 console.assert(name && typeof name === "string", name); 72 73 if (name === this._name) 74 return; 75 76 let oldName = this._name; 77 this._name = name; 78 this.dispatchEventToListeners(WI.AuditTestBase.Event.NameChanged, {oldName}); 79 } 80 81 get description() 82 { 83 return this._description; 84 } 85 86 set description(description) 87 { 88 console.assert(this.editable); 89 console.assert(WI.auditManager.editing); 90 console.assert(typeof description === "string", description); 91 92 if (description === this._description) 93 return; 94 95 this._description = description; 96 } 97 98 get supports() 99 { 100 return this._supports; 101 } 102 103 set supports(supports) 104 { 105 console.assert(this.editable); 106 console.assert(WI.auditManager.editing); 107 console.assert(typeof supports === "number", supports); 108 109 if (supports === this._supports) 110 return; 111 112 this._supports = supports; 113 this.determineIfSupported(); 114 } 115 116 get setup() 117 { 118 return this._setup; 119 } 120 121 set setup(setup) 122 { 123 console.assert(this.editable); 124 console.assert(WI.auditManager.editing); 125 console.assert(typeof setup === "string", setup); 126 127 if (setup === this._setup) 128 return; 129 130 this._setup = setup; 131 132 this.clearResult(); 81 133 } 82 134 … … 88 140 set disabled(disabled) 89 141 { 90 console.assert(this._runningState === WI.AuditManager.RunningState.Disabled || this._runningState === WI.AuditManager.RunningState.Inactive); 91 if (this._runningState !== WI.AuditManager.RunningState.Disabled && this._runningState !== WI.AuditManager.RunningState.Inactive) 92 return; 93 94 if (!this.supported) 95 disabled = true; 96 97 let runningState = disabled ? WI.AuditManager.RunningState.Disabled : WI.AuditManager.RunningState.Inactive; 98 if (runningState === this._runningState) 99 return; 100 101 this._runningState = runningState; 102 103 this.dispatchEventToListeners(WI.AuditTestBase.Event.DisabledChanged); 104 } 105 106 async setup() 107 { 142 this.updateDisabled(disabled); 143 } 144 145 get editable() 146 { 147 return !this._default; 148 } 149 150 get default() 151 { 152 return this._default; 153 } 154 155 markAsDefault() 156 { 157 console.assert(!this._default); 158 this._default = true; 159 } 160 161 get topLevelTest() 162 { 163 let test = this; 164 while (test._parent) 165 test = test._parent; 166 return test; 167 } 168 169 async runSetup() 170 { 171 console.assert(this.topLevelTest === this); 172 108 173 if (!this._setup) 109 174 return; … … 149 214 // Called from WI.AuditManager. 150 215 151 if (this.disabled) 152 return; 153 154 console.assert(this.supported); 216 if (!this._supported || this.disabled) 217 return; 155 218 156 219 console.assert(WI.auditManager.runningState === WI.AuditManager.RunningState.Active); … … 172 235 { 173 236 // Called from WI.AuditManager. 174 175 if (this.disabled) 176 return; 177 178 console.assert(this.supported); 237 // Overridden by sub-classes if needed. 238 239 if (!this._supported || this.disabled) 240 return; 179 241 180 242 console.assert(WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping); … … 189 251 clearResult(options = {}) 190 252 { 253 // Overridden by sub-classes if needed. 254 191 255 if (!this._result) 192 256 return false; … … 200 264 } 201 265 266 async clone() 267 { 268 console.assert(WI.auditManager.editing); 269 270 return this.constructor.fromPayload(this.toJSON()); 271 } 272 273 remove() 274 { 275 console.assert(WI.auditManager.editing); 276 277 if (!this._parent || this._default) { 278 WI.auditManager.removeTest(this); 279 return; 280 } 281 282 console.assert(this.editable); 283 console.assert(this._parent instanceof WI.AuditTestGroup); 284 this._parent.removeTest(this); 285 } 286 202 287 saveIdentityToCookie(cookie) 203 288 { 204 cookie["audit-" + this.constructor.TypeIdentifier + "-name"] = this._name; 289 let path = []; 290 let test = this; 291 while (test) { 292 path.push(test.name); 293 test = test._parent; 294 } 295 path.reverse(); 296 297 cookie["audit-path"] = path.join(","); 205 298 } 206 299 207 300 toJSON(key) 208 301 { 302 // Overridden by sub-classes if needed. 303 209 304 let json = { 210 305 type: this.constructor.TypeIdentifier, … … 213 308 if (this._description) 214 309 json.description = this._description; 215 if ( typeof this._supports === "number")216 json.supports = this._supports;310 if (!isNaN(this._supports)) 311 json.supports = Number.isFinite(this._supports) ? this._supports : WI.AuditTestBase.Version + 1; 217 312 if (this._setup) 218 313 json.setup = this._setup; … … 228 323 throw WI.NotImplementedError.subclassMustOverride(); 229 324 } 325 326 determineIfSupported(options = {}) 327 { 328 // Overridden by sub-classes if needed. 329 330 let supportedBefore = this._supported; 331 332 if (this._supports > WI.AuditTestBase.Version) { 333 this.updateSupported(false, options); 334 335 if (options.warn && supportedBefore !== this._supported && Number.isFinite(this._supports)) 336 WI.AuditManager.synthesizeWarning(WI.UIString("\u0022%s\u0022 is too new to run in this Web Inspector").format(this.name)); 337 } else if (InspectorBackend.hasDomain("Audit") && this._supports > InspectorBackend.getVersion("Audit")) { 338 this.updateSupported(false, options); 339 340 if (options.warn && supportedBefore !== this._supported && Number.isFinite(this._supports)) 341 WI.AuditManager.synthesizeWarning(WI.UIString("\u0022%s\u0022 is too new to run in the inspected page").format(this.name)); 342 } else 343 this.updateSupported(true, options); 344 345 return this._supported; 346 } 347 348 updateSupported(supported, options = {}) 349 { 350 // Overridden by sub-classes if needed. 351 352 if (supported === this._supported) 353 return; 354 355 this._supported = supported; 356 357 if (!options.silent) 358 this.dispatchEventToListeners(WI.AuditTestBase.Event.SupportedChanged); 359 360 if (!this._supported) 361 this.clearResult(); 362 } 363 364 updateDisabled(disabled, options = {}) 365 { 366 // Overridden by sub-classes if needed. 367 368 console.assert(this._runningState === WI.AuditManager.RunningState.Disabled || this._runningState === WI.AuditManager.RunningState.Inactive); 369 if (this._runningState !== WI.AuditManager.RunningState.Disabled && this._runningState !== WI.AuditManager.RunningState.Inactive) 370 return; 371 372 let runningState = disabled ? WI.AuditManager.RunningState.Disabled : WI.AuditManager.RunningState.Inactive; 373 if (runningState === this._runningState) 374 return; 375 376 this._runningState = runningState; 377 378 if (!options.silent) 379 this.dispatchEventToListeners(WI.AuditTestBase.Event.DisabledChanged); 380 381 if (this.disabled) 382 this.clearResult(); 383 } 384 385 updateResult(result) 386 { 387 // Overridden by sub-classes if needed. 388 389 console.assert(result instanceof WI.AuditTestResultBase, result); 390 391 this._result = result; 392 393 this.dispatchEventToListeners(WI.AuditTestBase.Event.ResultChanged); 394 } 230 395 }; 231 396 … … 238 403 Completed: "audit-test-base-completed", 239 404 DisabledChanged: "audit-test-base-disabled-changed", 405 NameChanged: "audit-test-base-name-changed", 240 406 Progress: "audit-test-base-progress", 241 407 ResultChanged: "audit-test-base-result-changed", 242 408 Scheduled: "audit-test-base-scheduled", 243 409 Stopping: "audit-test-base-stopping", 410 SupportedChanged: "audit-test-base-supported-changed", 411 TestChanged: "audit-test-base-test-changed", 244 412 }; -
trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js
r251227 r266317 28 28 constructor(name, test, options = {}) 29 29 { 30 console.assert(typeof test === "string" );30 console.assert(typeof test === "string", test); 31 31 32 32 super(name, options); … … 78 78 } 79 79 80 static stringifyFunction(func, indentLevel) 81 { 82 let string = func.toString(); 83 84 // Remove spaces to make the function look unindented. 85 string = string.replaceAll(new RegExp(`^ {${indentLevel}}`, "gm"), ""); 86 87 // Replace remaining indentations with the user set indent string. 88 string = string.replaceAll(/^ /gm, WI.indentString()); 89 90 return string; 91 } 92 80 93 // Public 81 94 82 get test() { return this._test; } 95 get test() 96 { 97 return this._test; 98 } 99 100 set test(test) 101 { 102 console.assert(this.editable); 103 console.assert(WI.auditManager.editing); 104 console.assert(typeof test === "string", test); 105 106 if (test === this._test) 107 return; 108 109 this._test = test; 110 111 this.clearResult(); 112 113 this.dispatchEventToListeners(WI.AuditTestBase.Event.TestChanged); 114 } 83 115 84 116 toJSON(key) … … 344 376 if (resolvedDOMNodes) 345 377 options.resolvedDOMNodes = resolvedDOMNodes; 346 this._result = new WI.AuditTestCaseResult(this.name, level, options); 347 348 this.dispatchEventToListeners(WI.AuditTestBase.Event.ResultChanged); 378 this.updateResult(new WI.AuditTestCaseResult(this.name, level, options)); 349 379 } 350 380 }; -
trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestGroup.js
r245914 r266317 28 28 constructor(name, tests, options = {}) 29 29 { 30 console.assert(Array.isArray(tests) );30 console.assert(Array.isArray(tests), tests); 31 31 32 32 // Set disabled once `_tests` is set so that it propagates. … … 36 36 super(name, options); 37 37 38 this._tests = tests; 39 this._preventDisabledPropagation = false; 40 41 if (disabled || !this.supported) 42 this.disabled = true; 43 44 let hasSupportedTest = false; 45 46 for (let test of this._tests) { 47 if (!this.supported) 48 test.supported = false; 49 else if (test.supported) 50 hasSupportedTest = true; 51 52 test.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCompleted, this); 53 test.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this); 54 test.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestProgress, this); 55 56 } 57 58 if (!hasSupportedTest) 59 this.supported = false; 38 this._tests = []; 39 for (let test of tests) 40 this.addTest(test); 41 42 if (disabled) 43 this.updateDisabled(true); 60 44 } 61 45 … … 122 106 get tests() { return this._tests; } 123 107 124 get supported() 125 { 126 return super.supported; 127 } 128 129 set supported(supported) 130 { 131 for (let test of this._tests) 132 test.supported = supported; 133 134 super.supported = supported; 135 } 136 137 get disabled() 138 { 139 return super.disabled; 140 } 141 142 set disabled(disabled) 143 { 144 if (!this._preventDisabledPropagation) { 145 for (let test of this._tests) 146 test.disabled = disabled; 147 } 148 149 super.disabled = disabled; 108 addTest(test) 109 { 110 console.assert(test instanceof WI.AuditTestBase, test); 111 console.assert(!this._tests.includes(test), test); 112 console.assert(!test._parent, test); 113 114 this._tests.push(test); 115 test._parent = this; 116 117 test.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCompleted, this); 118 test.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this); 119 test.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestProgress, this); 120 if (this.editable) { 121 test.addEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this); 122 test.addEventListener(WI.AuditTestBase.Event.TestChanged, this._handleTestChanged, this); 123 } 124 125 this.dispatchEventToListeners(WI.AuditTestGroup.Event.TestAdded, {test}); 126 127 this.determineIfSupported(); 128 129 if (this._checkDisabled(test)) 130 test.updateDisabled(true, {silent: true}); 131 } 132 133 removeTest(test) 134 { 135 console.assert(this.editable); 136 console.assert(WI.auditManager.editing); 137 console.assert(test instanceof WI.AuditTestBase, test); 138 console.assert(test.editable, test); 139 console.assert(this._tests.includes(test), test); 140 console.assert(test._parent === this, test); 141 142 test.removeEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCompleted, this); 143 test.removeEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this); 144 test.removeEventListener(WI.AuditTestBase.Event.Progress, this._handleTestProgress, this); 145 test.removeEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this); 146 test.removeEventListener(WI.AuditTestBase.Event.TestChanged, this._handleTestChanged, this); 147 148 this._tests.remove(test); 149 test._parent = null; 150 151 this.dispatchEventToListeners(WI.AuditTestGroup.Event.TestRemoved, {test}); 152 153 this.determineIfSupported(); 154 155 this._checkDisabled(); 150 156 } 151 157 … … 162 168 clearResult(options = {}) 163 169 { 164 let cleared = !!this._result; 165 for (let test of this._tests) { 166 if (test.clearResult(options)) 167 cleared = true; 170 let cleared = !!this.result; 171 172 if (!options.excludeTests && this._tests) { 173 for (let test of this._tests) { 174 if (test.clearResult(options)) 175 cleared = true; 176 } 168 177 } 169 178 … … 188 197 for (let index = 0; index < count && this._runningState === WI.AuditManager.RunningState.Active; ++index) { 189 198 let test = this._tests[index]; 190 if (test.disabled )199 if (test.disabled || !test.supported) 191 200 continue; 192 201 … … 197 206 } 198 207 199 this._updateResult(); 200 } 201 202 // Private 203 204 _updateResult() 208 this.updateResult(); 209 } 210 211 determineIfSupported(options = {}) 212 { 213 if (this._tests) { 214 for (let test of this._tests) 215 test.determineIfSupported({...options, warn: false, silent: true}); 216 } 217 218 return super.determineIfSupported(options); 219 } 220 221 updateSupported(supported, options = {}) 222 { 223 if (this._tests && (!supported || this._tests.every((test) => !test.supported))) { 224 supported = false; 225 226 for (let test of this._tests) 227 test.updateSupported(supported, {silent: true}); 228 } 229 230 super.updateSupported(supported, options); 231 } 232 233 updateDisabled(disabled, options = {}) 234 { 235 if (!options.excludeTests && this._tests) { 236 for (let test of this._tests) 237 test.updateDisabled(disabled, options); 238 } 239 240 super.updateDisabled(disabled, options); 241 } 242 243 updateResult() 205 244 { 206 245 let results = this._tests.map((test) => test.result).filter((result) => !!result); … … 208 247 return; 209 248 210 this._result =new WI.AuditTestGroupResult(this.name, results, {249 super.updateResult(new WI.AuditTestGroupResult(this.name, results, { 211 250 description: this.description, 212 }); 213 214 this.dispatchEventToListeners(WI.AuditTestBase.Event.ResultChanged); 251 })); 252 } 253 254 // Private 255 256 _checkDisabled(test) 257 { 258 let testDisabled = !test || !test.supported || test.disabled; 259 let enabledTestCount = this._tests.filter((existing) => existing.supported && !existing.disabled).length; 260 261 if (testDisabled && !enabledTestCount) 262 this.updateDisabled(true); 263 else if (!testDisabled && enabledTestCount === 1) 264 this.updateDisabled(false, {excludeTests: true}); 265 else { 266 // Don't change `disabled`, as we're currently in an "indeterminate" state. 267 this.dispatchEventToListeners(WI.AuditTestBase.Event.DisabledChanged); 268 } 269 270 return this.disabled; 215 271 } 216 272 … … 220 276 return; 221 277 222 this._updateResult(); 278 this.updateResult(); 279 223 280 this.dispatchEventToListeners(WI.AuditTestBase.Event.Completed); 224 281 } … … 226 283 _handleTestDisabledChanged(event) 227 284 { 228 let enabledTestCount = this._tests.filter((test) => !test.disabled).length; 229 if (event.target.disabled && !enabledTestCount) 230 this.disabled = true; 231 else if (!event.target.disabled && enabledTestCount === 1) { 232 this._preventDisabledPropagation = true; 233 this.disabled = false; 234 this._preventDisabledPropagation = false; 235 } else { 236 // Don't change `disabled`, as we're currently in an "indeterminate" state. 237 this.dispatchEventToListeners(WI.AuditTestBase.Event.DisabledChanged); 238 } 285 this._checkDisabled(event.target); 239 286 } 240 287 … … 247 294 let count = 0; 248 295 for (let test of tests) { 249 if (test.disabled )296 if (test.disabled || !test.supported) 250 297 continue; 251 298 … … 263 310 }); 264 311 } 312 313 _handleTestSupportedChanged(event) 314 { 315 this.determineIfSupported(); 316 } 317 318 _handleTestChanged(event) 319 { 320 console.assert(WI.auditManager.editing); 321 322 this.clearResult({excludeTests: true}); 323 324 this.dispatchEventToListeners(WI.AuditTestBase.Event.TestChanged); 325 } 265 326 }; 266 327 267 328 WI.AuditTestGroup.TypeIdentifier = "test-group"; 329 330 WI.AuditTestGroup.Event = { 331 TestAdded: "audit-test-group-test-added", 332 TestRemoved: "audit-test-group-test-removed", 333 }; -
trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestResultBase.js
r237613 r266317 70 70 } 71 71 72 get disabled() 73 { 74 return false; 75 } 76 77 get editable() 78 { 79 return false; 80 } 81 72 82 saveIdentityToCookie(cookie) 73 83 { -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.css
r244039 r266317 34 34 } 35 35 36 .sidebar > .panel.navigation.audit > .content.edit-audits:not(.disabled):active {36 .sidebar > .panel.navigation.audit .edit-audits:not(.disabled):active { 37 37 color: var(--glyph-color-pressed); 38 38 } 39 39 40 .sidebar > .panel.navigation.audit > .content.edit-audits:not(.disabled).activated {40 .sidebar > .panel.navigation.audit .edit-audits:not(.disabled).activated { 41 41 color: var(--glyph-color-active); 42 42 } 43 43 44 .sidebar > .panel.navigation.audit > .content.edit-audits:not(.disabled).activated:active {44 .sidebar > .panel.navigation.audit .edit-audits:not(.disabled).activated:active { 45 45 color: var(--glyph-color-active-pressed); 46 46 } 47 47 48 .sidebar > .panel.navigation.audit > .content.edit-audits.disabled {48 .sidebar > .panel.navigation.audit .edit-audits.disabled { 49 49 color: var(--glyph-color-disabled); 50 50 } … … 59 59 } 60 60 61 .finish-editing-audits-placeholder.message-text-view .navigation-item-help .navigation-bar { 62 padding: 0; 63 vertical-align: 0.5px; 61 .content-view.audit .message-text-view .navigation-item-help:is(.start-editing-audits, .stop-editing-audits) .navigation-bar { 62 --navigation-item-help-navigation-bar-vertical-align: 0.5px; 64 63 } 65 64 66 . audit-version {65 .content-view.tab.audit .content-view > .audit-version { 67 66 position: absolute; 68 67 right: 0; … … 75 74 color: var(--text-color-secondary); 76 75 } 76 77 .content-view.tab.audit .content-view .reference-page-link-container { 78 position: absolute; 79 bottom: 4px; 80 } 81 82 body[dir=ltr] .content-view.tab.audit .content-view .reference-page-link-container { 83 right: 4px; 84 } 85 86 body[dir=rtl] .content-view.tab.audit .content-view .reference-page-link-container { 87 left: 4px; 88 } -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.js
r258246 r266317 31 31 } 32 32 33 // Static 34 35 static _createNavigationItemTitle() 36 { 37 return WI.UIString("Create", "Create @ Audit Tab Navigation Sidebar", "Title of button that creates a new audit."); 38 } 39 33 40 // Public 34 41 … … 39 46 if (WI.auditManager.editing) { 40 47 let contentPlaceholder = WI.createMessageTextView(WI.UIString("Editing audits")); 41 contentPlaceholder.classList.add("finish-editing-audits-placeholder");42 48 contentView.element.appendChild(contentPlaceholder); 43 49 44 let finishEditingNavigationItem = new WI.ButtonNavigationItem("finish-editing-audits", WI.UIString("Done")); 45 finishEditingNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, (event) => { 46 WI.auditManager.editing = false; 47 }); 48 49 let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop editing"), finishEditingNavigationItem); 50 contentPlaceholder.appendChild(importHelpElement); 50 let descriptionElement = contentPlaceholder.appendChild(document.createElement("div")); 51 descriptionElement.className = "description"; 52 descriptionElement.textContent = WI.UIString("Select an audit in the navigation sidebar to edit it."); 53 54 let createAuditNavigationItem = new WI.ButtonNavigationItem("create-audit", WI.AuditNavigationSidebarPanel._createNavigationItemTitle(), "Images/Plus15.svg", 15, 15); 55 createAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 56 createAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateButtonNavigationItemClicked, this); 57 58 let createAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to create a new audit."), createAuditNavigationItem); 59 createAuditHelpElement.classList.add("create-audit"); 60 contentPlaceholder.appendChild(createAuditHelpElement); 61 62 let stopEditingAuditsNavigationItem = new WI.ButtonNavigationItem("stop-editing-audits", WI.UIString("Done")); 63 stopEditingAuditsNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this); 64 65 let stopEditingAuditsHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop editing audits."), stopEditingAuditsNavigationItem); 66 stopEditingAuditsHelpElement.classList.add("stop-editing-audits"); 67 contentPlaceholder.appendChild(stopEditingAuditsHelpElement); 51 68 } else { 69 let hasEnabledAudit = WI.auditManager.tests.length && WI.auditManager.tests.some((test) => !test.disabled && test.supported); 70 52 71 let contentPlaceholder = WI.createMessageTextView(WI.UIString("No audit selected")); 53 72 contentView.element.appendChild(contentPlaceholder); 54 73 55 let importNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15); 56 importNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 57 importNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this); 58 59 let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to import a test or result file"), importNavigationItem); 60 contentPlaceholder.appendChild(importHelpElement); 74 if (hasEnabledAudit) { 75 let descriptionElement = contentPlaceholder.appendChild(document.createElement("div")); 76 descriptionElement.className = "description"; 77 descriptionElement.textContent = WI.UIString("Select an audit in the navigation sidebar to view its results."); 78 } 79 80 let importAuditNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15); 81 importAuditNavigationItem.title = WI.UIString("Import audit or result"); 82 importAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 83 importAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this); 84 85 let importAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to import an audit or a result."), importAuditNavigationItem); 86 importAuditHelpElement.classList.add("import-audit"); 87 contentPlaceholder.appendChild(importAuditHelpElement); 88 89 let startEditingAuditsNavigationItem = new WI.ButtonNavigationItem("start-editing-audits", WI.UIString("Edit")); 90 startEditingAuditsNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this); 91 92 let startEditingAuditsHelpElement = WI.createNavigationItemHelp(hasEnabledAudit ? WI.UIString("Press %s to start editing audits.") : WI.UIString("Press %s to enable audits."), startEditingAuditsNavigationItem); 93 startEditingAuditsHelpElement.classList.add("start-editing-audits"); 94 contentPlaceholder.appendChild(startEditingAuditsHelpElement); 61 95 } 62 96 … … 69 103 versionContainer.textContent = WI.UIString("Audit version: %s").format(version); 70 104 105 versionContainer.appendChild(WI.createReferencePageLink("audit-tab")); 106 71 107 this.contentBrowser.showContentView(contentView); 72 108 } 73 109 110 // Popover delegate 111 112 willDismissPopover(popover) 113 { 114 console.assert(popover instanceof WI.CreateAuditPopover, popover); 115 116 let audit = popover.audit; 117 if (!audit) { 118 InspectorFrontendHost.beep(); 119 return; 120 } 121 122 WI.auditManager.addTest(audit); 123 124 WI.showRepresentedObject(audit); 125 } 126 74 127 // Protected 75 128 … … 82 135 let controlsNavigationBar = new WI.NavigationBar; 83 136 84 this._startStopButtonNavigationItem = new WI.ToggleButtonNavigationItem(" audit-start-stop", WI.UIString("Start"), WI.UIString("Stop"), "Images/AuditStart.svg", "Images/AuditStop.svg", 13, 13);137 this._startStopButtonNavigationItem = new WI.ToggleButtonNavigationItem("start-stop-audit", WI.UIString("Start"), WI.UIString("Stop"), "Images/AuditStart.svg", "Images/AuditStop.svg", 13, 13); 85 138 this._startStopButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 86 this._updateStartStopButtonNavigationItemState();87 139 this._startStopButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleStartStopButtonNavigationItemClicked, this); 88 140 controlsNavigationBar.addNavigationItem(this._startStopButtonNavigationItem); 89 141 142 this._createButtonNavigationItem = new WI.ButtonNavigationItem("create-audit", WI.AuditNavigationSidebarPanel._createNavigationItemTitle(), "Images/Plus15.svg", 15, 15); 143 this._createButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 144 this._createButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateButtonNavigationItemClicked, this); 145 controlsNavigationBar.addNavigationItem(this._createButtonNavigationItem); 146 90 147 controlsNavigationBar.addNavigationItem(new WI.DividerNavigationItem); 91 148 92 let importButtonNavigationItem = new WI.ButtonNavigationItem("audit-import", WI.UIString("Import"), "Images/Import.svg", 15, 15); 149 let importButtonNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15); 150 importButtonNavigationItem.title = WI.UIString("Import audit or result"); 93 151 importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 94 importButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;95 152 importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this); 96 153 controlsNavigationBar.addNavigationItem(importButtonNavigationItem); … … 98 155 this.addSubview(controlsNavigationBar); 99 156 100 let editNavigationbar = new WI.NavigationBar;101 102 157 this._editButtonNavigationItem = new WI.ActivateButtonNavigationItem("edit-audits", WI.UIString("Edit"), WI.UIString("Done")); 103 158 this._editButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this); 104 editNavigationbar.addNavigationItem(this._editButtonNavigationItem); 105 106 this.contentView.addSubview(editNavigationbar); 159 this.filterBar.addFilterNavigationItem(this._editButtonNavigationItem); 107 160 108 161 for (let test of WI.auditManager.tests) … … 113 166 }); 114 167 168 this._updateControlNavigationItems(); 169 this._updateEditNavigationItems(); 170 this._updateNoAuditsPlaceholder(); 171 172 WI.AuditTestGroup.addEventListener(WI.AuditTestGroup.Event.TestRemoved, this._handleAuditTestRemoved, this); 173 115 174 WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleAuditManagerEditingChanged, this); 175 WI.auditManager.addEventListener(WI.AuditManager.Event.RunningStateChanged, this._handleAuditManagerRunningStateChanged, this); 116 176 WI.auditManager.addEventListener(WI.AuditManager.Event.TestAdded, this._handleAuditTestAdded, this); 117 177 WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditTestCompleted, this); … … 148 208 return false; 149 209 } else { 150 if (treeElement.representedObject instanceof WI.AuditTestBase && treeElement.representedObject.disabled)210 if (treeElement.representedObject instanceof WI.AuditTestBase && (treeElement.representedObject.disabled || !treeElement.representedObject.supported)) 151 211 return false; 152 212 } … … 166 226 } else 167 227 this.contentTreeOutline.appendChild(treeElement); 168 169 this._updateStartStopButtonNavigationItemState();170 this._updateEditButtonNavigationItemState();171 this._updateNoAuditsPlaceholder();172 228 } 173 229 … … 194 250 for (let resultItem of result) 195 251 resultFolderTreeElement.appendChild(new WI.AuditTreeElement(resultItem)); 196 197 this._updateStartStopButtonNavigationItemState(); 198 this._updateEditButtonNavigationItemState(); 199 } 200 201 _updateStartStopButtonNavigationItemState() 252 } 253 254 _updateControlNavigationItems() 202 255 { 203 256 this._startStopButtonNavigationItem.toggled = WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping; 204 this._startStopButtonNavigationItem.enabled = WI.auditManager.tests.some((test) => !test.disabled) && (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive || WI.auditManager.runningState === WI.AuditManager.RunningState.Active); 205 } 206 207 _updateEditButtonNavigationItemState() 257 this._startStopButtonNavigationItem.enabled = WI.auditManager.tests.some((test) => !test.disabled && test.supported) && (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive || WI.auditManager.runningState === WI.AuditManager.RunningState.Active); 258 this._startStopButtonNavigationItem.hidden = WI.auditManager.editing; 259 260 this._createButtonNavigationItem.hidden = !WI.auditManager.editing; 261 } 262 263 _updateEditNavigationItems() 208 264 { 209 265 this._editButtonNavigationItem.label = WI.auditManager.editing ? this._editButtonNavigationItem.activatedToolTip : this._editButtonNavigationItem.defaultToolTip; 210 266 this._editButtonNavigationItem.activated = WI.auditManager.editing; 211 this._editButtonNavigationItem.enabled = WI.auditManager. tests.length && (WI.auditManager.editing || WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive);267 this._editButtonNavigationItem.enabled = WI.auditManager.editing || WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive; 212 268 } 213 269 214 270 _updateNoAuditsPlaceholder() 215 271 { 216 if (WI.auditManager.editing || WI.auditManager.tests.some((test) => !test.disabled )) {272 if (WI.auditManager.editing || WI.auditManager.tests.some((test) => !test.disabled && test.supported)) { 217 273 if (!this.hasActiveFilters) 218 274 this.hideEmptyContentPlaceholder(); … … 232 288 _handleAuditManagerEditingChanged(event) 233 289 { 234 if (WI.auditManager.editing) { 235 console.assert(!this._selectedTreeElementBeforeEditing); 236 this._selectedTreeElementBeforeEditing = this.contentTreeOutline.selectedTreeElement; 237 if (this._selectedTreeElementBeforeEditing) 238 this._selectedTreeElementBeforeEditing.deselect(); 239 } else if (this._selectedTreeElementBeforeEditing) { 240 if (this.contentTreeOutline.selectedTreeElement === this._selectedTreeElementBeforeEditing) { 241 const suppressNotification = true; 242 this._selectedTreeElementBeforeEditing.deselect(suppressNotification); 290 let previousSelectedTreeElement = this.contentTreeOutline.selectedTreeElement; 291 if (previousSelectedTreeElement) { 292 if (WI.auditManager.editing) { 293 if (!(previousSelectedTreeElement.representedObject instanceof WI.AuditTestBase)) 294 previousSelectedTreeElement.deselect(); 295 } else { 296 if (previousSelectedTreeElement.representedObject.disabled || !previousSelectedTreeElement.representedObject.supported) 297 previousSelectedTreeElement.deselect(); 243 298 } 244 if (!(this._selectedTreeElementBeforeEditing.representedObject instanceof WI.AuditTestBase) || !this._selectedTreeElementBeforeEditing.representedObject.disabled) { 245 const omitFocus = false; 246 const selectedByUser = true; 247 this._selectedTreeElementBeforeEditing.select(omitFocus, selectedByUser); 248 } 249 this._selectedTreeElementBeforeEditing = null; 250 } 299 } 300 301 this.updateFilter(); 251 302 252 303 if (!this.contentTreeOutline.selectedTreeElement) 253 304 this.showDefaultContentView(); 254 305 255 this._updateStartStopButtonNavigationItemState(); 256 this._updateEditButtonNavigationItemState(); 257 258 this.updateFilter(); 306 this._updateControlNavigationItems(); 307 this._updateEditNavigationItems(); 308 this._updateNoAuditsPlaceholder(); 309 } 310 311 _handleAuditManagerRunningStateChanged(event) 312 { 313 this._updateControlNavigationItems(); 314 this._updateEditNavigationItems(); 259 315 } 260 316 261 317 _handleAuditTestAdded(event) 262 318 { 263 this._addTest(event.data.test); 319 let {test} = event.data; 320 321 this._addTest(test); 322 323 this._updateControlNavigationItems(); 324 this._updateNoAuditsPlaceholder(); 264 325 } 265 326 … … 268 329 let {result, index} = event.data; 269 330 this._addResult(result, index); 331 332 this._updateControlNavigationItems(); 333 this._updateEditNavigationItems(); 270 334 } 271 335 272 336 _handleAuditTestRemoved(event) 273 337 { 338 console.assert(WI.auditManager.editing); 339 274 340 let {test} = event.data; 341 275 342 let treeElement = this.treeElementForRepresentedObject(test); 276 this.contentTreeOutline.removeChild(treeElement); 277 278 this._updateStartStopButtonNavigationItemState(); 279 this._updateEditButtonNavigationItemState(); 280 this._updateNoAuditsPlaceholder(); 343 treeElement.parent.removeChild(treeElement); 344 345 this._updateControlNavigationItems(); 281 346 } 282 347 283 348 _handleAuditTestScheduled(event) 284 349 { 285 this._update StartStopButtonNavigationItemState();286 this._updateEdit ButtonNavigationItemState();350 this._updateControlNavigationItems(); 351 this._updateEditNavigationItems(); 287 352 } 288 353 … … 297 362 return; 298 363 } 299 300 if (WI.auditManager.editing)301 return;302 364 303 365 let representedObject = treeElement.representedObject; … … 317 379 else if (WI.auditManager.runningState === WI.AuditManager.RunningState.Active) 318 380 WI.auditManager.stop(); 319 320 this._updateStartStopButtonNavigationItemState(); 381 } 382 383 _handleCreateButtonNavigationItemClicked(event) 384 { 385 console.assert(WI.auditManager.editing); 386 387 let popover = new WI.CreateAuditPopover(this); 388 popover.show(event.target.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MAX_X, WI.RectEdge.MIN_X]); 321 389 } 322 390 -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTabContentView.js
r265707 r266317 30 30 super(AuditTabContentView.tabInfo(), { 31 31 navigationSidebarPanelConstructor: WI.AuditNavigationSidebarPanel, 32 disableBackForward: true, 32 33 }); 33 34 … … 112 113 113 114 let dropZoneView = new WI.DropZoneView(this); 114 dropZoneView.text = WI.UIString("Import Audit ");115 dropZoneView.text = WI.UIString("Import Audit or Result"); 115 116 dropZoneView.targetElement = this.element; 116 117 this.addSubview(dropZoneView); -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestCaseContentView.css
r245914 r266317 24 24 */ 25 25 26 .content-view-container > .content-view.audit-test-case { 27 display: flex; 28 flex-direction: column; 29 height: 100%; 30 overflow: hidden; 31 } 32 26 33 .content-view-container > .content-view.audit-test-case > header { 34 flex-shrink: 0; 27 35 position: sticky; 28 top: -1px;36 top: 0; 29 37 z-index: var(--z-index-header); 30 margin-top: -1px;31 38 background-color: var(--audit-test-header-background-color); 32 border-top: 1px solid var(--border-color);33 39 -webkit-backdrop-filter: blur(20px); 34 40 } 35 41 36 .content-view-container > .content-view.audit-test-case > section > :not(.message-text-view):first-child { 42 .content-view-container > .content-view.audit-test-case.manager-editing > header h1 > img { 43 width: 0.75em; 44 min-width: 12px; 45 height: 0.75em; 46 min-height: 12px; 47 margin: 0.125em; 48 margin-inline-end: 0.375em; 49 } 50 51 .content-view-container > .content-view.audit-test-case > section > :not(.message-text-view, .editor):first-child { 37 52 margin-top: var(--audit-test-vertical-space); 53 } 54 55 .content-view-container > .content-view.audit-test-case > section { 56 overflow-y: scroll; 57 } 58 59 .content-view-container > .content-view.audit-test-case > section, 60 .content-view-container > .content-view.audit-test-case > section :is(.editor, .CodeMirror) { 61 height: 100%; 38 62 } 39 63 … … 53 77 min-height: 16px; 54 78 -webkit-margin-end: 0.25em; 79 } 80 81 .content-view.audit-test-case.manager-editing.disabled:not(.editable) > header h1 > img { 82 opacity: 0.3; 83 pointer-events: none; 55 84 } 56 85 … … 84 113 } 85 114 86 .content-view.audit-test-case > section > :not(.message-text-view ) {115 .content-view.audit-test-case > section > :not(.message-text-view, .editor) { 87 116 margin-right: var(--audit-test-horizontal-space); 88 117 margin-left: var(--audit-test-horizontal-space); 89 118 } 90 119 91 .content-view.audit-test-case > section > :not(.message-text-view ):last-child {120 .content-view.audit-test-case > section > :not(.message-text-view, .editor):last-child { 92 121 margin-bottom: var(--audit-test-vertical-space); 93 122 } 94 123 95 .content-view.audit-test-case > section > :not(.message-text-view ) + :not(.message-text-view) {124 .content-view.audit-test-case > section > :not(.message-text-view, .editor) + :not(.message-text-view, .editor) { 96 125 margin-top: var(--audit-test-vertical-space); 97 126 } … … 132 161 } 133 162 134 .content-view.audit-test-case > section .CodeMirror {135 width: 100%;136 height: auto;137 }138 139 163 .content-view.audit-test-case > section .mark { 140 164 background-color: hsla(53, 83%, 53%, 0.2); 141 165 border-bottom: 1px solid hsl(47, 82%, 60%); 142 166 } 167 168 @media (prefers-color-scheme: dark) { 169 .content-view.audit-test-case.manager-editing > header h1 > img { 170 filter: var(--filter-invert); 171 } 172 } -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestCaseContentView.js
r253757 r266317 48 48 informationContainer.classList.add("information"); 49 49 50 let name Element= informationContainer.appendChild(document.createElement("h1"));51 52 this._resultImageElement = name Element.appendChild(document.createElement("img"));53 54 name Element.appendChild(document.createTextNode(this.representedObject.name));55 56 i f (this.representedObject.description) {57 let descriptionElement = informationContainer.appendChild(document.createElement("p")); 58 descriptionElement.textContent = this.representedObject.description;59 }50 let nameContainer = informationContainer.appendChild(document.createElement("h1")); 51 52 this._resultImageElement = nameContainer.appendChild(document.createElement("img")); 53 54 nameContainer.appendChild(this.createNameElement("span")); 55 56 informationContainer.appendChild(this.createDescriptionElement("p")); 57 58 if (this.representedObject instanceof WI.AuditTestCase) 59 informationContainer.appendChild(this.createControlsTableElement()); 60 60 61 61 this._metadataElement = this.headerView.element.appendChild(document.createElement("div")); … … 70 70 super.layout(); 71 71 72 this._metadataElement.removeChildren(); 73 this.contentView.element.removeChildren(); 74 75 if (WI.auditManager.editing) { 76 this._resultImageElement.src = "Images/Pencil.svg"; 77 this._resultImageElement.title = WI.UIString("Editing audit", "Editing Audit @ Audit Tab - Test Case", "Title of icon indiciating that the selected audit is being edited."); 78 79 let testEditorElement = this.contentView.element.appendChild(document.createElement("div")); 80 testEditorElement.className = "editor"; 81 82 // Give the rest of the view a chance to load. 83 setTimeout(() => { 84 let testCodeMirror = WI.CodeMirrorEditor.create(testEditorElement, { 85 autoCloseBrackets: true, 86 lineNumbers: true, 87 lineWrapping: true, 88 matchBrackets: true, 89 mode: "text/javascript", 90 readOnly: this.representedObject.editable ? false : "nocursor", 91 styleSelectedText: true, 92 value: this.representedObject.test, 93 }); 94 95 if (this.representedObject.editable) { 96 testCodeMirror.on("blur", (event) => { 97 this.representedObject.test = testCodeMirror.getValue().trim(); 98 }); 99 } 100 }); 101 return; 102 } 103 72 104 this._resultImageElement.src = "Images/AuditTestNoResult.svg"; 73 this._metadataElement.removeChildren(); 74 75 this.contentView.element.removeChildren(); 105 this._resultImageElement.title = WI.UIString("Not yet run", "Not yet run @ Audit Tab - Test Case", "Title of icon indicating that the selected audit has not been run yet."); 76 106 77 107 let result = this.representedObject.result; … … 87 117 } 88 118 89 if (result.didError) 119 if (result.didError) { 90 120 this._resultImageElement.src = "Images/AuditTestError.svg"; 91 else if (result.didFail) 121 this._resultImageElement.title = WI.UIString("Error", "Error @ Audit Tab - Test Case", "Title of icon indicating that the selected audit threw an error."); 122 } else if (result.didFail) { 92 123 this._resultImageElement.src = "Images/AuditTestFail.svg"; 93 else if (result.didWarn) 124 this._resultImageElement.title = WI.UIString("Fail", "Fail @ Audit Tab - Test Case", "Title of icon indicating that the selected audit failed."); 125 } else if (result.didWarn) { 94 126 this._resultImageElement.src = "Images/AuditTestWarn.svg"; 95 else if (result.didPass) 127 this._resultImageElement.title = WI.UIString("Warn", "Warn @ Audit Tab - Test Case", "Title of icon indicating that the selected audit passed with issues (i.e. warnings)."); 128 } else if (result.didPass) { 96 129 this._resultImageElement.src = "Images/AuditTestPass.svg"; 97 else if (result.unsupported) 130 this._resultImageElement.title = WI.UIString("Pass", "Pass @ Audit Tab - Test Case", "Title of icon indicating that the selected audit passed with no issues."); 131 } else if (result.unsupported) { 98 132 this._resultImageElement.src = "Images/AuditTestUnsupported.svg"; 133 this._resultImageElement.title = WI.UIString("Unsupported", "Unsupported @ Audit Tab - Test Case", "Title of icon indicating that the selected audit is not able to be run (i.e. unsupported)."); 134 } 99 135 100 136 let metadata = result.metadata; … … 300 336 let spinner = new WI.IndeterminateProgressSpinner; 301 337 this.placeholderElement.appendChild(spinner.element); 338 339 let stopAuditNavigationItem = new WI.ButtonNavigationItem("stop-audit", WI.UIString("Stop"), "Images/AuditStop.svg", 13, 13); 340 stopAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 341 stopAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, (event) => { 342 WI.auditManager.stop(); 343 }, WI.auditManager); 344 345 let stopAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop running."), stopAuditNavigationItem); 346 this.placeholderElement.appendChild(stopAuditHelpElement); 347 348 this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab")); 302 349 } 303 350 -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestContentView.css
r265118 r266317 49 49 } 50 50 51 .content-view.audit-test:is(.unsupported, .disabled):not(.manager-editing) { 52 display: none; 53 } 54 51 55 .content-view.audit-test h1 { 52 56 margin: 0; 57 } 58 59 .content-view.audit-test.manager-editing .editor:not(:empty) { 60 width: 100%; 61 } 62 63 .content-view.audit-test.manager-editing :is(.content-view.audit-test, header) .editor:not(:empty) { 64 border: 1px solid var(--border-color); 65 } 66 67 .content-view.audit-test .CodeMirror { 68 width: 100%; 69 height: auto; 53 70 } 54 71 … … 71 88 } 72 89 90 .content-view.audit-test > header :is(.name, .description):not([contenteditable]) { 91 padding: 1px; 92 outline: none; 93 } 94 95 .content-view.audit-test.manager-editing > header :is(.name, .description)[contenteditable] { 96 border: 1px solid var(--border-color); 97 -webkit-user-select: text; 98 outline-offset: var(--focus-ring-outline-offset); 99 } 100 101 .content-view.audit-test.manager-editing > header .name[contenteditable]:empty { 102 border-color: var(--error-text-color); 103 } 104 105 .content-view.audit-test.manager-editing > header .name[contenteditable]:empty:before { 106 content: attr(data-name); 107 color: var(--text-color-tertiary); 108 } 109 110 .content-view.audit-test.manager-editing > header .description[contenteditable]:empty:before { 111 content: "description"; 112 color: var(--text-color-tertiary); 113 } 114 115 .content-view.audit-test:not(.manager-editing) > header .description:empty, 116 .content-view.audit-test:not(.manager-editing) > header table.controls { 117 display: none; 118 } 119 120 .content-view.audit-test > header table.controls, 121 .content-view.audit-test > header table.controls > tr > td { 122 width: 100%; 123 } 124 125 .content-view.audit-test > header table.controls > tr > th { 126 text-align: end; 127 vertical-align: top; 128 line-height: 2em; 129 color: hsl(0, 0%, 34%); 130 } 131 132 .content-view.audit-test > header table.controls > tr.supports input[type="number"] { 133 text-align: end; 134 } 135 136 .content-view.audit-test > header table.controls > tr.supports .warning { 137 margin-inline-start: 4px; 138 color: var(--text-color-secondary); 139 } 140 141 .content-view.audit-test > header table.controls > tr.supports .warning:not(:empty)::before { 142 display: inline-block; 143 width: 1em; 144 margin-inline-end: 2px; 145 vertical-align: -1px; 146 content: url(../Images/Warning.svg); 147 } 148 149 .content-view.audit-test > header table.controls > tr.setup .editor { 150 margin-top: 2px; 151 } 152 73 153 .content-view.audit-test .audit-test.filtered, 74 154 .content-view.audit-test .audit-test .message-text-view { … … 82 162 .content-view.audit-test > section > .message-text-view { 83 163 background-color: var(--background-color-content); 164 } 165 166 .content-view.audit-test > section > .message-text-view > :is(progress, .indeterminate-progress-spinner) { 167 margin-bottom: 8px; 84 168 } 85 169 … … 101 185 --audit-test-header-background-color: hsla(0, 0%, 23%, 0.7); 102 186 } 187 188 .content-view.audit-test > header table.controls > tr > th { 189 color: var(--text-color-secondary); 190 } 103 191 } -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestContentView.js
r245914 r266317 36 36 37 37 this.element.classList.add("audit-test"); 38 39 this._exportButtonNavigationItem = new WI.ButtonNavigationItem("audit-export", WI.UIString("Export"), "Images/Export.svg", 15, 15); 40 this._exportButtonNavigationItem.tooltip = WI.UIString("Export result (%s)").format(WI.saveKeyboardShortcut.displayName); 41 this._exportButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 42 this._exportButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low; 43 this._exportButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleExportButtonNavigationItemClicked, this); 44 this._updateExportButtonNavigationItemState(); 38 if (this.representedObject.editable) 39 this.element.classList.add("editable"); 40 41 if (this.representedObject instanceof WI.AuditTestBase) { 42 this._exportTestButtonNavigationItem = new WI.ButtonNavigationItem("audit-export-test", WI.UIString("Export Audit"), "Images/Export.svg", 15, 15); 43 this._exportTestButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 44 this._exportTestButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low; 45 this._exportTestButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleExportTestButtonNavigationItemClicked, this); 46 } 47 48 this._exportResultButtonNavigationItem = new WI.ButtonNavigationItem("audit-export-result", WI.UIString("Export Result"), "Images/Export.svg", 15, 15); 49 this._exportResultButtonNavigationItem.tooltip = WI.UIString("Export result (%s)", "Export result (%s) @ Audit Tab", "Tooltip for button that exports the most recent result after running an audit.").format(WI.saveKeyboardShortcut.displayName); 50 this._exportResultButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 51 this._exportResultButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low; 52 this._exportResultButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleExportResultButtonNavigationItemClicked, this); 53 54 this._updateExportNavigationItems(); 45 55 46 56 this._headerView = new WI.View(document.createElement("header")); … … 48 58 this._placeholderElement = null; 49 59 60 this._cachedName = this.representedObject.name; 61 this._nameElement = null; 62 63 this._descriptionElement = null; 64 65 this._supportsInputElement = null; 66 this._supportsWarningElement = null; 67 50 68 this._shownResult = null; 51 69 } … … 55 73 get navigationItems() 56 74 { 57 return [this._exportButtonNavigationItem]; 75 let navigationItems = []; 76 if (this._exportTestButtonNavigationItem) 77 navigationItems.push(this._exportTestButtonNavigationItem); 78 navigationItems.push(this._exportResultButtonNavigationItem); 79 return navigationItems; 58 80 } 59 81 … … 65 87 get supportsSave() 66 88 { 67 return ! !this.representedObject.result;89 return !WI.auditManager.editing && !!this.representedObject.result; 68 90 } 69 91 … … 80 102 } 81 103 104 createNameElement(tagName) 105 { 106 console.assert(!this._nameElement); 107 108 this._nameElement = document.createElement(tagName); 109 this._nameElement.textContent = this.representedObject.name; 110 this._nameElement.className = "name"; 111 112 if (this.representedObject.editable) { 113 this._nameElement.spellcheck = false; 114 115 this._nameElement.addEventListener("keydown", (event) => { 116 this._handleEditorKeydown(event, this._descriptionElement); 117 }); 118 119 this._nameElement.addEventListener("input", (event) => { 120 console.assert(WI.auditManager.editing); 121 122 let name = this._nameElement.textContent; 123 if (!name.trim()) { 124 name = this._cachedName; 125 this._nameElement.removeChildren(); 126 } 127 this.representedObject.name = name; 128 }); 129 } 130 131 return this._nameElement; 132 } 133 134 createDescriptionElement(tagName) 135 { 136 console.assert(!this._descriptionElement); 137 138 this._descriptionElement = document.createElement(tagName); 139 this._descriptionElement.textContent = this.representedObject.description; 140 this._descriptionElement.className = "description"; 141 142 if (this.representedObject.editable) { 143 this._descriptionElement.spellcheck = false; 144 145 this._descriptionElement.addEventListener("keydown", (event) => { 146 this._handleEditorKeydown(event, this._supportsInputElement); 147 }); 148 149 this._descriptionElement.addEventListener("input", (event) => { 150 console.assert(WI.auditManager.editing); 151 152 let description = this._descriptionElement.textContent; 153 if (!description.trim()) { 154 description = ""; 155 this._descriptionElement.removeChildren(); 156 } 157 this.representedObject.description = description; 158 }); 159 } 160 161 return this._descriptionElement; 162 } 163 164 createControlsTableElement() 165 { 166 console.assert(this.representedObject instanceof WI.AuditTestBase); 167 console.assert(!this._supportsInputElement); 168 console.assert(!this._supportsWarningElement); 169 170 let controlsTableElement = document.createElement("table"); 171 controlsTableElement.className = "controls"; 172 173 let supportsRowElement = controlsTableElement.appendChild(document.createElement("tr")); 174 supportsRowElement.className = "supports"; 175 176 let supportsHeaderElement = supportsRowElement.appendChild(document.createElement("th")); 177 supportsHeaderElement.textContent = WI.unlocalizedString("supports"); 178 179 let supportsDataElement = supportsRowElement.appendChild(document.createElement("td")); 180 181 this._supportsInputElement = supportsDataElement.appendChild(document.createElement("input")); 182 this._supportsInputElement.type = "number"; 183 this._supportsInputElement.disabled = !this.representedObject.editable; 184 this._supportsInputElement.min = 0; 185 this._supportsInputElement.placeholder = Math.min(WI.AuditTestBase.Version, InspectorBackend.hasDomain("Audit") ? InspectorBackend.getVersion("Audit") : Infinity); 186 if (!isNaN(this.representedObject.supports)) 187 this._supportsInputElement.value = this.representedObject.supports; 188 189 if (this.representedObject.editable) { 190 this._supportsInputElement.addEventListener("keydown", (event) => { 191 this._handleEditorKeydown(event, this._setupEditorElement); 192 }); 193 } 194 195 this._supportsWarningElement = supportsDataElement.appendChild(document.createElement("span")); 196 this._supportsWarningElement.className = "warning"; 197 198 if (this.representedObject.topLevelTest === this.representedObject) { 199 let setupRowElement = controlsTableElement.appendChild(document.createElement("tr")); 200 setupRowElement.className = "setup"; 201 202 let setupHeaderElement = setupRowElement.appendChild(document.createElement("th")); 203 setupHeaderElement.textContent = WI.unlocalizedString("setup"); 204 205 let setupDataElement = setupRowElement.appendChild(document.createElement("td")); 206 207 this._setupEditorElement = setupDataElement.appendChild(document.createElement("div")); 208 } 209 210 if (this.representedObject.editable) { 211 this._supportsInputElement.addEventListener("input", (event) => { 212 this.representedObject.supports = parseInt(this._supportsInputElement.value); 213 214 this._updateSupportsInputState(); 215 }); 216 } 217 218 return controlsTableElement; 219 } 220 82 221 initialLayout() 83 222 { … … 92 231 super.layout(); 93 232 233 if (this.representedObject instanceof WI.AuditTestBase) { 234 this.element.classList.toggle("unsupported", !this.representedObject.supported); 235 this.element.classList.toggle("disabled", this.representedObject.disabled); 236 this.element.classList.toggle("manager-editing", WI.auditManager.editing); 237 238 if (this.representedObject.editable) { 239 let contentEditable = WI.auditManager.editing ? "plaintext-only" : "inherit"; 240 this._nameElement.contentEditable = contentEditable; 241 this._descriptionElement.contentEditable = contentEditable; 242 } 243 244 if (WI.auditManager.editing) { 245 this._cachedName = this.representedObject.name; 246 this._nameElement.dataset.name = this._cachedName; 247 248 this._updateSupportsInputState(); 249 this._createSetupEditor(); 250 } else { 251 this._nameElement.textContent ||= this._cachedName; 252 253 this._setupEditorElement?.removeChildren(); 254 } 255 } 256 94 257 this.hidePlaceholder(); 95 this._updateExport ButtonNavigationItemState();258 this._updateExportNavigationItems(); 96 259 } 97 260 … … 102 265 if (this.representedObject instanceof WI.AuditTestBase) { 103 266 this.representedObject.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestChanged, this); 267 this.representedObject.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this); 104 268 this.representedObject.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestChanged, this); 105 269 this.representedObject.addEventListener(WI.AuditTestBase.Event.ResultChanged, this.handleResultChanged, this); 106 270 this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestChanged, this); 107 271 this.representedObject.addEventListener(WI.AuditTestBase.Event.Stopping, this._handleTestChanged, this); 272 this.representedObject.addEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this); 273 274 WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleEditingChanged, this); 108 275 } 109 276 } … … 111 278 hidden() 112 279 { 113 if (this.representedObject instanceof WI.AuditTestBase) 114 this.representedObject.removeEventListener(null, null, this); 280 if (this.representedObject instanceof WI.AuditTestBase) { 281 this.representedObject.removeEventListener(WI.AuditTestBase.Event.Completed, this._handleTestChanged, this); 282 this.representedObject.removeEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this); 283 this.representedObject.removeEventListener(WI.AuditTestBase.Event.Progress, this._handleTestChanged, this); 284 this.representedObject.removeEventListener(WI.AuditTestBase.Event.ResultChanged, this.handleResultChanged, this); 285 this.representedObject.removeEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestChanged, this); 286 this.representedObject.removeEventListener(WI.AuditTestBase.Event.Stopping, this._handleTestChanged, this); 287 this.representedObject.removeEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this); 288 289 WI.auditManager.removeEventListener(WI.AuditManager.Event.EditingChanged, this._handleEditingChanged, this); 290 } 115 291 116 292 super.hidden(); … … 121 297 // Overridden by sub-classes. 122 298 123 this.needsLayout(); 299 if (!WI.auditManager.editing) 300 this.needsLayout(); 124 301 } 125 302 … … 153 330 let spinner = new WI.IndeterminateProgressSpinner; 154 331 this.placeholderElement.appendChild(spinner.element); 332 333 this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab")); 155 334 } 156 335 … … 170 349 }); 171 350 172 let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to start running the audit "), startNavigationItem);351 let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to start running the audit."), startNavigationItem); 173 352 this.placeholderElement.appendChild(importHelpElement); 353 354 this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab")); 174 355 } 175 356 … … 204 385 this.placeholderElement = WI.createMessageTextView(message.format(this.representedObject.name), result.didError); 205 386 this.placeholderElement.__placeholderNoResultData = true; 387 388 this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab")); 206 389 } 207 390 … … 221 404 this.needsLayout(); 222 405 }); 406 407 this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab")); 223 408 } 224 409 … … 279 464 } 280 465 281 _updateExportButtonNavigationItemState() 282 { 283 this._exportButtonNavigationItem.enabled = !!this.representedObject.result; 466 _updateExportNavigationItems() 467 { 468 if (this._exportTestButtonNavigationItem) 469 this._exportTestButtonNavigationItem.enabled = !WI.auditManager.editing; 470 471 this._exportResultButtonNavigationItem.enabled = !WI.auditManager.editing && this.representedObject.result; 472 } 473 474 _updateSupportsInputState() 475 { 476 console.assert(WI.auditManager.editing); 477 478 this._supportsInputElement.autosize(4); 479 480 this._supportsWarningElement.removeChildren(); 481 if (this.representedObject.supports > WI.AuditTestBase.Version) 482 this._supportsWarningElement.textContent = WI.UIString("too new to run in this Web Inspector", "too new to run in this Web Inspector @ Audit Tab", "Warning text shown if the version number in the 'supports' input is too new."); 483 else if (InspectorBackend.hasDomain("Audit") && this._supports > InspectorBackend.getVersion("Audit")) 484 this._supportsWarningElement.textContent = WI.UIString("too new to run in the inspected page", "too new to run in the inspected page @ Audit Tab", "Warning text shown if the version number in the 'supports' input is too new."); 485 } 486 487 _createSetupEditor() 488 { 489 if (!this._setupEditorElement) 490 return; 491 492 let setupEditorElement = document.createElement(this._setupEditorElement.nodeName); 493 setupEditorElement.className = "editor"; 494 495 // Give the rest of the view a chance to load. 496 setTimeout(() => { 497 let setupCodeMirror = WI.CodeMirrorEditor.create(setupEditorElement, { 498 autoCloseBrackets: true, 499 lineNumbers: true, 500 lineWrapping: true, 501 matchBrackets: true, 502 mode: "text/javascript", 503 readOnly: this.representedObject.editable ? false : "nocursor", 504 styleSelectedText: true, 505 value: this.representedObject.setup, 506 }); 507 508 if (this.representedObject.editable) { 509 setupCodeMirror.on("blur", (event) => { 510 this.representedObject.setup = setupCodeMirror.getValue().trim(); 511 }); 512 } 513 }); 514 515 this._setupEditorElement.parentNode.replaceChild(setupEditorElement, this._setupEditorElement); 516 this._setupEditorElement = setupEditorElement; 284 517 } 285 518 … … 290 523 } 291 524 292 _handleExportButtonNavigationItemClicked(event) 525 _handleEditorKeydown(event, nextEditor) 526 { 527 console.assert(WI.auditManager.editing); 528 529 switch (event.keyCode) { 530 case WI.KeyboardShortcut.Key.Enter.keyCode: 531 if (nextEditor) { 532 nextEditor.focus(); 533 break; 534 } 535 // fallthrough 536 537 case WI.KeyboardShortcut.Key.Escape.keyCode: 538 event.target.blur(); 539 break; 540 541 default: 542 return; 543 } 544 545 event.preventDefault(); 546 } 547 548 _handleExportTestButtonNavigationItemClicked(event) 549 { 550 WI.auditManager.export(this.representedObject); 551 } 552 553 _handleExportResultButtonNavigationItemClicked(event) 293 554 { 294 555 this._exportResult(); … … 299 560 this.needsLayout(); 300 561 } 562 563 _handleTestDisabledChanged(event) 564 { 565 console.assert(WI.auditManager.editing); 566 567 this.element.classList.toggle("disabled", this.representedObject.disabled); 568 } 569 570 _handleTestSupportedChanged(event) 571 { 572 console.assert(WI.auditManager.editing); 573 574 this.element.classList.toggle("unsupported", !this.representedObject.supported); 575 } 576 577 _handleEditingChanged(event) 578 { 579 this.needsLayout(); 580 581 this._updateExportNavigationItems(); 582 } 301 583 }; -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestGroupContentView.css
r258057 r266317 28 28 } 29 29 30 .content-view.audit-test-group > section > .audit-test-group > header { 31 margin-top: -1px; 32 border-top: 1px solid var(--border-color); 33 } 34 30 35 .content-view.audit-test-group > header { 31 margin-top: -1px;32 36 -webkit-padding-end: var(--audit-test-horizontal-space); 33 border-top: 1px solid var(--border-color);34 37 } 35 38 … … 45 48 .content-view.audit-test-group.contains-test-case > header { 46 49 position: sticky; 47 top: -1px;50 top: 0; 48 51 z-index: var(--z-index-header); 49 52 background-color: var(--audit-test-header-background-color); … … 51 54 } 52 55 53 .content-view.audit-test-group.contains-test-case + .audit-test-group.contains-test-case { 56 .content-view.audit-test-group > section > .audit-test-group.contains-test-case > header { 57 top: -1px; 58 } 59 60 .content-view.audit-test-group.contains-test-case + .audit-test-group.contains-test-case, 61 .content-view.audit-test-group + .content-view.audit-test-case { 54 62 border-top: 1px solid var(--border-color); 55 63 } -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestGroupContentView.js
r249118 r266317 33 33 34 34 this.element.classList.add("audit-test-group"); 35 this.element.classList.toggle("contains-test-case", this._subobjects().some((test) => test instanceof WI.AuditTestCase || test instanceof WI.AuditTestCaseResult));36 this.element.classList.toggle("contains-test-group", this._subobjects().some((test) => test instanceof WI.AuditTestGroup || test instanceof WI.AuditTestGroupResult));37 35 38 36 this._levelScopeBar = null; 37 38 this._viewForSubobject = new Map; 39 } 40 41 // Popover delegate 42 43 willDismissPopover(popover) 44 { 45 console.assert(popover instanceof WI.CreateAuditPopover, popover); 46 47 let audit = popover.audit; 48 if (!audit) { 49 InspectorFrontendHost.beep(); 50 return; 51 } 52 53 this.representedObject.addTest(audit); 39 54 } 40 55 41 56 // Protected 57 58 createControlsTableElement() 59 { 60 let controlsTableElement = super.createControlsTableElement(); 61 62 let actionsRowElement = controlsTableElement.appendChild(document.createElement("tr")); 63 actionsRowElement.className = "actions"; 64 65 let actionsHeaderElement = controlsTableElement.appendChild(document.createElement("th")); 66 let actionsDataElement = controlsTableElement.appendChild(document.createElement("td")); 67 68 let addTestCaseButtonElement = actionsDataElement.appendChild(document.createElement("button")); 69 addTestCaseButtonElement.disabled = !this.representedObject.editable; 70 addTestCaseButtonElement.textContent = WI.UIString("Add Test Case", "Add Test Case @ Audit Tab - Group", "Text of button to add a new audit test case to the currently shown audit group."); 71 addTestCaseButtonElement.addEventListener("click", (event) => { 72 console.assert(WI.auditManager.editing); 73 74 let popover = new WI.CreateAuditPopover(this); 75 popover.show(addTestCaseButtonElement, [WI.RectEdge.MAX_Y, WI.RectEdge.MAX_X, WI.RectEdge.MIN_X]); 76 }); 77 78 return controlsTableElement; 79 } 42 80 43 81 initialLayout() … … 48 86 informationContainer.classList.add("information"); 49 87 50 let nameElement = informationContainer.appendChild(document.createElement("h1")); 51 nameElement.textContent = this.representedObject.name; 52 53 if (this.representedObject.description) { 54 let descriptionElement = informationContainer.appendChild(document.createElement("p")); 55 descriptionElement.textContent = this.representedObject.description; 56 } 88 let nameContainer = informationContainer.appendChild(document.createElement("h1")); 89 90 nameContainer.appendChild(this.createNameElement("span")); 91 92 informationContainer.appendChild(this.createDescriptionElement("p")); 93 94 if (this.representedObject instanceof WI.AuditTestGroup) 95 informationContainer.appendChild(this.createControlsTableElement()); 57 96 58 97 this._levelNavigationBar = new WI.NavigationBar(document.createElement("nav")); … … 70 109 return a; 71 110 }); 111 112 this._updateClassList(); 72 113 } 73 114 … … 78 119 79 120 super.layout(); 121 122 if (WI.auditManager.editing) { 123 if (this._levelScopeBar) { 124 this._levelNavigationBar.removeNavigationItem(this._levelScopeBar); 125 this._levelScopeBar = null; 126 } 127 128 this._percentageContainer.hidden = true; 129 130 this.resetFilter(); 131 return; 132 } 80 133 81 134 let result = this.representedObject.result; … … 149 202 this.representedObject.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestGroupProgress, this); 150 203 this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this); 151 } 152 153 for (let subobject of this._subobjects()) {154 if (subobject instanceof WI.AuditTestBase && subobject.disabled)155 continue;156 157 let view = WI.ContentView.contentViewForRepresentedObject(subobject); 158 this.contentView.addSubview(view);159 view.shown();160 }204 205 if (this.representedObject.editable) { 206 this.representedObject.addEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this); 207 this.representedObject.addEventListener(WI.AuditTestGroup.Event.TestRemoved, this._handleTestGroupTestRemoved, this); 208 } 209 } 210 211 console.assert(!this._viewForSubobject.size); 212 for (let subobject of this._subobjects()) 213 this._addTest(subobject); 161 214 } 162 215 163 216 hidden() 164 217 { 165 for (let view of this.contentView.subviews) 218 if (this.representedObject instanceof WI.AuditTestGroup) { 219 this.representedObject.removeEventListener(WI.AuditTestBase.Event.Progress, this._handleTestGroupProgress, this); 220 this.representedObject.removeEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this); 221 222 if (this.representedObject.editable) { 223 this.representedObject.removeEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this); 224 this.representedObject.removeEventListener(WI.AuditTestGroup.Event.TestRemoved, this._handleTestGroupTestRemoved, this); 225 } 226 } 227 228 for (let view of this._viewForSubobject.values()) 166 229 view.hidden(); 167 168 230 this.contentView.removeAllSubviews(); 231 this._viewForSubobject.clear(); 169 232 170 233 super.hidden(); … … 197 260 this.placeholderElement.__progress.value = 0; 198 261 this.placeholderElement.appendChild(this.placeholderElement.__progress); 262 263 let stopAuditNavigationItem = new WI.ButtonNavigationItem("stop-audit", WI.UIString("Stop"), "Images/AuditStop.svg", 13, 13); 264 stopAuditNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText; 265 stopAuditNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, (event) => { 266 WI.auditManager.stop(); 267 }, WI.auditManager); 268 269 let stopAuditHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop running."), stopAuditNavigationItem); 270 this.placeholderElement.appendChild(stopAuditHelpElement); 271 272 this.placeholderElement.appendChild(WI.createReferencePageLink("audit-tab")); 199 273 } 200 274 … … 216 290 } 217 291 292 _updateClassList() 293 { 294 let subobjects = this._subobjects(); 295 let containsTestGroup = subobjects.some((test) => test instanceof WI.AuditTestGroup || test instanceof WI.AuditTestGroupResult); 296 this.element.classList.toggle("contains-test-group", containsTestGroup); 297 this.element.classList.toggle("contains-test-case", !containsTestGroup && subobjects.some((test) => test instanceof WI.AuditTestCase || test instanceof WI.AuditTestCaseResult)); 298 } 299 218 300 _updateLevelScopeBar(levels) 219 301 { … … 224 306 item.selected = levels.includes(item.id); 225 307 226 for (let view of this. contentView.subviews) {308 for (let view of this._viewForSubobject.values()) { 227 309 if (view instanceof WI.AuditTestGroupContentView) 228 310 view._updateLevelScopeBar(levels); 229 311 } 312 } 313 314 _addTest(test) 315 { 316 console.assert(!this._viewForSubobject.has(test)); 317 318 let view = WI.ContentView.contentViewForRepresentedObject(test); 319 this.contentView.addSubview(view); 320 view.shown(); 321 322 this._viewForSubobject.set(test, view); 230 323 } 231 324 … … 243 336 } 244 337 338 _handleTestGroupTestAdded(event) 339 { 340 console.assert(WI.auditManager.editing); 341 342 let {test} = event.data; 343 344 this._addTest(test); 345 346 this._updateClassList(); 347 } 348 349 _handleTestGroupTestRemoved(event) 350 { 351 console.assert(WI.auditManager.editing); 352 353 let {test} = event.data; 354 355 let view = this._viewForSubobject.get(test); 356 console.assert(view); 357 358 view.hidden(); 359 this.contentView.removeSubview(view); 360 361 this._updateClassList(); 362 } 363 245 364 _handleLevelScopeBarSelectionChanged(event) 246 365 { -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.css
r256774 r266317 36 36 } 37 37 38 .tree-outline .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active) > .status:hover> img {38 .tree-outline .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active):hover > .status > img { 39 39 width: 75%; 40 40 height: 75%; … … 43 43 } 44 44 45 .tree-outline .item.audit > .status:not(:hover) > img.show-on-hover, 46 .tree-outline .item.audit.test-group.expanded:not(.unsupported, .editing-audits) > .status:not(:hover) { 45 body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active).selected:hover > .status > img, 46 body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.audit.test-case.selected > .status > .indeterminate-progress-spinner, 47 body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.audit.test-group.selected > .status > progress { 48 filter: var(--filter-invert); 49 } 50 51 .tree-outline .item.audit:not(:hover) > .status > img.show-on-hover, 52 .tree-outline .item.audit.test-group.expanded:not(.unsupported, .editing-audits):not(:hover) > .status { 47 53 opacity: 0; 48 54 } 49 55 50 56 .tree-outline .item.audit.manager-active > .status > img.show-on-hover, 51 .tree-outline .item.audit.test-group.expanded:not(.editing-audits) > .status:hover> :not(img),57 .tree-outline .item.audit.test-group.expanded:not(.editing-audits):hover > .status > :not(img), 52 58 .tree-outline .item.audit.test-group-result.expanded > .status, 53 59 .tree-outline .item.audit.unsupported + .children .item.audit.unsupported > .status > img { … … 103 109 104 110 @media (prefers-color-scheme: dark) { 111 .tree-outline .item.audit:matches(.test-case, .test-group):not(.unsupported, .manager-active):hover > .status > img { 112 filter: var(--filter-invert) brightness(90%); 113 } 114 105 115 .audit.test-case .icon { 106 116 content: url(../Images/TypeIcons.svg#AuditTestCase-dark); -
trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.js
r245914 r266317 52 52 53 53 if (isTestGroup) 54 this._expandedSetting = new WI.Setting(`audit-tree-element-${this.representedObject.name}-expanded`, false); 54 this._expandedSetting = new WI.Setting(WI.AuditTreeElement.expandedSettingKey(this.representedObject.name), false); 55 } 56 57 // Static 58 59 static expandedSettingKey(name) 60 { 61 return `audit-tree-element-${name}-expanded`; 55 62 } 56 63 … … 69 76 else if (this.representedObject instanceof WI.AuditTestGroup) 70 77 this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this); 78 79 if (this.representedObject.editable) { 80 this.representedObject.addEventListener(WI.AuditTestBase.Event.NameChanged, this._handleTestNameChanged, this); 81 this.representedObject.addEventListener(WI.AuditTestBase.Event.SupportedChanged, this._handleTestSupportedChanged, this); 82 83 if (this.representedObject instanceof WI.AuditTestGroup) 84 this.representedObject.addEventListener(WI.AuditTestGroup.Event.TestAdded, this._handleTestGroupTestAdded, this); 85 } 71 86 72 87 WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleManagerEditingChanged, this); … … 130 145 return false; 131 146 132 if (!(this.parent instanceof WI.TreeOutline))133 return false;134 135 147 if (!WI.auditManager.editing) 136 148 return false; 137 149 138 WI.auditManager.removeTest(this.representedObject);150 this.representedObject.remove(); 139 151 140 152 return true; 141 153 } 142 154 155 canSelectOnMouseDown(event) 156 { 157 if (this.representedObject instanceof WI.AuditTestBase && this.representedObject.supported && this.status.contains(event.target)) 158 return false; 159 160 return super.canSelectOnMouseDown(event); 161 } 162 143 163 populateContextMenu(contextMenu, event) 144 164 { 145 if (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive) { 146 contextMenu.appendItem(WI.UIString("Start"), (event) => { 147 this._start(); 148 }); 149 } 165 let isTest = this.representedObject instanceof WI.AuditTestBase; 150 166 151 167 contextMenu.appendSeparator(); 152 168 153 if (this.representedObject instanceof WI.AuditTestBase) { 154 contextMenu.appendItem(WI.UIString("Export Test"), (event) => { 155 WI.auditManager.export(this.representedObject); 156 }); 157 } 158 159 if (this.representedObject.result) { 160 contextMenu.appendItem(WI.UIString("Export Result"), (event) => { 169 if (WI.auditManager.editing) { 170 if (isTest) { 171 if (this.representedObject.supported) { 172 contextMenu.appendItem(this.representedObject.disabled ? WI.UIString("Enable Audit") : WI.UIString("Disable Audit"), () => { 173 this.representedObject.disabled = !this.representedObject.disabled; 174 }); 175 } 176 177 contextMenu.appendItem(WI.UIString("Duplicate Audit"), async () => { 178 let audit = await this.representedObject.clone(); 179 WI.auditManager.addTest(audit); 180 }); 181 182 if (this.representedObject.editable) { 183 contextMenu.appendItem(WI.UIString("Delete Audit"), () => { 184 this.representedObject.remove(); 185 }); 186 } 187 } 188 } else { 189 if (isTest) { 190 contextMenu.appendItem(WI.UIString("Start Audit"), () => { 191 this._start(); 192 }, WI.auditManager.runningState !== WI.AuditManager.RunningState.Inactive); 193 194 contextMenu.appendSeparator(); 195 196 contextMenu.appendItem(WI.UIString("Export Audit"), () => { 197 WI.auditManager.export(this.representedObject); 198 }); 199 } 200 201 contextMenu.appendItem(WI.UIString("Export Result"), () => { 161 202 WI.auditManager.export(this.representedObject.result); 162 }); 203 }, !this.representedObject.result); 204 205 if (isTest && this.representedObject.editable) { 206 contextMenu.appendSeparator(); 207 208 contextMenu.appendItem(WI.UIString("Edit Audit"), () => { 209 WI.auditManager.editing = true; 210 WI.showRepresentedObject(this.representedObject); 211 }); 212 } 163 213 } 164 214 … … 316 366 } 317 367 368 _handleTestNameChanged(event) 369 { 370 this.mainTitle = this.representedObject.name; 371 372 if (this.representedObject instanceof WI.AuditTestGroup) 373 this._expandedSetting = new WI.Setting(WI.AuditTreeElement.expandedSettingKey(this.representedObject.name), !!WI.Setting.migrateValue(WI.AuditTreeElement.expandedSettingKey(event.data.oldName))); 374 } 375 376 _handleTestSupportedChanged(event) 377 { 378 this._updateStatus(); 379 } 380 381 _handleTestGroupTestAdded(event) 382 { 383 let {test} = event.data; 384 385 this.appendChild(new WI.AuditTreeElement(test)); 386 } 387 318 388 _handleManagerEditingChanged(event) 319 389 { -
trunk/Source/WebInspectorUI/UserInterface/Views/CanvasOverviewContentView.css
r265118 r266317 202 202 width: 1.5em; 203 203 min-width: 1.5em; 204 margin: 0 var(--recording-auto-capture-input-margin);204 margin: 0 4px; 205 205 text-align: center; 206 }207 208 .navigation-bar > .item.canvas-recording-auto-capture > label > input::-webkit-inner-spin-button {209 -webkit-appearance: none;210 206 } 211 207 -
trunk/Source/WebInspectorUI/UserInterface/Views/CanvasOverviewContentView.js
r255396 r266317 50 50 this._recordingAutoCaptureFrameCountInputElement.type = "number"; 51 51 this._recordingAutoCaptureFrameCountInputElement.min = 0; 52 this._recordingAutoCaptureFrameCountInputElement.style.setProperty("--recording-auto-capture-input-margin", CanvasOverviewContentView.recordingAutoCaptureInputMargin + "px");53 52 this._recordingAutoCaptureFrameCountInputElement.addEventListener("input", this._handleRecordingAutoCaptureInput.bind(this)); 54 53 this._recordingAutoCaptureFrameCountInputElementValue = WI.settings.canvasRecordingAutoCaptureFrameCount.value; … … 69 68 this._savedRecordingsTreeOutline = null; 70 69 } 71 72 // Static73 74 static get recordingAutoCaptureInputMargin() { return 4; }75 70 76 71 // Public … … 227 222 } 228 223 229 WI.ImageUtilities.scratchCanvasContext2D((context) => { 230 if (!this._recordingAutoCaptureFrameCountInputElement.__cachedFont) { 231 let computedStyle = window.getComputedStyle(this._recordingAutoCaptureFrameCountInputElement); 232 this._recordingAutoCaptureFrameCountInputElement.__cachedFont = computedStyle.font; 233 } 234 235 context.font = this._recordingAutoCaptureFrameCountInputElement.__cachedFont; 236 let textMetrics = context.measureText(this._recordingAutoCaptureFrameCountInputElement.value || this._recordingAutoCaptureFrameCountInputElement.placeholder); 237 this._recordingAutoCaptureFrameCountInputElement.style.setProperty("width", (textMetrics.width + (2 * CanvasOverviewContentView.recordingAutoCaptureInputMargin)) + "px"); 238 }); 224 this._recordingAutoCaptureFrameCountInputElement.autosize(); 239 225 240 226 return frameCount; -
trunk/Source/WebInspectorUI/UserInterface/Views/Main.css
r265027 r266317 231 231 display: inline-flex; 232 232 height: 20px; 233 padding: 0 4px;234 233 border-bottom: none; 235 vertical-align: -3px;234 vertical-align: var(--navigation-item-help-navigation-bar-vertical-align, sub); 236 235 } 237 236 … … 250 249 .navigation-item-help > .navigation-bar > .item.button.text-only { 251 250 border: solid 1px var(--border-color); 251 } 252 253 .message-text-view > .navigation-item-help + .navigation-item-help { 254 margin-top: 4px; 252 255 } 253 256 -
trunk/Source/WebInspectorUI/UserInterface/Views/SearchSidebarPanel.js
r262806 r266317 70 70 searchNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleDefaultContentViewSearchNavigationItemClicked, this); 71 71 72 let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to see recent searches "), searchNavigationItem);72 let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to see recent searches."), searchNavigationItem); 73 73 contentPlaceholder.appendChild(importHelpElement); 74 74 -
trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css
r265237 r266317 191 191 --focus-ring-outline-offset: -2px; 192 192 193 /* Invert colors yet preserve the hue */ 194 --filter-invert: invert(100%) hue-rotate(180deg); 195 193 196 --undocked-title-area-height: 0px; 194 197 --tab-bar-height: var(--navigation-bar-height); … … 363 366 --timeline-scanner-color: hsl(0, 0%, 80%); 364 367 365 /* Invert colors yet preserve the hue */366 --filter-invert: invert(100%) hue-rotate(180deg);367 368 368 /* TODO: Use the same variable for the default theme */ 369 369 --overlay-background: hsla(0, 0%, 24%, 0.9);
Note:
See TracChangeset
for help on using the changeset viewer.