summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/changes/test/browser_changes_declaration_edit_value.js
blob: 588513a2748906417da34fd933a090194218cb87 (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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* Any copyright is dedicated to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

// Test that editing the value of a CSS declaration in the Rule view is tracked.

const TEST_URI = `
  <style type='text/css'>
    div {
      color: red;
      font-family: "courier";
    }
  </style>
  <div>test</div>
`;

/*
  This object contains iteration steps to modify various CSS properties of the
  test element, keyed by property name,.
  Each value is an array which will be iterated over in order and the `value`
  property will be used to update the value of the property.
  The `add` and `remove` objects hold the expected values of the tracked declarations
  shown in the Changes panel. If `add` or `remove` are null, it means we don't expect
  any corresponding tracked declaration to show up in the Changes panel.
 */
const ITERATIONS = {
  color: [
    // No changes should be tracked if the value did not actually change.
    {
      value: "red",
      add: null,
      remove: null,
    },
    // Changing the priority flag "!important" should be tracked.
    {
      value: "red !important",
      add: { value: "red !important" },
      remove: { value: "red" },
    },
    // Repeated changes should still show the original value as the one removed.
    {
      value: "blue",
      add: { value: "blue" },
      remove: { value: "red" },
    },
    // Restoring the original value should clear tracked changes.
    {
      value: "red",
      add: null,
      remove: null,
    },
  ],
  "font-family": [
    // Set a value with an opening quote, missing the closing one.
    // The closing quote should still appear in the "add" value.
    {
      value: '"ar',
      add: { value: '"ar"' },
      remove: { value: '"courier"' },
      // For some reason we need an additional flush the first time we set a
      // value with a quote. Since the ruleview is manually flushed when opened
      // openRuleView, we need to pass this information all the way down to the
      // setProperty helper.
      needsExtraFlush: true,
    },
    // Add an escaped character
    {
      value: '"ar\\i',
      add: { value: '"ar\\i"' },
      remove: { value: '"courier"' },
    },
    // Add some more text
    {
      value: '"ar\\ia',
      add: { value: '"ar\\ia"' },
      remove: { value: '"courier"' },
    },
    // Remove the backslash
    {
      value: '"aria',
      add: { value: '"aria"' },
      remove: { value: '"courier"' },
    },
    // Add the rest of the text, still no closing quote
    {
      value: '"arial',
      add: { value: '"arial"' },
      remove: { value: '"courier"' },
    },
    // Restoring the original value should clear tracked changes.
    {
      value: '"courier"',
      add: null,
      remove: null,
    },
  ],
};

add_task(async function () {
  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
  const { inspector, view: ruleView } = await openRuleView();
  const { document: doc, store } = selectChangesView(inspector);

  await selectNode("div", inspector);

  const colorProp = getTextProperty(ruleView, 1, { color: "red" });
  await assertEditValue(ruleView, doc, store, colorProp, ITERATIONS.color);

  const fontFamilyProp = getTextProperty(ruleView, 1, {
    "font-family": '"courier"',
  });
  await assertEditValue(
    ruleView,
    doc,
    store,
    fontFamilyProp,
    ITERATIONS["font-family"]
  );
});

async function assertEditValue(ruleView, doc, store, prop, iterations) {
  let onTrackChange;
  for (const { value, add, needsExtraFlush, remove } of iterations) {
    onTrackChange = waitForDispatch(store, "TRACK_CHANGE");

    info(`Change the CSS declaration value to ${value}`);
    await setProperty(ruleView, prop, value, {
      flushCount: needsExtraFlush ? 2 : 1,
    });
    info("Wait for the change to be tracked");
    await onTrackChange;

    if (add) {
      await waitFor(() => {
        const decl = getAddedDeclarations(doc);
        return decl.length == 1 && decl[0].value == add.value;
      }, "Only one declaration was tracked as added.");
      const addDecl = getAddedDeclarations(doc);
      is(
        addDecl[0].value,
        add.value,
        `Added declaration has expected value: ${add.value}`
      );
    } else {
      await waitFor(
        () => !getAddedDeclarations(doc).length,
        "Added declaration was cleared"
      );
    }

    if (remove) {
      await waitFor(
        () => getRemovedDeclarations(doc).length == 1,
        "Only one declaration was tracked as removed."
      );
      const removeDecl = getRemovedDeclarations(doc);
      is(
        removeDecl[0].value,
        remove.value,
        `Removed declaration has expected value: ${remove.value}`
      );
    } else {
      await waitFor(
        () => !getRemovedDeclarations(doc).length,
        "Removed declaration was cleared"
      );
    }
  }
}