Diff
Modified: trunk/LayoutTests/ChangeLog (239857 => 239858)
--- trunk/LayoutTests/ChangeLog 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/LayoutTests/ChangeLog 2019-01-11 05:54:54 UTC (rev 239858)
@@ -1,3 +1,14 @@
+2019-01-10 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: Audit: allow audits to be enabled/disabled
+ https://bugs.webkit.org/show_bug.cgi?id=192210
+ <rdar://problem/46423583>
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/unit-tests/objectStore/clear.html: Added.
+ * inspector/unit-tests/objectStore/clear-expected.txt: Added.
+
2019-01-10 Justin Fan <justin_...@apple.com>
[WebGPU] WebGPUBindGroup and device::createBindGroup prototype
Added: trunk/LayoutTests/inspector/unit-tests/objectStore/clear-expected.txt (0 => 239858)
--- trunk/LayoutTests/inspector/unit-tests/objectStore/clear-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/objectStore/clear-expected.txt 2019-01-11 05:54:54 UTC (rev 239858)
@@ -0,0 +1,12 @@
+Tests WI.ObjectStore.prototype.clear.
+
+
+== Running test suite: WI.ObjectStore.prototype.clear
+-- Running test case: WI.ObjectStore.prototype.clear.Empty
+[]
+[]
+
+-- Running test case: WI.ObjectStore.prototype.clear.NotEmpty
+[true,1,"foo",["bar"],{"a":1}]
+[]
+
Added: trunk/LayoutTests/inspector/unit-tests/objectStore/clear.html (0 => 239858)
--- trunk/LayoutTests/inspector/unit-tests/objectStore/clear.html (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/objectStore/clear.html 2019-01-11 05:54:54 UTC (rev 239858)
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+function test()
+{
+ let suite = InspectorTest.ObjectStore.createSuite("WI.ObjectStore.prototype.clear");
+
+ function testClear(name, {objects}) {
+ InspectorTest.ObjectStore.wrapTest(name, async function() {
+ let objectStore = InspectorTest.ObjectStore.createObjectStore({autoIncrement: true});
+
+ for (let object of objects)
+ await objectStore.add(object);
+
+ await InspectorTest.ObjectStore.logValues();
+
+ await objectStore.clear();
+ });
+ }
+
+ testClear("WI.ObjectStore.prototype.clear.Empty", {
+ objects: [],
+ });
+
+ testClear("WI.ObjectStore.prototype.clear.NotEmpty", {
+ objects: [true, 1, "foo", ["bar"], {a: 1}],
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+ <p>Tests WI.ObjectStore.prototype.clear.</p>
+</body>
+</html>
Modified: trunk/Source/WebInspectorUI/ChangeLog (239857 => 239858)
--- trunk/Source/WebInspectorUI/ChangeLog 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/ChangeLog 2019-01-11 05:54:54 UTC (rev 239858)
@@ -1,3 +1,109 @@
+2019-01-10 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: Audit: allow audits to be enabled/disabled
+ https://bugs.webkit.org/show_bug.cgi?id=192210
+ <rdar://problem/46423583>
+
+ Reviewed by Joseph Pecoraro.
+
+ * UserInterface/Controllers/AuditManager.js:
+ (WI.AuditManager.prototype.get editing): Added.
+ (WI.AuditManager.prototype.set editing): Added.
+ (WI.AuditManager.prototype.stop):
+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded):
+ Since default audits aren't stored, keep a list of disabled default tests in a `WI.Setting`.
+
+ * UserInterface/Models/AuditTestBase.js:
+ (WI.AuditTestBase):
+ (WI.AuditTestBase.prototype.get disabled): Added.
+ (WI.AuditTestBase.prototype.set disabled): Added.
+ (WI.AuditTestBase.prototype.async start):
+ (WI.AuditTestBase.prototype.stop):
+ (WI.AuditTestBase.toJSON):
+
+ * UserInterface/Models/AuditTestCase.js:
+ (WI.AuditTestCase):
+ (WI.AuditTestCase.async fromPayload):
+ (WI.AuditTestCase.prototype.toJSON):
+
+ * UserInterface/Models/AuditTestGroup.js:
+ (WI.AuditTestGroup):
+ (WI.AuditTestGroup.async fromPayload):
+ (WI.AuditTestGroup.prototype.get disabled): Added.
+ (WI.AuditTestGroup.prototype.set disabled): Added.
+ (WI.AuditTestGroup.prototype.toJSON):
+ (WI.AuditTestGroup.prototype.async run):
+ (WI.AuditTestGroup.prototype._handleTestDisabledChanged): Added.
+ (WI.AuditTestGroup.prototype._handleTestProgress):
+ Propagate `disabled` changes to all sub-tests, unless the change was caused by one of the
+ sub-tests, in which case we are now in an intermediate state.
+
+ * UserInterface/Views/AuditNavigationSidebarPanel.js:
+ (WI.AuditNavigationSidebarPanel):
+ (WI.AuditNavigationSidebarPanel.prototype.showDefaultContentView):
+ (WI.AuditNavigationSidebarPanel.prototype.initialLayout):
+ (WI.AuditNavigationSidebarPanel.prototype.hasCustomFilters): Added.
+ (WI.AuditNavigationSidebarPanel.prototype.matchTreeElementAgainstCustomFilters): Added.
+ (WI.AuditNavigationSidebarPanel.prototype._addTest):
+ (WI.AuditNavigationSidebarPanel.prototype._addResult):
+ (WI.AuditNavigationSidebarPanel.prototype._updateStartStopButtonNavigationItemState):
+ (WI.AuditNavigationSidebarPanel.prototype._updateEditButtonNavigationItemState): Added.
+ (WI.AuditNavigationSidebarPanel.prototype._handleAuditManagerEditingChanged): Added.
+ (WI.AuditNavigationSidebarPanel.prototype._handleAuditTestRemoved):
+ (WI.AuditNavigationSidebarPanel.prototype._handleAuditTestScheduled):
+ (WI.AuditNavigationSidebarPanel.prototype._treeSelectionDidChange):
+ (WI.AuditNavigationSidebarPanel.prototype._handleEditButtonNavigationItemClicked): Added.
+ * UserInterface/Views/AuditNavigationSidebarPanel.css:
+ (.sidebar > .panel.navigation.audit > .content):
+ (.sidebar > .panel.navigation.audit > .content > .tree-outline): Added.
+ (.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled):active): Added.
+ (.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled).activated): Added.
+ (.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled).activated:active): Added.
+ (.sidebar > .panel.navigation.audit > .content .edit-audits.disabled): Added.
+ (.finish-editing-audits-placeholder.message-text-view .navigation-item-help .navigation-bar): Added.
+ Leverage custom filters to ensure that disabled audits arent shown when not editing and that
+ result tree elements aren't shown while editing.
+
+ * UserInterface/Views/AuditTestGroupContentView.js:
+ (WI.AuditTestGroupContentView.prototype.shown):
+
+ * UserInterface/Views/AuditTreeElement.js:
+ (WI.AuditTreeElement.prototype.onattach):
+ (WI.AuditTreeElement.prototype.canSelectOnMouseDown): Added.
+ (WI.AuditTreeElement.prototype._updateTestGroupDisabled): Added.
+ (WI.AuditTreeElement.prototype._handleTestDisabledChanged): Added.
+ (WI.AuditTreeElement.prototype._handleManagerEditingChanged): Added.
+ * UserInterface/Views/AuditTreeElement.css:
+ (.tree-outline .item.audit > .status:not(:hover) > img.show-on-hover, .tree-outline .item.audit.test-group.expanded:not(.editing-audits) > .status:not(:hover)): Added.
+ (.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): Added.
+ (.tree-outline .item.audit > .status:not(:hover) > img.show-on-hover, .tree-outline .item.audit.test-group.expanded > .status:not(:hover)): Deleted.
+ (.tree-outline .item.audit.manager-active > .status > img.show-on-hover, .tree-outline .item.audit.test-group.expanded > .status:hover > :not(img), .tree-outline .item.audit.test-group-result.expanded > .status): Deleted.
+ Prevent selection and running when editing.
+
+ * UserInterface/Views/TreeOutline.css:
+ (.tree-outline .children.expanded:not([hidden])): Added.
+ (.tree-outline .children.expanded): Deleted.
+
+ * UserInterface/Base/ObjectStore.js:
+ (WI.ObjectStore._open):
+ Batch operations together to help avoid multiple simultaneous `indexedDB.open` calls. This
+ should also help preserve the order of operations, as once the database is open, operations
+ are executed in the order they were enqueued.
+
+ (WI.ObjectStore.prototype.async.addObject):
+ Pass a unique `Symbol` to the `toJSON` call on the given object so that the object can save
+ additional values that wouldn't normally be saved. This doesn't conflict with normal usage
+ of `toJSON` (e.g. `JSON.stringify`) because that case also passes in a value:
+ - `undefined`, if it was called directly on the object
+ - the key for this object in the containing object
+ - the index of this object in the containing array
+ In any case, the value can never equal the unique `Symbol`, so it's guaranteed that the code
+ will only run for `WI.ObjectStore` operations.
+
+ (WI.ObjectStore.prototype.async.clear): Added.
+
+ * Localizations/en.lproj/localizedStrings.js:
+
2019-01-09 Devin Rousso <drou...@apple.com>
Web Inspector: Protocol Logging: log messages as objects if inspector^2 is open
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -324,6 +324,7 @@
localizedStrings["Edit \u201Cspring\u201D function"] = "Edit \u201Cspring\u201D function";
localizedStrings["Edit configuration"] = "Edit configuration";
localizedStrings["Edit custom gradient"] = "Edit custom gradient";
+localizedStrings["Editing audits"] = "Editing audits";
localizedStrings["Element"] = "Element";
localizedStrings["Element clips compositing descendants"] = "Element clips compositing descendants";
localizedStrings["Element has CSS blending applied and composited descendants"] = "Element has CSS blending applied and composited descendants";
@@ -688,6 +689,7 @@
localizedStrings["Press %s to import a test or result file"] = "Press %s to import a test or result file";
localizedStrings["Press %s to load a recording from file."] = "Press %s to load a recording from file.";
localizedStrings["Press %s to start running the audit"] = "Press %s to start running the audit";
+localizedStrings["Press %s to stop editing"] = "Press %s to stop editing";
localizedStrings["Pressed"] = "Pressed";
localizedStrings["Pretty print"] = "Pretty print";
localizedStrings["Preview"] = "Preview";
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/ObjectStore.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Base/ObjectStore.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/ObjectStore.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -52,6 +52,13 @@
return;
}
+ if (Array.isArray(WI.ObjectStore._databaseCallbacks)) {
+ WI.ObjectStore._databaseCallbacks.push(callback);
+ return;
+ }
+
+ WI.ObjectStore._databaseCallbacks = [callback];
+
const version = 1; // Increment this for every edit to `WI.objectStores`.
let databaseRequest = indexedDB.open(WI.ObjectStore._databaseName, version);
@@ -81,7 +88,10 @@
WI.ObjectStore._database = null;
});
- callback(WI.ObjectStore._database);
+ for (let databaseCallback of WI.ObjectStore._databaseCallbacks)
+ databaseCallback(WI.ObjectStore._database);
+
+ WI.ObjectStore._databaseCallbacks = null;
});
}
@@ -118,7 +128,7 @@
return undefined;
console.assert(typeof object.toJSON === "function", "ObjectStore cannot store an object without JSON serialization", object.constructor.name);
- let result = await this.add(object.toJSON(), ...args);
+ let result = await this.add(object.toJSON(WI.ObjectStore.toJSONSymbol), ...args);
this.associateObject(object, args[0], result);
return result;
}
@@ -139,6 +149,14 @@
return this.delete(this._resolveKeyPath(object).value, ...args);
}
+ async clear(...args)
+ {
+ if (!WI.ObjectStore.supported())
+ return undefined;
+
+ return this._operation("readwrite", (objectStore) => objectStore.clear(...args));
+ }
+
// Private
_resolveKeyPath(object, keyPath)
@@ -203,7 +221,10 @@
};
WI.ObjectStore._database = null;
+WI.ObjectStore._databaseCallbacks = null;
+WI.ObjectStore.toJSONSymbol = Symbol("ObjectStore-toJSON");
+
// Be sure to update the `version` above when making changes.
WI.objectStores = {
audits: new WI.ObjectStore("audit-manager-tests", {keyPath: "__id", autoIncrement: true}),
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -35,6 +35,8 @@
this._runningState = WI.AuditManager.RunningState.Inactive;
this._runningTests = [];
+ this._disabledDefaultTestsSetting = new WI.Setting("audit-disabled-default-tests", []);
+
WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
}
@@ -52,6 +54,51 @@
get results() { return this._results; }
get runningState() { return this._runningState; }
+ get editing()
+ {
+ return this._runningState === WI.AuditManager.RunningState.Disabled;
+ }
+
+ set editing(editing)
+ {
+ console.assert(this._runningState === WI.AuditManager.RunningState.Disabled || this._runningState === WI.AuditManager.RunningState.Inactive);
+ if (this._runningState !== WI.AuditManager.RunningState.Disabled && this._runningState !== WI.AuditManager.RunningState.Inactive)
+ return;
+
+ let runningState = editing ? WI.AuditManager.RunningState.Disabled : WI.AuditManager.RunningState.Inactive;
+ console.assert(runningState !== this._runningState);
+ if (runningState === this._runningState)
+ return;
+
+ this._runningState = runningState;
+
+ this.dispatchEventToListeners(WI.AuditManager.Event.EditingChanged);
+
+ if (!this.editing) {
+ WI.objectStores.audits.clear();
+
+ let disabledDefaultTests = [];
+ let saveDisabledDefaultTest = (test) => {
+ if (test.disabled)
+ disabledDefaultTests.push(test.name);
+
+ if (test instanceof WI.AuditTestGroup) {
+ for (let child of test.tests)
+ saveDisabledDefaultTest(child);
+ }
+ };
+
+ for (let test of this._tests) {
+ if (test.__default)
+ saveDisabledDefaultTest(test);
+ else
+ WI.objectStores.audits.addObject(test);
+ }
+
+ this._disabledDefaultTestsSetting.value = disabledDefaultTests;
+ }
+ }
+
async start(tests)
{
console.assert(this._runningState === WI.AuditManager.RunningState.Inactive);
@@ -97,10 +144,10 @@
if (this._runningState !== WI.AuditManager.RunningState.Active)
return;
+ this._runningState = WI.AuditManager.RunningState.Stopping;
+
for (let test of this._runningTests)
test.stop();
-
- this._runningState = WI.AuditManager.RunningState.Stopping;
}
async processJSON({json, error})
@@ -253,7 +300,19 @@
], {description: WI.UIString("Tests for ways to improve accessibility.")}),
];
+ let checkDisabledDefaultTest = (test) => {
+ if (this._disabledDefaultTestsSetting.value.includes(test.name))
+ test.disabled = true;
+
+ if (test instanceof WI.AuditTestGroup) {
+ for (let child of test.tests)
+ checkDisabledDefaultTest(child);
+ }
+ };
+
for (let test of defaultTests) {
+ checkDisabledDefaultTest(test);
+
test.__default = true;
this._addTest(test);
}
@@ -261,6 +320,7 @@
};
WI.AuditManager.RunningState = {
+ Disabled: "disabled",
Inactive: "inactive",
Active: "active",
Stopping: "stopping",
@@ -267,6 +327,7 @@
};
WI.AuditManager.Event = {
+ EditingChanged: "audit-manager-editing-changed",
TestAdded: "audit-manager-test-added",
TestCompleted: "audit-manager-test-completed",
TestRemoved: "audit-manager-test-removed",
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestBase.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestBase.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestBase.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -25,17 +25,21 @@
WI.AuditTestBase = class AuditTestBase extends WI.Object
{
- constructor(name, {description} = {})
+ constructor(name, {description, disabled} = {})
{
console.assert(typeof name === "string");
console.assert(!description || typeof description === "string");
+ console.assert(disabled === undefined || typeof disabled === "boolean");
super();
+ // This class should not be instantiated directly. Create a concrete subclass instead.
+ console.assert(this.constructor !== WI.AuditTestBase && this instanceof WI.AuditTestBase);
+
this._name = name;
this._description = description || null;
- this._runningState = WI.AuditManager.RunningState.Inactive;
+ this._runningState = disabled ? WI.AuditManager.RunningState.Disabled : WI.AuditManager.RunningState.Inactive;
this._result = null;
}
@@ -46,10 +50,33 @@
get runningState() { return this._runningState; }
get result() { return this._result; }
+ get disabled()
+ {
+ return this._runningState === WI.AuditManager.RunningState.Disabled;
+ }
+
+ set disabled(disabled)
+ {
+ console.assert(this._runningState === WI.AuditManager.RunningState.Disabled || this._runningState === WI.AuditManager.RunningState.Inactive);
+ if (this._runningState !== WI.AuditManager.RunningState.Disabled && this._runningState !== WI.AuditManager.RunningState.Inactive)
+ return;
+
+ let runningState = disabled ? WI.AuditManager.RunningState.Disabled : WI.AuditManager.RunningState.Inactive;
+ if (runningState === this._runningState)
+ return;
+
+ this._runningState = runningState;
+
+ this.dispatchEventToListeners(WI.AuditTestBase.Event.DisabledChanged);
+ }
+
async start()
{
// Called from WI.AuditManager.
+ if (this.disabled)
+ return;
+
console.assert(WI.auditManager.runningState === WI.AuditManager.RunningState.Active);
console.assert(this._runningState === WI.AuditManager.RunningState.Inactive);
@@ -69,8 +96,11 @@
{
// Called from WI.AuditManager.
- console.assert(this._runningState !== WI.AuditManager.RunningState.Inactive);
+ if (this.disabled)
+ return;
+ console.assert(WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping);
+
if (this._runningState !== WI.AuditManager.RunningState.Active)
return;
@@ -96,7 +126,7 @@
cookie["audit-" + this.constructor.TypeIdentifier + "-name"] = this._name;
}
- toJSON()
+ toJSON(key)
{
let json = {
type: this.constructor.TypeIdentifier,
@@ -104,6 +134,8 @@
};
if (this._description)
json.description = this._description;
+ if (key === WI.ObjectStore.toJSONSymbol)
+ json.disabled = this.disabled;
return json;
}
@@ -117,6 +149,7 @@
WI.AuditTestBase.Event = {
Completed: "audit-test-base-completed",
+ DisabledChanged: "audit-test-base-disabled-changed",
Progress: "audit-test-base-progress",
ResultCleared: "audit-test-base-result-cleared",
Scheduled: "audit-test-base-scheduled",
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -25,11 +25,11 @@
WI.AuditTestCase = class AuditTestCase extends WI.AuditTestBase
{
- constructor(name, test, {description} = {})
+ constructor(name, test, options = {})
{
console.assert(typeof test === "string");
- super(name, {description});
+ super(name, options);
this._test = test;
}
@@ -41,7 +41,7 @@
if (typeof payload !== "object" || payload === null)
return null;
- let {type, name, test, description} = payload;
+ let {type, name, test, description, disabled} = payload;
if (type !== WI.AuditTestCase.TypeIdentifier)
return null;
@@ -55,6 +55,8 @@
let options = {};
if (typeof description === "string")
options.description = description;
+ if (typeof disabled === "boolean")
+ options.disabled = disabled;
return new WI.AuditTestCase(name, test, options);
}
@@ -63,9 +65,9 @@
get test() { return this._test; }
- toJSON()
+ toJSON(key)
{
- let json = super.toJSON();
+ let json = super.toJSON(key);
json.test = this._test;
return json;
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestGroup.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestGroup.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/AuditTestGroup.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -25,16 +25,25 @@
WI.AuditTestGroup = class AuditTestGroup extends WI.AuditTestBase
{
- constructor(name, tests, {description} = {})
+ constructor(name, tests, options = {})
{
console.assert(Array.isArray(tests));
- super(name, {description});
+ // Set disabled once `_tests` is set so that it propagates.
+ let disabled = options.disabled;
+ options.disabled = false;
+ super(name, options);
+
this._tests = tests;
+ this._preventDisabledPropagation = false;
+ if (disabled)
+ this.disabled = disabled;
+
for (let test of this._tests) {
test.addEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCompleted, this);
+ test.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this);
test.addEventListener(WI.AuditTestBase.Event.Progress, this._handleTestProgress, this);
}
}
@@ -46,7 +55,7 @@
if (typeof payload !== "object" || payload === null)
return null;
- let {type, name, tests, description} = payload;
+ let {type, name, tests, description, disabled} = payload;
if (type !== WI.AuditTestGroup.TypeIdentifier)
return null;
@@ -75,6 +84,8 @@
let options = {};
if (typeof description === "string")
options.description = description;
+ if (typeof disabled === "boolean")
+ options.disabled = disabled;
return new WI.AuditTestGroup(name, tests, options);
}
@@ -83,6 +94,21 @@
get tests() { return this._tests; }
+ get disabled()
+ {
+ return super.disabled;
+ }
+
+ set disabled(disabled)
+ {
+ if (!this._preventDisabledPropagation) {
+ for (let test of this._tests)
+ test.disabled = disabled;
+ }
+
+ super.disabled = disabled;
+ }
+
stop()
{
// Called from WI.AuditManager.
@@ -107,10 +133,10 @@
});
}
- toJSON()
+ toJSON(key)
{
- let json = super.toJSON();
- json.tests = this._tests.map((testCase) => testCase.toJSON());
+ let json = super.toJSON(key);
+ json.tests = this._tests.map((testCase) => testCase.toJSON(key));
return json;
}
@@ -121,6 +147,8 @@
let count = this._tests.length;
for (let index = 0; index < count && this._runningState === WI.AuditManager.RunningState.Active; ++index) {
let test = this._tests[index];
+ if (test.disabled)
+ continue;
await test.start();
@@ -153,6 +181,21 @@
this.dispatchEventToListeners(WI.AuditTestBase.Event.Completed);
}
+ _handleTestDisabledChanged(event)
+ {
+ let enabledTestCount = this._tests.filter((test) => !test.disabled).length;
+ if (event.target.disabled && !enabledTestCount)
+ this.disabled = true;
+ else if (!event.target.disabled && enabledTestCount === 1) {
+ this._preventDisabledPropagation = true;
+ this.disabled = false;
+ this._preventDisabledPropagation = false;
+ } else {
+ // Don't change `disabled`, as we're currently in an "indeterminate" state.
+ this.dispatchEventToListeners(WI.AuditTestBase.Event.DisabledChanged);
+ }
+ }
+
_handleTestProgress(event)
{
if (this._runningState !== WI.AuditManager.RunningState.Active)
@@ -161,6 +204,9 @@
let walk = (tests) => {
let count = 0;
for (let test of tests) {
+ if (test.disabled)
+ continue;
+
if (test instanceof WI.AuditTestCase)
++count;
else if (test instanceof WI.AuditTestGroup)
@@ -170,8 +216,8 @@
};
this.dispatchEventToListeners(WI.AuditTestBase.Event.Progress, {
- index: event.data.index + walk(this.tests.slice(0, this.tests.indexOf(event.target))),
- count: walk(this.tests),
+ index: event.data.index + walk(this._tests.slice(0, this._tests.indexOf(event.target))),
+ count: walk(this._tests),
});
}
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.css (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.css 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.css 2019-01-11 05:54:54 UTC (rev 239858)
@@ -24,9 +24,31 @@
*/
.sidebar > .panel.navigation.audit > .content {
+ display: flex;
+ flex-direction: column;
top: var(--navigation-bar-height);
}
+.sidebar > .panel.navigation.audit > .content > .tree-outline {
+ flex-grow: 1;
+}
+
+.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled):active {
+ color: var(--glyph-color-pressed);
+}
+
+.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled).activated {
+ color: var(--glyph-color-active);
+}
+
+.sidebar > .panel.navigation.audit > .content .edit-audits:not(.disabled).activated:active {
+ color: var(--glyph-color-active-pressed);
+}
+
+.sidebar > .panel.navigation.audit > .content .edit-audits.disabled {
+ color: var(--glyph-color-disabled);
+}
+
.sidebar > .panel.navigation.audit.has-results:not(.has-tests) > .content > .message-text-view {
position: initial;
border-bottom: 1px solid var(--border-color);
@@ -39,3 +61,8 @@
.sidebar > .panel.navigation.audit.has-results:not(.has-tests) > .content > .message-text-view > button {
margin: 8px 0 7px;
}
+
+.finish-editing-audits-placeholder.message-text-view .navigation-item-help .navigation-bar {
+ padding: 0;
+ vertical-align: 0.5px;
+}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -36,16 +36,30 @@
{
let contentView = new WI.ContentView;
- let contentPlaceholder = WI.createMessageTextView(WI.UIString("No audit selected"));
- contentView.element.appendChild(contentPlaceholder);
+ if (WI.auditManager.editing) {
+ let contentPlaceholder = WI.createMessageTextView(WI.UIString("Editing audits"));
+ contentPlaceholder.classList.add("finish-editing-audits-placeholder");
+ contentView.element.appendChild(contentPlaceholder);
- let importNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15);
- importNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
- importNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
+ let finishEditingNavigationItem = new WI.ButtonNavigationItem("finish-editing-audits", WI.UIString("Done"));
+ finishEditingNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, (event) => {
+ WI.auditManager.editing = false;
+ });
- let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to import a test or result file"), importNavigationItem);
- contentPlaceholder.appendChild(importHelpElement);
+ let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop editing"), finishEditingNavigationItem);
+ contentPlaceholder.appendChild(importHelpElement);
+ } else {
+ let contentPlaceholder = WI.createMessageTextView(WI.UIString("No audit selected"));
+ contentView.element.appendChild(contentPlaceholder);
+ let importNavigationItem = new WI.ButtonNavigationItem("import-audit", WI.UIString("Import"), "Images/Import.svg", 15, 15);
+ importNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
+ importNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
+
+ let importHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to import a test or result file"), importNavigationItem);
+ contentPlaceholder.appendChild(importHelpElement);
+ }
+
this.contentBrowser.showContentView(contentView);
}
@@ -57,24 +71,32 @@
this.contentTreeOutline.allowsRepeatSelection = false;
- let navigationBar = new WI.NavigationBar;
+ let controlsNavigationBar = new WI.NavigationBar;
this._startStopButtonNavigationItem = new WI.ToggleButtonNavigationItem("audit-start-stop", WI.UIString("Start"), WI.UIString("Stop"), "Images/AuditStart.svg", "Images/AuditStop.svg", 13, 13);
this._startStopButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
this._updateStartStopButtonNavigationItemState();
this._startStopButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleStartStopButtonNavigationItemClicked, this);
- navigationBar.addNavigationItem(this._startStopButtonNavigationItem);
+ controlsNavigationBar.addNavigationItem(this._startStopButtonNavigationItem);
- navigationBar.addNavigationItem(new WI.DividerNavigationItem);
+ controlsNavigationBar.addNavigationItem(new WI.DividerNavigationItem);
let importButtonNavigationItem = new WI.ButtonNavigationItem("audit-import", WI.UIString("Import"), "Images/Import.svg", 15, 15);
importButtonNavigationItem.buttonStyle = WI.ButtonNavigationItem.Style.ImageAndText;
importButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
importButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleImportButtonNavigationItemClicked, this);
- navigationBar.addNavigationItem(importButtonNavigationItem);
+ controlsNavigationBar.addNavigationItem(importButtonNavigationItem);
- this.addSubview(navigationBar);
+ this.addSubview(controlsNavigationBar);
+ let editNavigationbar = new WI.NavigationBar;
+
+ this._editButtonNavigationItem = new WI.ActivateButtonNavigationItem("edit-audits", WI.UIString("Edit"), WI.UIString("Done"));
+ this._editButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);
+ editNavigationbar.addNavigationItem(this._editButtonNavigationItem);
+
+ this.contentView.addSubview(editNavigationbar);
+
for (let test of WI.auditManager.tests)
this._addTest(test);
@@ -82,6 +104,7 @@
this._addResult(result, i);
});
+ WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleAuditManagerEditingChanged, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestAdded, this._handleAuditTestAdded, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditTestCompleted, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestRemoved, this._handleAuditTestRemoved, this);
@@ -105,6 +128,24 @@
this._updateNoAuditsPlaceholder();
}
+ hasCustomFilters()
+ {
+ return true;
+ }
+
+ matchTreeElementAgainstCustomFilters(treeElement, flags)
+ {
+ if (WI.auditManager.editing) {
+ if (treeElement.representedObject instanceof WI.AuditTestResultBase || treeElement.hasAncestor(this._resultsFolderTreeElement) || treeElement === this._resultsFolderTreeElement)
+ return false;
+ } else {
+ if (treeElement.representedObject instanceof WI.AuditTestBase && treeElement.representedObject.disabled)
+ return false;
+ }
+
+ return super.matchTreeElementAgainstCustomFilters(treeElement, flags);
+ }
+
// Private
_addTest(test)
@@ -111,8 +152,6 @@
{
this.element.classList.add("has-tests");
- this._updateStartStopButtonNavigationItemState();
-
let treeElement = new WI.AuditTreeElement(test);
if (this._resultsFolderTreeElement) {
@@ -121,6 +160,9 @@
} else
this.contentTreeOutline.appendChild(treeElement);
+ this._updateStartStopButtonNavigationItemState();
+ this._updateEditButtonNavigationItemState();
+
this.hideEmptyContentPlaceholder();
}
@@ -128,8 +170,6 @@
{
this.element.classList.add("has-results");
- this._updateStartStopButtonNavigationItemState();
-
if (!this._resultsFolderTreeElement) {
this._resultsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Results"));
this.contentTreeOutline.appendChild(this._resultsFolderTreeElement);
@@ -144,16 +184,28 @@
}
this._resultsFolderTreeElement.appendChild(resultFolderTreeElement);
+ console.assert(this._resultsFolderTreeElement.children.length === WI.auditManager.results.length);
+
for (let resultItem of result)
resultFolderTreeElement.appendChild(new WI.AuditTreeElement(resultItem));
+
+ this._updateStartStopButtonNavigationItemState();
+ this._updateEditButtonNavigationItemState();
}
_updateStartStopButtonNavigationItemState()
{
- this._startStopButtonNavigationItem.toggled = WI.auditManager.runningState !== WI.AuditManager.RunningState.Inactive;
- this._startStopButtonNavigationItem.enabled = WI.auditManager.tests.length && WI.auditManager.runningState !== WI.AuditManager.RunningState.Stopping;
+ this._startStopButtonNavigationItem.toggled = WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping;
+ this._startStopButtonNavigationItem.enabled = WI.auditManager.tests.length && (WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive || WI.auditManager.runningState === WI.AuditManager.RunningState.Active);
}
+ _updateEditButtonNavigationItemState()
+ {
+ this._editButtonNavigationItem.label = WI.auditManager.editing ? this._editButtonNavigationItem.activatedToolTip : this._editButtonNavigationItem.defaultToolTip;
+ this._editButtonNavigationItem.activated = WI.auditManager.editing;
+ this._editButtonNavigationItem.enabled = WI.auditManager.tests.length && (WI.auditManager.editing || WI.auditManager.runningState === WI.AuditManager.RunningState.Inactive);
+ }
+
_updateNoAuditsPlaceholder()
{
if (WI.auditManager.tests.length)
@@ -176,8 +228,32 @@
// be styled such that only the button is visible.
this.contentView.element.insertBefore(contentPlaceholder, this.contentView.element.firstChild);
}
+
+ this._updateEditButtonNavigationItemState();
}
+ _handleAuditManagerEditingChanged(event)
+ {
+ if (WI.auditManager.editing) {
+ console.assert(!this._selectedTreeElementBeforeEditing);
+ this._selectedTreeElementBeforeEditing = this.contentTreeOutline.selectedTreeElement;
+ if (this._selectedTreeElementBeforeEditing)
+ this._selectedTreeElementBeforeEditing.deselect();
+ } else if (this._selectedTreeElementBeforeEditing) {
+ if (!(this._selectedTreeElementBeforeEditing.representedObject instanceof WI.AuditTestBase) || !this._selectedTreeElementBeforeEditing.representedObject.disabled)
+ this._selectedTreeElementBeforeEditing.select();
+ this._selectedTreeElementBeforeEditing = null;
+ }
+
+ if (!this.contentTreeOutline.selectedTreeElement)
+ this.showDefaultContentView();
+
+ this._updateStartStopButtonNavigationItemState();
+ this._updateEditButtonNavigationItemState();
+
+ this.updateFilter();
+ }
+
_handleAuditTestAdded(event)
{
this._addTest(event.data.test);
@@ -204,6 +280,7 @@
_handleAuditTestScheduled(event)
{
this._updateStartStopButtonNavigationItemState();
+ this._updateEditButtonNavigationItemState();
}
_treeSelectionDidChange(event)
@@ -217,6 +294,10 @@
return;
}
+ console.assert(!WI.auditManager.editing);
+ if (WI.auditManager.editing)
+ return;
+
let representedObject = treeElement.representedObject;
if (representedObject instanceof WI.AuditTestCase || representedObject instanceof WI.AuditTestGroup
|| representedObject instanceof WI.AuditTestCaseResult || representedObject instanceof WI.AuditTestGroupResult) {
@@ -241,4 +322,9 @@
{
WI.FileUtilities.importJSON((result) => WI.auditManager.processJSON(result));
}
+
+ _handleEditButtonNavigationItemClicked(event)
+ {
+ WI.auditManager.editing = !WI.auditManager.editing;
+ }
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestGroupContentView.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestGroupContentView.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/AuditTestGroupContentView.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -149,6 +149,9 @@
}
for (let subobject of this._subobjects()) {
+ if (subobject instanceof WI.AuditTestBase && subobject.disabled)
+ continue;
+
let view = WI.ContentView.contentViewForRepresentedObject(subobject);
this.contentView.addSubview(view);
view.shown();
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.css (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.css 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.css 2019-01-11 05:54:54 UTC (rev 239858)
@@ -43,12 +43,12 @@
}
.tree-outline .item.audit > .status:not(:hover) > img.show-on-hover,
-.tree-outline .item.audit.test-group.expanded > .status:not(:hover) {
+.tree-outline .item.audit.test-group.expanded:not(.editing-audits) > .status:not(:hover) {
opacity: 0;
}
.tree-outline .item.audit.manager-active > .status > img.show-on-hover,
-.tree-outline .item.audit.test-group.expanded > .status:hover > :not(img),
+.tree-outline .item.audit.test-group.expanded:not(.editing-audits) > .status:hover > :not(img),
.tree-outline .item.audit.test-group-result.expanded > .status {
display: none;
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.js (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.js 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/AuditTreeElement.js 2019-01-11 05:54:54 UTC (rev 239858)
@@ -61,6 +61,7 @@
super.onattach();
if (this.representedObject instanceof WI.AuditTestBase) {
+ this.representedObject.addEventListener(WI.AuditTestBase.Event.DisabledChanged, this._handleTestDisabledChanged, this);
this.representedObject.addEventListener(WI.AuditTestBase.Event.ResultCleared, this._handleTestResultCleared, this);
if (this.representedObject instanceof WI.AuditTestCase)
@@ -68,6 +69,7 @@
else if (this.representedObject instanceof WI.AuditTestGroup)
this.representedObject.addEventListener(WI.AuditTestBase.Event.Scheduled, this._handleTestGroupScheduled, this);
+ WI.auditManager.addEventListener(WI.AuditManager.Event.EditingChanged, this._handleManagerEditingChanged, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);
}
@@ -162,6 +164,11 @@
super.populateContextMenu(contextMenu, event);
}
+ canSelectOnMouseDown(event)
+ {
+ return !WI.auditManager.editing;
+ }
+
// Private
_start()
@@ -232,6 +239,14 @@
this.status.value = progress || 0;
}
+ _updateTestGroupDisabled()
+ {
+ this.status.checked = !this.representedObject.disabled;
+
+ if (this.representedObject instanceof WI.AuditTestGroup)
+ this.status.indeterminate = this.representedObject.tests.some((test) => test.disabled !== this.representedObject.tests[0].disabled);
+ }
+
_handleTestCaseCompleted(event)
{
this.representedObject.removeEventListener(WI.AuditTestBase.Event.Completed, this._handleTestCaseCompleted, this);
@@ -239,6 +254,12 @@
this._updateLevel();
}
+ _handleTestDisabledChanged(event)
+ {
+ if (this.status instanceof HTMLInputElement && this.status.type === "checkbox")
+ this._updateTestGroupDisabled();
+ }
+
_handleTestResultCleared(event)
{
this._updateLevel();
@@ -273,6 +294,24 @@
this._showRunningProgress();
}
+ _handleManagerEditingChanged(event)
+ {
+ if (WI.auditManager.editing) {
+ this.status = document.createElement("input");
+ this.status.type = "checkbox";
+ this._updateTestGroupDisabled();
+ this.status.addEventListener("change", () => {
+ this.representedObject.disabled = !this.representedObject.disabled;
+ });
+
+ this.addClassName("editing-audits");
+ } else {
+ this.removeClassName("editing-audits");
+
+ this._updateLevel();
+ }
+ }
+
_handleAuditManagerTestScheduled(event)
{
this.addClassName("manager-active");
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css (239857 => 239858)
--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css 2019-01-11 04:46:23 UTC (rev 239857)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css 2019-01-11 05:54:54 UTC (rev 239858)
@@ -40,7 +40,7 @@
display: none;
}
-.tree-outline .children.expanded {
+.tree-outline .children.expanded:not([hidden]) {
display: block;
}