mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1022725: add a mock httpd.js Translation provider for tests. r=florian,felipe
This commit is contained in:
parent
e5e972ff8a
commit
30a432a6e1
218
browser/components/translation/test/bing.sjs
Normal file
218
browser/components/translation/test/bing.sjs
Normal file
@ -0,0 +1,218 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, Constructor: CC} = Components;
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
|
||||
function handleRequest(req, res) {
|
||||
try {
|
||||
reallyHandleRequest(req, res);
|
||||
} catch (ex) {
|
||||
res.setStatusLine("1.0", 200, "AlmostOK");
|
||||
let msg = "Error handling request: " + ex + "\n" + ex.stack;
|
||||
log(msg);
|
||||
res.write(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function log(msg) {
|
||||
// dump("BING-SERVER-MOCK: " + msg + "\n");
|
||||
}
|
||||
|
||||
const statusCodes = {
|
||||
400: "Bad Request",
|
||||
401: "Unauthorized",
|
||||
403: "Forbidden",
|
||||
404: "Not Found",
|
||||
405: "Method Not Allowed",
|
||||
500: "Internal Server Error",
|
||||
501: "Not Implemented",
|
||||
503: "Service Unavailable"
|
||||
};
|
||||
|
||||
function HTTPError(code = 500, message) {
|
||||
this.code = code;
|
||||
this.name = statusCodes[code] || "HTTPError";
|
||||
this.message = message || this.name;
|
||||
}
|
||||
HTTPError.prototype = new Error();
|
||||
HTTPError.prototype.constructor = HTTPError;
|
||||
|
||||
function sendError(res, err) {
|
||||
if (!(err instanceof HTTPError)) {
|
||||
err = new HTTPError(typeof err == "number" ? err : 500,
|
||||
err.message || typeof err == "string" ? err : "");
|
||||
}
|
||||
res.setStatusLine("1.1", err.code, err.name);
|
||||
res.write(err.message);
|
||||
}
|
||||
|
||||
function parseQuery(query) {
|
||||
let ret = {};
|
||||
for (let param of query.replace(/^[?&]/, "").split("&")) {
|
||||
param = param.split("=");
|
||||
if (!param[0])
|
||||
continue;
|
||||
ret[unescape(param[0])] = unescape(param[1]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getRequestBody(req) {
|
||||
let avail;
|
||||
let bytes = [];
|
||||
let body = new BinaryInputStream(req.bodyInputStream);
|
||||
|
||||
while ((avail = body.available()) > 0)
|
||||
Array.prototype.push.apply(bytes, body.readByteArray(avail));
|
||||
|
||||
return String.fromCharCode.apply(null, bytes);
|
||||
}
|
||||
|
||||
function sha1(str) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
// `result` is an out parameter, `result.value` will contain the array length.
|
||||
let result = {};
|
||||
// `data` is an array of bytes.
|
||||
let data = converter.convertToByteArray(str, result);
|
||||
let ch = Cc["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Ci.nsICryptoHash);
|
||||
ch.init(ch.SHA1);
|
||||
ch.update(data, data.length);
|
||||
let hash = ch.finish(false);
|
||||
|
||||
// Return the two-digit hexadecimal code for a byte.
|
||||
function toHexString(charCode) {
|
||||
return ("0" + charCode.toString(16)).slice(-2);
|
||||
}
|
||||
|
||||
// Convert the binary hash data to a hex string.
|
||||
return [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");
|
||||
}
|
||||
|
||||
function parseXml(body) {
|
||||
let DOMParser = Cc["@mozilla.org/xmlextras/domparser;1"]
|
||||
.createInstance(Ci.nsIDOMParser);
|
||||
let xml = DOMParser.parseFromString(body, "text/xml");
|
||||
if (xml.documentElement.localName == "parsererror")
|
||||
throw new Error("Invalid XML");
|
||||
return xml;
|
||||
}
|
||||
|
||||
function getInputStream(path) {
|
||||
let file = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
.get("CurWorkD", Ci.nsILocalFile);
|
||||
for (let part of path.split("/"))
|
||||
file.append(part);
|
||||
let fileStream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fileStream.init(file, 1, 0, false);
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
function checkAuth(req) {
|
||||
let err = new Error("Authorization failed");
|
||||
err.code = 401;
|
||||
|
||||
if (!req.hasHeader("Authorization"))
|
||||
throw new HTTPError(401, "No Authorization header provided.");
|
||||
|
||||
let auth = req.getHeader("Authorization");
|
||||
if (!auth.startsWith("Bearer "))
|
||||
throw new HTTPError(401, "Invalid Authorization header content: '" + auth + "'");
|
||||
}
|
||||
|
||||
function reallyHandleRequest(req, res) {
|
||||
log("method: " + req.method);
|
||||
if (req.method != "POST") {
|
||||
sendError(res, "Bing only deals with POST requests, not '" + req.method + "'.");
|
||||
return;
|
||||
}
|
||||
|
||||
let body = getRequestBody(req);
|
||||
log("body: " + body);
|
||||
|
||||
// First, we'll see if we're dealing with an XML body:
|
||||
let contentType = req.hasHeader("Content-Type") ? req.getHeader("Content-Type") : null;
|
||||
log("contentType: " + contentType);
|
||||
|
||||
if (contentType == "text/xml") {
|
||||
try {
|
||||
// For all these requests the client needs to supply the correct
|
||||
// authentication headers.
|
||||
checkAuth(req);
|
||||
|
||||
let xml = parseXml(body);
|
||||
let method = xml.documentElement.localName;
|
||||
log("invoking method: " + method);
|
||||
// If the requested method is supported, delegate it to its handler.
|
||||
if (methodHandlers[method])
|
||||
methodHandlers[method](res, xml);
|
||||
else
|
||||
throw new HTTPError(501);
|
||||
} catch (ex) {
|
||||
sendError(res, ex, ex.code);
|
||||
}
|
||||
} else {
|
||||
// Not XML, so it must be a query-string.
|
||||
let params = parseQuery(body);
|
||||
|
||||
// Delegate an authentication request to the correct handler.
|
||||
if ("grant_type" in params && params.grant_type == "client_credentials")
|
||||
methodHandlers.authenticate(res, params);
|
||||
else
|
||||
sendError(res, 501);
|
||||
}
|
||||
}
|
||||
|
||||
const methodHandlers = {
|
||||
authenticate: function(res, params) {
|
||||
// Validate a few required parameters.
|
||||
if (params.scope != "http://api.microsofttranslator.com") {
|
||||
sendError(res, "Invalid scope.");
|
||||
return;
|
||||
}
|
||||
if (!params.client_id) {
|
||||
sendError(res, "Missing client_id param.");
|
||||
return;
|
||||
}
|
||||
if (!params.client_secret) {
|
||||
sendError(res, "Missing client_secret param.");
|
||||
return;
|
||||
}
|
||||
|
||||
let content = JSON.stringify({
|
||||
access_token: "test",
|
||||
expires_in: 600
|
||||
});
|
||||
|
||||
res.setStatusLine("1.1", 200, "OK");
|
||||
res.setHeader("Content-Length", String(content.length));
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.write(content);
|
||||
},
|
||||
|
||||
TranslateArrayRequest: function(res, xml, body) {
|
||||
let from = xml.querySelector("From").firstChild.nodeValue;
|
||||
let to = xml.querySelector("To").firstChild.nodeValue
|
||||
log("translating from '" + from + "' to '" + to + "'");
|
||||
|
||||
res.setStatusLine("1.1", 200, "OK");
|
||||
res.setHeader("Content-Type", "text/xml");
|
||||
|
||||
let hash = sha1(body).substr(0, 10);
|
||||
log("SHA1 hash of content: " + hash);
|
||||
let inputStream = getInputStream(
|
||||
"browser/browser/components/translation/test/fixtures/result-" + hash + ".txt");
|
||||
res.bodyOutputStream.writeFrom(inputStream, inputStream.available());
|
||||
inputStream.close();
|
||||
}
|
||||
};
|
@ -1,6 +1,10 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
bing.sjs
|
||||
fixtures/bug1022725-fr.html
|
||||
fixtures/result-da39a3ee5e.txt
|
||||
|
||||
[browser_translation_bing.js]
|
||||
[browser_translation_fhr.js]
|
||||
skip-if = true # Needs to wait until bug 1022725.
|
||||
[browser_translation_infobar.js]
|
||||
[browser_translation_exceptions.js]
|
||||
|
@ -0,0 +1,56 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Test the Bing Translator client against a mock Bing service, bing.sjs.
|
||||
|
||||
"use strict";
|
||||
|
||||
const kClientIdPref = "browser.translation.bing.clientIdOverride";
|
||||
const kClientSecretPref = "browser.translation.bing.apiKeyOverride";
|
||||
|
||||
const {BingTranslator} = Cu.import("resource:///modules/translation/BingTranslator.jsm", {});
|
||||
const {TranslationDocument} = Cu.import("resource:///modules/translation/TranslationDocument.jsm", {});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setCharPref(kClientIdPref, "testClient");
|
||||
Services.prefs.setCharPref(kClientSecretPref, "testSecret");
|
||||
|
||||
// Deduce the Mochitest server address in use from a pref that was pre-processed.
|
||||
let server = Services.prefs.getCharPref("browser.translation.bing.authURL")
|
||||
.replace("http://", "");
|
||||
server = server.substr(0, server.indexOf("/"));
|
||||
let tab = gBrowser.addTab("http://" + server +
|
||||
"/browser/browser/components/translation/test/fixtures/bug1022725-fr.html");
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.removeTab(tab);
|
||||
Services.prefs.clearUserPref(kClientIdPref);
|
||||
Services.prefs.clearUserPref(kClientSecretPref);
|
||||
});
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
browser.addEventListener("load", function onload() {
|
||||
if (browser.currentURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
browser.removeEventListener("load", onload, true);
|
||||
let client = new BingTranslator(
|
||||
new TranslationDocument(browser.contentDocument), "fr", "en");
|
||||
|
||||
client.translate().then(
|
||||
result => {
|
||||
// XXXmikedeboer; here you would continue the test/ content inspection.
|
||||
ok(result, "There should be a result.");
|
||||
finish();
|
||||
},
|
||||
error => {
|
||||
ok(false, "Unexpected Client Error: " + error);
|
||||
finish();
|
||||
}
|
||||
);
|
||||
}, true);
|
||||
}
|
@ -57,7 +57,8 @@ function retrieveTranslationCounts() {
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
return [day.get("pageTranslatedCount"), day.get("charactersTranslatedCount")];
|
||||
// .get() may return `undefined`, which we can't compute.
|
||||
return [day.get("pageTranslatedCount") || 0, day.get("charactersTranslatedCount") || 0];
|
||||
});
|
||||
}
|
||||
|
||||
|
15
browser/components/translation/test/fixtures/bug1022725-fr.html
vendored
Normal file
15
browser/components/translation/test/fixtures/bug1022725-fr.html
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<!--
|
||||
- Text retrieved from http://fr.wikipedia.org/wiki/Coupe_du_monde_de_football_de_2014
|
||||
- at 06/13/2014, Creative Commons Attribution-ShareAlike License.
|
||||
-->
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Coupe du monde de football de 2014</h1>
|
||||
<div>La Coupe du monde de football de 2014 est la 20e édition de la Coupe du monde de football, compétition organisée par la FIFA et qui réunit les trente-deux meilleures sélections nationales. Sa phase finale a lieu à l'été 2014 au Brésil. Avec le pays organisateur, toutes les équipes championnes du monde depuis 1930 (Uruguay, Italie, Allemagne, Angleterre, Argentine, France et Espagne) se sont qualifiées pour cette compétition. Elle est aussi la première compétition internationale de la Bosnie-Herzégovine.</div>
|
||||
</body>
|
||||
</html>
|
22
browser/components/translation/test/fixtures/result-da39a3ee5e.txt
vendored
Normal file
22
browser/components/translation/test/fixtures/result-da39a3ee5e.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<ArrayOfTranslateArrayResponse xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<TranslateArrayResponse>
|
||||
<From>fr</From>
|
||||
<OriginalTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
|
||||
<a:int>34</a:int>
|
||||
</OriginalTextSentenceLengths>
|
||||
<TranslatedText>Football's 2014 World Cup</TranslatedText>
|
||||
<TranslatedTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
|
||||
<a:int>25</a:int>
|
||||
</TranslatedTextSentenceLengths>
|
||||
</TranslateArrayResponse>
|
||||
<TranslateArrayResponse>
|
||||
<From>fr</From>
|
||||
<OriginalTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
|
||||
<a:int>508</a:int>
|
||||
</OriginalTextSentenceLengths>
|
||||
<TranslatedText>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus diam sem, porttitor eget neque sit amet, ultricies posuere metus. Cras placerat rutrum risus, nec dignissim magna dictum vitae. Fusce eleifend fermentum lacinia. Nulla sagittis cursus nibh. Praesent adipiscing, elit at pulvinar dapibus, neque massa tincidunt sapien, eu consectetur lectus metus sit amet odio. Proin blandit consequat porttitor. Pellentesque vehicula justo sed luctus vestibulum. Donec metus.</TranslatedText>
|
||||
<TranslatedTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
|
||||
<a:int>475</a:int>
|
||||
</TranslatedTextSentenceLengths>
|
||||
</TranslateArrayResponse>
|
||||
</ArrayOfTranslateArrayResponse>
|
@ -200,3 +200,7 @@ user_pref('identity.fxaccounts.auth.uri', 'https://%(server)s/fxa-dummy/');
|
||||
|
||||
// Enable logging of APZ test data (see bug 961289).
|
||||
user_pref('apz.test.logging_enabled', true);
|
||||
|
||||
// Make sure Translation won't hit the network.
|
||||
user_pref("browser.translation.bing.authURL", "http://%(server)s/browser/browser/components/translation/test/bing.sjs");
|
||||
user_pref("browser.translation.bing.translateArrayURL", "http://%(server)s/browser/browser/components/translation/test/bing.sjs");
|
||||
|
Loading…
Reference in New Issue
Block a user