--- a/devtools/client/inspector/animation/test/browser_animation_animation-list.js+++ b/devtools/client/inspector/animation/test/browser_animation_animation-list.js@@ -12,22 +12,13 @@ add_task(async function() { info("Checking animation list and items existence"); ok(panel.querySelector(".animation-list"), "The animation-list is in the DOM"); is(panel.querySelectorAll(".animation-list .animation-item").length, animationInspector.state.animations.length, "The number of animations displayed matches the number of animations");- info("Checking the background color for the animation list items");- const animationItemEls = panel.querySelectorAll(".animation-list .animation-item");- const evenColor =- panel.ownerGlobal.getComputedStyle(animationItemEls[0]).backgroundColor;- const oddColor =- panel.ownerGlobal.getComputedStyle(animationItemEls[1]).backgroundColor;- isnot(evenColor, oddColor,- "Background color of an even animation should be different from odd");- info("Checking list and items existence after select a element which has an animation"); await selectNodeAndWaitForAnimations(".animated", inspector); is(panel.querySelectorAll(".animation-list .animation-item").length, 1, "The number of animations displayed should be 1 for .animated element"); });

new file mode 100644--- /dev/null+++ b/devtools/client/inspector/animation/test/browser_animation_animation-list_one-animation-select.js@@ -0,0 +1,22 @@+/* Any copyright is dedicated to the Public Domain.+ http://creativecommons.org/publicdomain/zero/1.0/ */++"use strict";++// Test whether the animation item has been selected from first time+// if count of the animations is one.++add_task(async function() {+ await addTab(URL_ROOT + "doc_simple_animation.html");+ await removeAnimatedElementsExcept([".animated"]);+ const { panel } = await openAnimationInspector();++ info("Checking whether an item element has been selected");+ is(panel.querySelector(".animation-item").classList.contains("selected"), true,+ "The animation item should have 'selected' class");++ info("Checking whether the element will be unselected after closing the detail pane");+ clickOnDetailCloseButton(panel);+ is(panel.querySelector(".animation-item").classList.contains("selected"), false,+ "The animation item should not have 'selected' class");+});

--- a/taskcluster/taskgraph/actions/util.py+++ b/taskcluster/taskgraph/actions/util.py@@ -106,35 +106,40 @@ def create_task_from_def(task_id, task_d def update_parent(task, graph): task.task.setdefault('extra', {})['parent'] = os.environ.get('TASK_ID', '') return task def create_tasks(to_run, full_task_graph, label_to_taskid,- params, decision_task_id=None, suffix=''):+ params, decision_task_id=None, suffix='', modifier=lambda t: t): """Create new tasks. The task definition will have {relative-datestamp': '..'} rendered just like in a decision task. Action callbacks should use this function to create new tasks, allowing easy debugging with `mach taskgraph action-callback --test`. This builds up all required tasks to run in order to run the tasks requested.+ Optionally this function takes a `modifier` function that is passed in each+ task before it is put into a new graph. It should return a valid task. Note+ that this is passed _all_ tasks in the graph, not just the set in to_run. You+ may want to skip modifying tasks not in your to_run list.+ If you wish to create the tasks in a new group, leave out decision_task_id.""" if suffix != '': suffix = '-{}'.format(suffix) to_run = set(to_run) # Copy to avoid side-effects later full_task_graph = copy.deepcopy(full_task_graph) label_to_taskid = label_to_taskid.copy() target_graph = full_task_graph.graph.transitive_closure(to_run) target_task_graph = TaskGraph(- {l: full_task_graph[l] for l in target_graph.nodes},+ {l: modifier(full_task_graph[l]) for l in target_graph.nodes}, target_graph) target_task_graph.for_each_task(update_parent) optimized_task_graph, label_to_taskid = optimize_task_graph(target_task_graph, params, to_run, label_to_taskid) write_artifact('task-graph{}.json'.format(suffix), optimized_task_graph.to_json()) write_artifact('label-to-taskid{}.json'.format(suffix), label_to_taskid)

--- a/taskcluster/taskgraph/task.py+++ b/taskcluster/taskgraph/task.py@@ -16,17 +16,17 @@ class Task(object): - optimization: optimization to apply to the task (see taskgraph.optimize) - dependencies: tasks this one depends on, in the form {name: label}, for example {'build': 'build-linux64/opt', 'docker-image': 'build-docker-image-desktop-test'} And later, as the task-graph processing proceeds: - task_id -- TaskCluster taskId under which this task will be created- This class is just a convenience wraper for the data type and managing+ This class is just a convenience wrapper for the data type and managing display, comparison, serialization, etc. It has no functionality of its own. """ def __init__(self, kind, label, attributes, task, optimization=None, dependencies=None): self.kind = kind self.label = label self.attributes = attributes self.task = task