Skip to content
This repository has been archived by the owner on Sep 4, 2023. It is now read-only.

Introducing end-to-end tests #106

Merged
merged 6 commits into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/e2etest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: End-to-End Tests
on:
push:
branches: [ main ]
schedule:
- cron: '30 1 * * *'
pull_request:
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '17.x'
- run: npm install
- run: brew install git-cinnabar
- name: Run test
run: python3 scripts/tests/e2e-tests.py
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Build](https://github.com/mozilla/firefox-translations/actions/workflows/build_main.yml/badge.svg)](https://github.com/mozilla/firefox-translations/actions/workflows/build_main.yml) [![CodeQL](https://github.com/mozilla/firefox-translations/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/mozilla/firefox-translations/actions/workflows/codeql-analysis.yml)
[![Build](https://github.com/mozilla/firefox-translations/actions/workflows/build_main.yml/badge.svg)](https://github.com/mozilla/firefox-translations/actions/workflows/build_main.yml) [![CodeQL](https://github.com/mozilla/firefox-translations/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/mozilla/firefox-translations/actions/workflows/codeql-analysis.yml) [![End-to-End Tests](https://github.com/mozilla/firefox-translations/actions/workflows/e2etest.yml/badge.svg?branch=main&event=push)](https://github.com/mozilla/firefox-translations/actions/workflows/e2etest.yml)


# Firefox Translations
Expand Down
16 changes: 16 additions & 0 deletions scripts/tests/browser.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[DEFAULT]
prefs =
# The Translations extension is disabled by default in Mochitests. We re-enable
# it here, since it's a more realistic configuration.
extensions.translations.disabled=false

[browser_translation_test.js]
support-files =
browser_translation_test.html
esen/lex.50.50.esen.s2t.bin
esen/model.esen.intgemm.alphas.bin
esen/vocab.esen.spm
enes/lex.50.50.enes.s2t.bin
enes/vocab.esen.spm
enes/model.enes.intgemm.alphas.bin
bergamot-translator-worker-with-wormhole.wasm
11 changes: 11 additions & 0 deletions scripts/tests/browser_translation_test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Translation test.</title>
</head>
<body>
<div id="translationDiv">Hola mundo. Eso es una prueba de testes de traduciones.</div>
<textarea id="mainTextarea"></textarea>
</body>
</html>
94 changes: 94 additions & 0 deletions scripts/tests/browser_translation_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* eslint-disable prefer-reflect */
/* eslint-disable no-undef */
/* eslint-disable max-lines-per-function */


const baseURL = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.com"
);

add_task(async function testTranslationBarDisplayed() {
info("Test the Translation functionality");

// open the test page.
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
`${baseURL }browser_translation_test.html`
);

/*
* the infobar is not triggered first time the page is loaded due some caching
* so we need to reload the tab in order to have it summoned. It happens only
* on mochistests.
*/
gBrowser.reloadTab(tab);

// wait for the translation bar to be displayed.
let notification = await TestUtils.waitForCondition(() => gBrowser
.getNotificationBox()
.getNotificationWithValue("fxtranslation-notification"));
ok(notification, "Translation notification bar was displayed.");

// let's make sure the selected language in the bar matches the page
const languageDropdown = notification.querySelector("[anonid=detectedLanguage]");
const selectedLanguage = languageDropdown.selectedItem.textContent;
is(selectedLanguage, "Spanish", "Detected language is in spanish");

// now that the bar was displayed, let's select the form translations checkbox
notification.querySelector("[anonid=outboundtranslations-check]").checked = true;
// and push the button to translate
let translateButton = notification.querySelector("[anonid=translate]");
translateButton.click();

// we wait until the models and engine are loaded
await TestUtils.waitForCondition(
() => {
return (
notification.querySelector("[anonid=progress-label]").value
.includes("Automatic Translation enabled")
);
},
"Translation was properly started.",
5000,
200
);

// and check if the translation happened
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
await new Promise(resolve => content.setTimeout(resolve, 5000));

is(
content.document.getElementById("translationDiv").innerHTML,
"Hello world. That's a test of translations.",
"Text was correctly translated."
);
});

// let's now select the outbound translation form
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {

content.document.getElementById("mainTextarea").focus();
content.document.getElementById("OTapp").querySelectorAll("textarea")[0].value = "Hello World";
content.document.getElementById("OTapp").querySelectorAll("textarea")[0].dispatchEvent(new content.KeyboardEvent('keydown', {'key': 'Enter'}));
await new Promise(resolve => content.setTimeout(resolve, 5000));

is(
content.document.getElementById("mainTextarea").value.trim(),
"Hola Mundo",
"Form translation text was correctly translated."
);

is(
content.document.getElementById("OTapp").querySelectorAll("textarea")[1].value.trim(),
"Hello World",
"Back Translation text was correctly translated."
);

});

