Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit d6b38f2

Browse files
author
Zibi Braniecki
committed
Bug 1503657 - Land DOMOverlays tests prior to switch to C++. r=Pike
Differential Revision: https://phabricator.services.mozilla.com/D27199 --HG-- extra : moz-landing-system : lando
1 parent 778dc43 commit d6b38f2

9 files changed

Lines changed: 747 additions & 0 deletions

dom/l10n/moz.build

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
2+
# vim: set filetype=python:
3+
# This Source Code Form is subject to the terms of the Mozilla Public
4+
# License, v. 2.0. If a copy of the MPL was not distributed with this
5+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
7+
with Files("**"):
8+
BUG_COMPONENT = ("Core", "Internationalization")
9+
10+
MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[test_domoverlays_attributes.html]
2+
[test_domoverlays_functional_children.html]
3+
[test_domoverlays_text_children.html]
4+
[test_domoverlays_extra_text_markup.html]
5+
[test_domoverlays.xul]
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?xml version="1.0"?>
2+
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
3+
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
4+
type="text/css"?>
5+
6+
7+
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
8+
xmlns:html="http://www.w3.org/1999/xhtml"
9+
title="Testing DocumentL10n in XUL environment">
10+
11+
<linkset>
12+
<html:link rel="localization" href="toolkit/about/aboutAddons.ftl"/>
13+
</linkset>
14+
15+
<script type="application/javascript"
16+
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
17+
<script type="application/javascript">
18+
<![CDATA[
19+
const {DOMLocalization} = ChromeUtils.import("resource://gre/modules/DOMLocalization.jsm");
20+
21+
function elem(name) {
22+
return function(str) {
23+
const element = document.createElement(name);
24+
// eslint-disable-next-line no-unsanitized/property
25+
element.innerHTML = str;
26+
return element;
27+
};
28+
}
29+
30+
const { translateElement } = DOMLocalization.DOMOverlays;
31+
32+
SimpleTest.waitForExplicitFinish();
33+
34+
{
35+
// Allowed attribute
36+
const element = elem("description")``;
37+
const translation = {
38+
value: null,
39+
attributes: [
40+
{name: "title", value: "FOO"},
41+
],
42+
};
43+
translateElement(element, translation);
44+
is(element.outerHTML, '<description xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="FOO"/>');
45+
}
46+
47+
document.addEventListener("DOMContentLoaded", () => {
48+
{
49+
// Handle HTML translation
50+
const element = document.getElementById("test2");
51+
const translation = {
52+
value: "This is <a data-l10n-name=\"link\">a link</a>.",
53+
attributes: null,
54+
};
55+
translateElement(element, translation);
56+
is(element.innerHTML, 'This is <html:a xmlns:html="http://www.w3.org/1999/xhtml" data-l10n-name=\"link\" href="https://www.mozilla.org\">a link</html:a>.');
57+
}
58+
59+
{
60+
// Don't handle XUL translation
61+
//
62+
// Current iteration of DOMOverlays will replace
63+
// XUL elements from translation with text.
64+
//
65+
// See bug 1545704 for details.
66+
const element = document.getElementById("test3");
67+
const translation = {
68+
value: "This is <description data-l10n-name=\"desc\">a desc</description>.",
69+
attributes: null,
70+
};
71+
translateElement(element, translation);
72+
is(element.innerHTML, 'This is a desc.');
73+
}
74+
SimpleTest.finish();
75+
}, {once: true});
76+
77+
]]>
78+
</script>
79+
80+
<description id="test2">
81+
<html:a data-l10n-name="link" href="https://www.mozilla.org"/>
82+
</description>
83+
84+
<box id="test3">
85+
<description data-l10n-name="desc"/>
86+
</box>
87+
</window>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Test DOMOverlays Top-level attributes</title>
6+
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
7+
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
8+
<script type="application/javascript">
9+
"use strict";
10+
11+
const {DOMLocalization} = ChromeUtils.import("resource://gre/modules/DOMLocalization.jsm");
12+
13+
function elem(name) {
14+
return function(str) {
15+
const element = document.createElement(name);
16+
// eslint-disable-next-line no-unsanitized/property
17+
element.innerHTML = str;
18+
return element;
19+
};
20+
}
21+
22+
const { translateElement } = DOMLocalization.DOMOverlays;
23+
24+
{
25+
// Allowed attribute
26+
const element = elem("div")``;
27+
const translation = {
28+
value: null,
29+
attributes: [
30+
{name: "title", value: "FOO"},
31+
],
32+
};
33+
translateElement(element, translation);
34+
is(element.outerHTML, '<div title="FOO"></div>');
35+
}
36+
37+
{
38+
// Forbidden attribute
39+
const element = elem("input")``;
40+
const translation = {
41+
value: null,
42+
attributes: [
43+
{name: "disabled", value: "DISABLED"},
44+
],
45+
};
46+
translateElement(element, translation);
47+
is(element.outerHTML, "<input>");
48+
}
49+
50+
{
51+
// Attributes do not leak on first translation
52+
const element = elem("div")`Foo`;
53+
element.setAttribute("title", "Title");
54+
55+
const translation = {
56+
value: "FOO",
57+
attributes: null,
58+
};
59+
translateElement(element, translation);
60+
is(element.outerHTML, "<div>FOO</div>");
61+
}
62+
63+
{
64+
// Attributes do not leak on retranslation
65+
const element = elem("div")`Foo`;
66+
67+
const translationA = {
68+
value: "FOO A",
69+
attributes: [
70+
{name: "title", value: "TITLE A"},
71+
],
72+
};
73+
74+
const translationB = {
75+
value: "FOO B",
76+
attributes: null,
77+
};
78+
translateElement(element, translationA);
79+
is(element.outerHTML, '<div title="TITLE A">FOO A</div>');
80+
translateElement(element, translationB);
81+
is(element.outerHTML, "<div>FOO B</div>");
82+
}
83+
</script>
84+
</head>
85+
<body>
86+
</body>
87+
</html>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<!DOCTYPE HTML>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Test DOMOverlays Localized text markup</title>
6+
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
7+
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
8+
<script type="application/javascript">
9+
"use strict";
10+
11+
const {DOMLocalization} = ChromeUtils.import("resource://gre/modules/DOMLocalization.jsm");
12+
13+
function elem(name) {
14+
return function(str) {
15+
const element = document.createElement(name);
16+
// eslint-disable-next-line no-unsanitized/property
17+
element.innerHTML = str;
18+
return element;
19+
};
20+
}
21+
22+
const { translateElement } = DOMLocalization.DOMOverlays;
23+
24+
// Localized text markup
25+
{
26+
// allowed element
27+
const element = elem("div")`Foo`;
28+
const translation = {
29+
value: "FOO <em>BAR</em> BAZ",
30+
attributes: null,
31+
};
32+
33+
translateElement(element, translation);
34+
is(element.innerHTML, "FOO <em>BAR</em> BAZ");
35+
}
36+
37+
{
38+
// forbidden element
39+
const element = elem("div")`Foo`;
40+
const translation = {
41+
value: 'FOO <img src="img.png" />',
42+
attributes: null,
43+
};
44+
45+
translateElement(element, translation);
46+
is(element.innerHTML, "FOO ");
47+
}
48+
49+
{
50+
// forbiden element with text
51+
const element = elem("div")`Foo`;
52+
const translation = {
53+
value: "FOO <a>a</a>",
54+
attributes: null,
55+
};
56+
57+
translateElement(element, translation);
58+
is(element.innerHTML, "FOO a");
59+
}
60+
61+
{
62+
// nested HTML is forbidden
63+
const element = elem("div")`Foo`;
64+
const translation = {
65+
value: "FOO <em><strong>BAR</strong></em> BAZ",
66+
attributes: null,
67+
};
68+
69+
translateElement(element, translation);
70+
is(element.innerHTML, "FOO <em>BAR</em> BAZ");
71+
}
72+
73+
// Attributes of localized text markup
74+
{
75+
// allowed attribute
76+
const element = elem("div")`Foo Bar`;
77+
const translation = {
78+
value: 'FOO <em title="BAR">BAR</em>',
79+
attributes: null,
80+
};
81+
82+
translateElement(element, translation);
83+
is(element.innerHTML,
84+
'FOO <em title="BAR">BAR</em>');
85+
}
86+
87+
{
88+
// forbidden attribute
89+
const element = elem("div")`Foo Bar`;
90+
const translation = {
91+
value: 'FOO <em class="BAR" title="BAR">BAR</em>',
92+
attributes: null,
93+
};
94+
95+
translateElement(element, translation);
96+
is(element.innerHTML,
97+
'FOO <em title="BAR">BAR</em>');
98+
}
99+
100+
{
101+
// attributes do not leak on first translation
102+
const element = elem("div")`
103+
<em title="Foo">Foo</a>`;
104+
const translation = {
105+
value: "<em>FOO</em>",
106+
attributes: null,
107+
};
108+
109+
translateElement(element, translation);
110+
is(element.innerHTML,
111+
"<em>FOO</em>");
112+
}
113+
114+
{
115+
// attributes do not leak on retranslation
116+
const element = elem("div")``;
117+
const translationA = {
118+
value: '<em title="FOO A">FOO A</em>',
119+
attributes: null,
120+
};
121+
const translationB = {
122+
value: "<em>FOO B</em>",
123+
attributes: null,
124+
};
125+
126+
translateElement(element, translationA);
127+
is(element.innerHTML,
128+
'<em title="FOO A">FOO A</em>');
129+
translateElement(element, translationB);
130+
is(element.innerHTML,
131+
"<em>FOO B</em>");
132+
}
133+
</script>
134+
</head>
135+
<body>
136+
</body>
137+
</html>

0 commit comments

Comments
 (0)