summaryrefslogtreecommitdiffstats
path: root/devtools/shared/commands/resource/tests/browser_resources_css_changes.js
blob: 22b11a8186c8ca389040960d035c78616d1286aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

// Test the ResourceCommand API around CSS_CHANGE.

add_task(async function () {
  // Open a test tab
  const tab = await addTab(
    "data:text/html,<body style='color: lime;'>CSS Changes</body>"
  );

  const { client, resourceCommand, targetCommand } = await initResourceCommand(
    tab
  );

  // CSS_CHANGE watcher doesn't record modification made before watching,
  // so we have to start watching before doing any DOM mutation.
  await resourceCommand.watchResources([resourceCommand.TYPES.CSS_CHANGE], {
    onAvailable: () => {},
  });

  const { walker } = await targetCommand.targetFront.getFront("inspector");
  const nodeList = await walker.querySelectorAll(walker.rootNode, "body");
  const body = (await nodeList.items())[0];
  const style = (
    await body.inspectorFront.pageStyle.getApplied(body, {
      skipPseudo: false,
    })
  )[0];

  info(
    "Check whether ResourceCommand catches CSS change that fired before starting to watch"
  );
  await setProperty(style.rule, 0, "color", "black");

  const availableResources = [];
  await resourceCommand.watchResources([resourceCommand.TYPES.CSS_CHANGE], {
    onAvailable: resources => availableResources.push(...resources),
  });
  assertResource(
    availableResources[0],
    { index: 0, property: "color", value: "black" },
    { index: 0, property: "color", value: "lime" }
  );

  info(
    "Check whether ResourceCommand catches CSS changes after the property was renamed and updated"
  );

  // RuleRewriter:apply will not support a simultaneous rename + setProperty.
  // Doing so would send inconsistent arguments to StyleRuleActor:setRuleText,
  // the CSS text for the rule will not match the list of modifications, which
  // would desynchronize the Changes view. Thankfully this scenario should not
  // happen when using the UI to update the rules.
  await renameProperty(style.rule, 0, "color", "background-color");
  await waitUntil(() => availableResources.length === 2);
  assertResource(
    availableResources[1],
    { index: 0, property: "background-color", value: "black" },
    { index: 0, property: "color", value: "black" }
  );

  await setProperty(style.rule, 0, "background-color", "pink");
  await waitUntil(() => availableResources.length === 3);
  assertResource(
    availableResources[2],
    { index: 0, property: "background-color", value: "pink" },
    { index: 0, property: "background-color", value: "black" }
  );

  info("Check whether ResourceCommand catches CSS change of disabling");
  await setPropertyEnabled(style.rule, 0, "background-color", false);
  await waitUntil(() => availableResources.length === 4);
  assertResource(availableResources[3], null, {
    index: 0,
    property: "background-color",
    value: "pink",
  });

  info("Check whether ResourceCommand catches CSS change of new property");
  await createProperty(style.rule, 1, "font-size", "100px");
  await waitUntil(() => availableResources.length === 5);
  assertResource(
    availableResources[4],
    { index: 1, property: "font-size", value: "100px" },
    null
  );

  info("Check whether ResourceCommand sends all resources added in this test");
  const existingResources = [];
  await resourceCommand.watchResources([resourceCommand.TYPES.CSS_CHANGE], {
    onAvailable: resources => existingResources.push(...resources),
  });
  await waitUntil(() => existingResources.length === 5);
  is(availableResources[0], existingResources[0], "1st resource is correct");
  is(availableResources[1], existingResources[1], "2nd resource is correct");
  is(availableResources[2], existingResources[2], "3rd resource is correct");
  is(availableResources[3], existingResources[3], "4th resource is correct");
  is(availableResources[4], existingResources[4], "4th resource is correct");

  targetCommand.destroy();
  await client.close();
});

function assertResource(resource, expectedAddedChange, expectedRemovedChange) {
  if (expectedAddedChange) {
    is(resource.add.length, 1, "The number of added changes is correct");
    assertChange(resource.add[0], expectedAddedChange);
  } else {
    is(resource.add, null, "There is no added changes");
  }

  if (expectedRemovedChange) {
    is(resource.remove.length, 1, "The number of removed changes is correct");
    assertChange(resource.remove[0], expectedRemovedChange);
  } else {
    is(resource.remove, null, "There is no removed changes");
  }
}

function assertChange(change, expected) {
  is(change.index, expected.index, "The index of change is correct");
  is(change.property, expected.property, "The property of change is correct");
  is(change.value, expected.value, "The value of change is correct");
}

async function setProperty(rule, index, property, value) {
  const modifications = rule.startModifyingProperties({ isKnown: true });
  modifications.setProperty(index, property, value, "");
  await modifications.apply();
}

async function renameProperty(rule, index, oldName, newName, value) {
  const modifications = rule.startModifyingProperties({ isKnown: true });
  modifications.renameProperty(index, oldName, newName);
  await modifications.apply();
}

async function createProperty(rule, index, property, value) {
  const modifications = rule.startModifyingProperties({ isKnown: true });
  modifications.createProperty(index, property, value, "", true);
  await modifications.apply();
}

async function setPropertyEnabled(rule, index, property, isEnabled) {
  const modifications = rule.startModifyingProperties({ isKnown: true });
  modifications.setPropertyEnabled(index, property, isEnabled);
  await modifications.apply();
}