delete window.MozTranslationNotification;
delete window.now;
notification.close();
BrowserTestUtils.removeTab(tab);
});
73 changes: 73 additions & 0 deletions scripts/tests/e2e-tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import os.path
from zipfile import ZipFile
import subprocess
from subprocess import PIPE, CalledProcessError
import shutil
import sys
import json

if not os.path.exists("scripts/tests/e2e-tests.py"):
sys.exit("This script is intended to be executed from the root folder.")
root = os.getcwd()

# Remove old gecko
subprocess.call("rm -rf gecko".split(), cwd=root)
# First we build the extension
subprocess.call("npm run build".split(), cwd=root)
# the nwe clone gecko
subprocess.call("git clone hg::https://hg.mozilla.org/mozilla-central gecko".split(), cwd=root)
# We then remove the old extension
subprocess.call("rm -rf gecko/browser/extensions/translations/extension".split(), cwd=root)
# and extract the newly one built there
subprocess.call("unzip web-ext-artifacts/firefox_translations.xpi -d gecko/browser/extensions/translations/extension/".split(), cwd=root)
# copy the tests
subprocess.call("mkdir -p gecko/browser/extensions/translations/test/browser/".split(), cwd=root)
subprocess.call("cp scripts/tests/browser.ini gecko/browser/extensions/translations/test/browser/".split(), cwd=root)
subprocess.call("cp scripts/tests/browser_translation_test.html gecko/browser/extensions/translations/test/browser/".split(), cwd=root)
subprocess.call("cp scripts/tests/browser_translation_test.js gecko/browser/extensions/translations/test/browser/".split(), cwd=root)
subprocess.call("cp -r scripts/tests/esen/ gecko/browser/extensions/translations/test/browser/esen/".split(), cwd=root)
subprocess.call("cp -r scripts/tests/enes/ gecko/browser/extensions/translations/test/browser/enes/".split(), cwd=root)

# let's download bergamot-translator-worker-with-wormhole.wasm
engineRegistryRootURL = ""
fileName = ""
with open('extension/model/engineRegistry.js') as fp:
Lines = fp.readlines()
for line in Lines:
if "engineRegistryRootURL " in line:
engineRegistryRootURL = line.split("=")[1].replace("\"","").replace(";","").strip()
if "fileName:" in line:
fileName = line.split(":")[1].replace("\"","").replace(",","").strip()

subprocess.call(("curl", "-L", "-o", "gecko/browser/extensions/translations/test/browser/"+fileName, engineRegistryRootURL + fileName), cwd=root)

# patching BrowserGlue.jsm to add the extension's version so it could be loaded
f = open("extension/manifest.json")
data = json.load(f)
extension_version = data["version"]
f.close()
with open("gecko/browser/components/BrowserGlue.jsm") as fp:
count = 0
Lines = fp.readlines()
for line in Lines:
if "resource://builtin-addons/translations/" in line:
Lines[count - 1] = ' "{}",\n'.format(extension_version)
with open("gecko/browser/components/BrowserGlue.jsm", "w") as outfile:
outfile.write("".join(Lines))
break
count += 1

# enable our test
with open('gecko/mozconfig', 'w') as f:
print('ac_add_options --enable-artifact-builds', file=f)

with open('gecko/browser/extensions/translations/moz.build', 'a') as f:
print('BROWSER_CHROME_MANIFESTS += [\"test/browser/browser.ini\"]', file=f)

# build and run our test
try:
subprocess.check_output("./mach build", stderr=subprocess.STDOUT, shell=True, universal_newlines=True, cwd="gecko")
subprocess.check_output("./mach test browser/extensions/translations/test/browser/browser_translation_test.js", stderr=subprocess.STDOUT, shell=True, universal_newlines=True, cwd="gecko")
except CalledProcessError as cpe:
print(cpe.output)
sys.exit("Tests failed")
Binary file added scripts/tests/enes/lex.50.50.enes.s2t.bin
Binary file not shown.
Binary file added scripts/tests/enes/model.enes.intgemm.alphas.bin
Binary file not shown.
Binary file added scripts/tests/enes/vocab.esen.spm
Binary file not shown.
Binary file added scripts/tests/esen/lex.50.50.esen.s2t.bin
Binary file not shown.
Binary file added scripts/tests/esen/model.esen.intgemm.alphas.bin
Binary file not shown.
Binary file added scripts/tests/esen/vocab.esen.spm
Binary file not shown.