diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /taskcluster/docker/snap-coreXX-build/snap-tests | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'taskcluster/docker/snap-coreXX-build/snap-tests')
36 files changed, 1415 insertions, 0 deletions
diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/README.md b/taskcluster/docker/snap-coreXX-build/snap-tests/README.md new file mode 100644 index 0000000000..73f78c72bc --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/README.md @@ -0,0 +1,24 @@ +Debugging tests +================ + +You can use the `TEST_FILTER` environment variable, e.g., `TEST_FILTER=xxx` +will filter test named `test_xxx`. + +Setting `TEST_GECKODRIVER_TRACE` to any value will make Selenium dump a trace +log for debugging. + +You can control running headless or not with `TEST_NO_HEADLESS`. Currently, +the copy/paste image test required NOT to run headless. + +More useful for local repro, you can set `TEST_NO_QUIT` if you need to keep +inspecting the browser at the end of a test. + +Data URL containing the diff screenshot will be dumped to stdout/stderr when +`TEST_DUMP_DIFF` is set in the environment. + +Updating reference screenshots +============================== + - `./mach try fuzzy --push-to-lando --full --env TEST_COLLECT_REFERENCE=1 -q "'snap-upstream-test"` + - note the successfull task id you want to source + - you need curl and jq installed + - ./update-references.sh <TASK_ID> diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests.py b/taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests.py new file mode 100644 index 0000000000..fb8841817b --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests.py @@ -0,0 +1,307 @@ +#!/usr/bin/env python3 +# 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 https://mozilla.org/MPL/2.0/. + + +import base64 +import io +import json +import os +import sys +import time +import traceback + +from mozlog import formatters, handlers, structuredlog +from PIL import Image, ImageChops +from selenium import webdriver +from selenium.common.exceptions import TimeoutException +from selenium.webdriver.common.by import By +from selenium.webdriver.firefox.options import Options +from selenium.webdriver.firefox.service import Service +from selenium.webdriver.remote.webelement import WebElement +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import WebDriverWait + + +class SnapTestsBase: + def __init__(self, exp): + driver_service = Service( + executable_path=r"/snap/firefox/current/usr/lib/firefox/geckodriver", + log_output=os.path.join( + os.environ.get("ARTIFACT_DIR", ""), "geckodriver.log" + ), + ) + options = Options() + if "TEST_GECKODRIVER_TRACE" in os.environ.keys(): + options.log.level = "trace" + options.binary_location = r"/snap/firefox/current/usr/lib/firefox/firefox" + if not "TEST_NO_HEADLESS" in os.environ.keys(): + options.add_argument("--headless") + if "MOZ_AUTOMATION" in os.environ.keys(): + os.environ["MOZ_LOG_FILE"] = os.path.join( + os.environ.get("ARTIFACT_DIR"), "gecko.log" + ) + self._driver = webdriver.Firefox(service=driver_service, options=options) + + self._logger = structuredlog.StructuredLogger(self.__class__.__name__) + self._logger.add_handler( + handlers.StreamHandler(sys.stdout, formatters.TbplFormatter()) + ) + + test_filter = "test_{}".format(os.environ.get("TEST_FILTER", "")) + object_methods = [ + method_name + for method_name in dir(self) + if callable(getattr(self, method_name)) + and method_name.startswith(test_filter) + ] + + self._logger.suite_start(object_methods) + + assert self._dir is not None + + self._wait = WebDriverWait(self._driver, self.get_timeout()) + self._longwait = WebDriverWait(self._driver, 60) + + with open(exp, "r") as j: + self._expectations = json.load(j) + + rv = False + try: + first_tab = self._driver.window_handles[0] + for m in object_methods: + tabs_before = set(self._driver.window_handles) + self._driver.switch_to.window(first_tab) + self._logger.test_start(m) + rv = getattr(self, m)(self._expectations[m]) + self._driver.switch_to.parent_frame() + if rv: + self._logger.test_end(m, status="OK") + else: + self._logger.test_end(m, status="FAIL") + tabs_after = set(self._driver.window_handles) + tabs_opened = tabs_after - tabs_before + self._logger.info("opened {} tabs".format(len(tabs_opened))) + for tab in tabs_opened: + self._driver.switch_to.window(tab) + self._driver.close() + self._wait.until(EC.number_of_windows_to_be(len(tabs_before))) + except Exception as ex: + rv = False + test_status = "ERROR" + if isinstance(ex, AssertionError): + test_status = "FAIL" + elif isinstance(ex, TimeoutException): + test_status = "TIMEOUT" + + test_message = repr(ex) + self.save_screenshot("screenshot_{}.png".format(test_status.lower())) + self._driver.switch_to.parent_frame() + self.save_screenshot("screenshot_{}_parent.png".format(test_status.lower())) + self._logger.test_end(m, status=test_status, message=test_message) + traceback.print_exc() + finally: + self._driver.switch_to.window(first_tab) + + if not "TEST_NO_QUIT" in os.environ.keys(): + self._driver.quit() + + self._logger.info("Exiting with {}".format(rv)) + self._logger.suite_end() + sys.exit(0 if rv is True else 1) + + def get_screenshot_destination(self, name): + final_name = name + if "MOZ_AUTOMATION" in os.environ.keys(): + final_name = os.path.join(os.environ.get("ARTIFACT_DIR"), name) + return final_name + + def save_screenshot(self, name): + final_name = self.get_screenshot_destination(name) + self._logger.info("Saving screenshot '{}' to '{}'".format(name, final_name)) + self._driver.save_screenshot(final_name) + + def get_timeout(self): + if "TEST_TIMEOUT" in os.environ.keys(): + return int(os.getenv("TEST_TIMEOUT")) + else: + return 5 + + def maybe_collect_reference(self): + return "TEST_COLLECT_REFERENCE" in os.environ.keys() + + def open_tab(self, url): + opened_tabs = len(self._driver.window_handles) + + self._driver.switch_to.new_window("tab") + self._wait.until(EC.number_of_windows_to_be(opened_tabs + 1)) + self._driver.get(url) + + return self._driver.current_window_handle + + def assert_rendering(self, exp, element_or_driver): + # wait a bit for things to settle down + time.sleep(0.5) + + # Convert as RGB otherwise we cannot get difference + png_bytes = ( + element_or_driver.screenshot_as_png + if isinstance(element_or_driver, WebElement) + else element_or_driver.get_screenshot_as_png() + ) + svg_png = Image.open(io.BytesIO(png_bytes)).convert("RGB") + svg_png_cropped = svg_png.crop((0, 0, svg_png.width - 20, svg_png.height - 20)) + + if self.maybe_collect_reference(): + new_ref = "new_{}".format(exp["reference"]) + new_ref_file = self.get_screenshot_destination(new_ref) + self._logger.info( + "Collecting new reference screenshot: {} => {}".format( + new_ref, new_ref_file + ) + ) + + with open(new_ref_file, "wb") as current_screenshot: + svg_png_cropped.save(current_screenshot) + + return + + svg_ref = Image.open(os.path.join(self._dir, exp["reference"])).convert("RGB") + diff = ImageChops.difference(svg_ref, svg_png_cropped) + + if diff.getbbox() is not None: + buffered = io.BytesIO() + diff.save(buffered, format="PNG") + + if "TEST_DUMP_DIFF" in os.environ.keys(): + diff_b64 = base64.b64encode(buffered.getvalue()) + self._logger.info( + "data:image/png;base64,{}".format(diff_b64.decode("utf-8")) + ) + + with open( + self.get_screenshot_destination("differences.png"), "wb" + ) as diff_screenshot: + diff_screenshot.write(buffered.getvalue()) + + with open( + self.get_screenshot_destination("current_rendering.png"), "wb" + ) as current_screenshot: + svg_png_cropped.save(current_screenshot) + + assert diff.getbbox() is None, "Mismatching screenshots for {}".format( + exp["reference"] + ) + + +class SnapTests(SnapTestsBase): + def __init__(self, exp): + self._dir = "basic_tests" + super(SnapTests, self).__init__(exp) + + def test_about_support(self, exp): + self.open_tab("about:support") + + version_box = self._wait.until( + EC.visibility_of_element_located((By.ID, "version-box")) + ) + self._wait.until(lambda d: len(version_box.text) > 0) + self._logger.info("about:support version: {}".format(version_box.text)) + assert version_box.text == exp["version_box"], "version text should match" + + distributionid_box = self._wait.until( + EC.visibility_of_element_located((By.ID, "distributionid-box")) + ) + self._wait.until(lambda d: len(distributionid_box.text) > 0) + self._logger.info( + "about:support distribution ID: {}".format(distributionid_box.text) + ) + assert ( + distributionid_box.text == exp["distribution_id"] + ), "distribution_id should match" + + windowing_protocol = self._driver.execute_script( + "return document.querySelector('th[data-l10n-id=\"graphics-window-protocol\"').parentNode.lastChild.textContent;" + ) + self._logger.info( + "about:support windowing protocol: {}".format(windowing_protocol) + ) + assert windowing_protocol == "wayland", "windowing protocol should be wayland" + + return True + + def test_about_buildconfig(self, exp): + self.open_tab("about:buildconfig") + + source_link = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "a")) + ) + self._wait.until(lambda d: len(source_link.text) > 0) + self._logger.info("about:buildconfig source: {}".format(source_link.text)) + assert source_link.text.startswith( + exp["source_repo"] + ), "source repo should exists and match" + + build_flags_box = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "p:last-child")) + ) + self._wait.until(lambda d: len(build_flags_box.text) > 0) + self._logger.info("about:support buildflags: {}".format(build_flags_box.text)) + assert ( + build_flags_box.text.find(exp["official"]) >= 0 + ), "official build flag should be there" + + return True + + def test_youtube(self, exp): + self.open_tab("https://www.youtube.com") + + # Wait for the consent dialog and accept it + self._logger.info("Wait for consent form") + try: + self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, "button[aria-label*=Accept]") + ) + ).click() + except TimeoutException: + self._logger.info("Wait for consent form: timed out, maybe it is not here") + + try: + # Find first video and click it + self._logger.info("Wait for one video") + self._wait.until( + EC.visibility_of_element_located((By.ID, "video-title-link")) + ).click() + except TimeoutException: + # We might have got the "try searching to get started" + # link to News channel + self._driver.get("https://www.youtube.com/channel/UCYfdidRxbB8Qhf0Nx7ioOYw") + self._logger.info("Wait again for one video") + self._wait.until( + EC.visibility_of_element_located((By.ID, "video-title-link")) + ).click() + + # Wait for duration to be set to something + self._logger.info("Wait for video to start") + video = self._wait.until( + EC.visibility_of_element_located((By.CLASS_NAME, "html5-main-video")) + ) + self._wait.until(lambda d: type(video.get_property("duration")) == float) + self._logger.info("video duration: {}".format(video.get_property("duration"))) + assert ( + video.get_property("duration") > exp["duration"] + ), "youtube video should have duration" + + self._wait.until(lambda d: video.get_property("currentTime") > exp["playback"]) + self._logger.info("video played: {}".format(video.get_property("currentTime"))) + assert ( + video.get_property("currentTime") > exp["playback"] + ), "youtube video should perform playback" + + return True + + +if __name__ == "__main__": + SnapTests(exp=sys.argv[1]) diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests/expectations.json.in b/taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests/expectations.json.in new file mode 100644 index 0000000000..92e26dd699 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/basic_tests/expectations.json.in @@ -0,0 +1,14 @@ +{ + "test_about_support": { + "version_box": "#RUNTIME_VERSION#", + "distribution_id": "canonical-002" + }, + "test_about_buildconfig": { + "source_repo": "https://hg.mozilla.org/", + "official": "MOZILLA_OFFICIAL=1" + }, + "test_youtube": { + "duration": 1, + "playback": 2 + } +} diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests.py b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests.py new file mode 100644 index 0000000000..781000981e --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests.py @@ -0,0 +1,860 @@ +#!/usr/bin/env python3 +# 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 https://mozilla.org/MPL/2.0/. + + +import os +import random +import tempfile +import time + +from basic_tests import SnapTestsBase +from selenium.common.exceptions import StaleElementReferenceException, TimeoutException +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.select import Select + + +class QATests(SnapTestsBase): + def __init__(self): + self._dir = "qa_tests" + + super(QATests, self).__init__( + exp=os.path.join(self._dir, "qa_expectations.json") + ) + + def _test_audio_playback( + self, url, iframe_selector=None, click_to_play=False, video_selector=None + ): + self._logger.info("open url {}".format(url)) + if url: + self.open_tab(url) + + if iframe_selector: + self._logger.info("find iframe") + iframe = self._driver.find_element(By.CSS_SELECTOR, iframe_selector) + self._driver.switch_to.frame(iframe) + + self._logger.info("find video") + video = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, video_selector or "video") + ) + ) + self._wait.until(lambda d: type(video.get_property("duration")) == float) + assert video.get_property("duration") > 0.0, "<video> duration null" + + # For HE-AAC page, Google Drive does not like SPACE + if not click_to_play and video.get_property("autoplay") is False: + self._logger.info("force play") + video.send_keys(Keys.SPACE) + + # Mostly for Google Drive video, click()/play() seems not to really + # work to trigger, but 'k' is required + if click_to_play: + self._driver.execute_script("arguments[0].click();", video) + video.send_keys("k") + + ref_volume = video.get_property("volume") + + self._logger.info("find video: wait readyState") + self._wait.until(lambda d: video.get_property("readyState") >= 4) + + # Some videos sometimes self-pause? + self._logger.info( + "find video: check paused: {}".format(video.get_property("paused")) + ) + self._logger.info( + "find video: check autoplay: {}".format(video.get_property("autoplay")) + ) + if not click_to_play and video.get_property("paused") is True: + self._driver.execute_script("arguments[0].play()", video) + + self._logger.info("find video: sleep") + # let it play at least 500ms + time.sleep(0.5) + + self._logger.info("find video: wait currentTime") + self._wait.until(lambda d: video.get_property("currentTime") >= 0.01) + assert ( + video.get_property("currentTime") >= 0.01 + ), "<video> currentTime not moved" + + # this should pause + self._logger.info("find video: pause") + if click_to_play: + video.send_keys("k") + else: + self._driver.execute_script("arguments[0].pause()", video) + datum = video.get_property("currentTime") + time.sleep(1) + datum_after_sleep = video.get_property("currentTime") + self._logger.info( + "datum={} datum_after_sleep={}".format(datum, datum_after_sleep) + ) + assert datum == datum_after_sleep, "<video> is sleeping" + assert video.get_property("paused") is True, "<video> is paused" + + self._logger.info("find video: unpause") + # unpause and verify playback + if click_to_play: + video.send_keys("k") + else: + self._driver.execute_script("arguments[0].play()", video) + assert video.get_property("paused") is False, "<video> is not paused" + time.sleep(2) + datum_after_resume = video.get_property("currentTime") + self._logger.info( + "datum_after_resume={} datum_after_sleep={}".format( + datum_after_resume, datum_after_sleep + ) + ) + # we wait for 2s but it's not super accurate on CI (vbox VMs?), + # observed values +/- 15% so check for more that should avoid + # intermittent failures + assert ( + datum_after_resume >= datum_after_sleep + 0.5 + ), "<video> progressed after pause" + + self._logger.info("find video: volume") + self._driver.execute_script( + "arguments[0].volume = arguments[1]", video, ref_volume * 0.25 + ) + assert ( + video.get_property("volume") == ref_volume * 0.25 + ), "<video> sound volume increased" + + self._logger.info("find video: done") + + def _test_audio_video_playback(self, url): + self._logger.info("open url {}".format(url)) + self.open_tab(url) + self._logger.info("find thumbnail") + thumbnail = self._longwait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "img")) + ) + self._logger.info("click") + self._driver.execute_script("arguments[0].click()", thumbnail) + self._logger.info("audio test") + self._test_audio_playback( + url=None, + iframe_selector="#drive-viewer-video-player-object-0", + click_to_play=True, + ) + + self._logger.info("find video again") + # we are still in the iframe + video = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "video")) + ) + self._logger.info("try fullscreen") + promise = self._driver.execute_script( + "return arguments[0].requestFullscreen().then(() => { return true; }).catch(() => { return false; })", + video, + ) + assert promise is True, "<video> full screen promised fullfilled" + + self._driver.execute_script("arguments[0].pause();", video) + self._driver.execute_script("document.exitFullscreen()") + + def test_h264_mov(self, exp): + """ + C95233 + """ + + self._test_audio_video_playback( + "https://drive.google.com/file/d/0BwxFVkl63-lEY3l3ODJReDg3RzQ/view?resourcekey=0-5kDw2QbFk9eLrWE1N9M1rQ" + ) + + return True + + def test_he_aac(self, exp): + """ + C95239 + """ + self._test_audio_playback( + url="https://www2.iis.fraunhofer.de/AAC/multichannel.html", + video_selector="p.inlineVideo > video", + ) + + return True + + def test_flac(self, exp): + """ + C95240 + """ + + self._test_audio_playback( + "http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.FLAC" + ) + + return True + + def test_mp3(self, exp): + """ + C95241 + """ + self._test_audio_playback( + "https://freetestdata.com/wp-content/uploads/2021/09/Free_Test_Data_5MB_MP3.mp3" + ) + + return True + + def test_ogg(self, exp): + """ + C95244 + """ + self._test_audio_playback( + "http://www.metadecks.org/software/sweep/audio/demos/beats1.ogg" + ) + + return True + + def test_custom_fonts(self, exp): + """ + C128146 + """ + + self.open_tab( + "http://codinginparadise.org/projects/svgweb/samples/demo.html?name=droid%20font1" + ) + + renderer = self._wait.until( + EC.visibility_of_element_located((By.ID, "selectRenderer")) + ) + self._wait.until(lambda d: len(renderer.text) > 0) + + renderer_drop = Select(renderer) + renderer_drop.select_by_visible_text("browser native svg") + + font = self._wait.until(EC.visibility_of_element_located((By.ID, "selectSVG"))) + self._wait.until(lambda d: len(font.text) > 0) + + font_drop = Select(font) + font_drop.select_by_value("droid font1") + + svg_div = self._wait.until( + EC.visibility_of_element_located((By.ID, "__svg__random___1__object")) + ) + self._wait.until(lambda d: svg_div.is_displayed() is True) + + self.assert_rendering(exp, svg_div) + + return True + + def pdf_select_zoom(self, value): + pdf_zoom = self._wait.until( + EC.visibility_of_element_located((By.ID, "scaleSelect")) + ) + self._wait.until(lambda d: len(pdf_zoom.text) > 0) + + pdf_zoom_drop = Select(pdf_zoom) + pdf_zoom_drop.select_by_value(value) + + def pdf_wait_div(self): + pdf_div = self._wait.until(EC.visibility_of_element_located((By.ID, "viewer"))) + self._wait.until(lambda d: pdf_div.is_displayed() is True) + return pdf_div + + def pdf_get_page(self, page, long=False): + waiter = self._longwait if long is True else self._wait + page = waiter.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, "div.page[data-page-number='{}'] canvas".format(page)) + ) + ) + + try: + self._wait.until(lambda d: page.is_displayed() is True) + except StaleElementReferenceException as ex: + self._logger.info("Stale element but who cares?: {}".format(ex)) + time.sleep(2) + + # self._wait.until( + # lambda d: d.execute_script( + # 'return window.getComputedStyle(document.querySelector(".loadingInput.start"), "::after").getPropertyValue("visibility");' + # ) + # == "hidden" + # ) + + # PDF.js can take time to settle and we don't have a nice way to wait + # for an event on it + time.sleep(2) + return page + + def pdf_go_to_page(self, page): + pagenum = self._wait.until( + EC.visibility_of_element_located((By.ID, "pageNumber")) + ) + pagenum.send_keys(Keys.BACKSPACE) + pagenum.send_keys("{}".format(page)) + + def test_pdf_navigation(self, exp): + """ + C3927 + """ + + self.open_tab("http://www.pdf995.com/samples/pdf.pdf") + + # Test basic rendering + self.pdf_wait_div() + self.pdf_select_zoom("1") + page_1 = self.pdf_get_page(1) + self.assert_rendering(exp["base"], page_1) + + # Navigating to page X, we know the PDF has 5 pages. + rand_page = random.randint(1, 5) + self.pdf_go_to_page(rand_page) + # the click step ensures we change page + self.pdf_wait_div().click() + # getting page X will wait on is_displayed() so if page X is not visible + # this will timeout + self.pdf_get_page(rand_page) + + # press down/up/right/left/PageDown/PageUp/End/Home + key_presses = [ + (Keys.DOWN, "down"), + (Keys.UP, "up"), + (Keys.RIGHT, "right"), + (Keys.LEFT, "left"), + (Keys.PAGE_DOWN, "pagedown"), + (Keys.PAGE_UP, "pageup"), + (Keys.END, "end"), + (Keys.HOME, "home"), + ] + + for key, ref in key_presses: + # reset to page 2 + self.pdf_go_to_page(2) + pdfjs = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "html")) + ) + pdfjs.send_keys(key) + self.pdf_get_page(2) + # give some time for rendering to update + time.sleep(0.2) + self._logger.info("assert {}".format(ref)) + self.assert_rendering(exp[ref], self._driver) + + # click Next/Previous page + self.pdf_go_to_page(1) + button_next = self._wait.until( + EC.visibility_of_element_located((By.ID, "next")) + ) + button_next.click() + button_next.click() + self._logger.info("assert next twice 1 => 3") + self.assert_rendering(exp["next"], self._driver) + + button_previous = self._wait.until( + EC.visibility_of_element_located((By.ID, "previous")) + ) + button_previous.click() + self._logger.info("assert previous 3 => 2") + self.assert_rendering(exp["previous"], self._driver) + + secondary_menu = self._wait.until( + EC.visibility_of_element_located((By.ID, "secondaryToolbarToggle")) + ) + + # Use tools button + # - first/lage page + # - rotate left/right + # - doc properties + menu_buttons = [ + "firstPage", + "lastPage", + "pageRotateCw", + "pageRotateCcw", + "documentProperties", + ] + + for menu_id in menu_buttons: + self._logger.info("reset to page for {}".format(menu_id)) + if menu_id != "firstPage": + self.pdf_go_to_page(1) + else: + self.pdf_go_to_page(2) + time.sleep(0.2) + + self._logger.info("click menu for {}".format(menu_id)) + # open menu + secondary_menu.click() + + self._logger.info("find button for {}".format(menu_id)) + button_to_test = self._wait.until( + EC.visibility_of_element_located((By.ID, menu_id)) + ) + + self._logger.info("click button for {}".format(menu_id)) + button_to_test.click() + + # rotation does not close the menu?: + if menu_id == "pageRotateCw" or menu_id == "pageRotateCcw": + secondary_menu.click() + + time.sleep(0.2) + + self._logger.info("assert {}".format(menu_id)) + self.assert_rendering(exp[menu_id], self._driver) + + if menu_id == "documentProperties": + close = self._wait.until( + EC.visibility_of_element_located((By.ID, "documentPropertiesClose")) + ) + close.click() + + self.pdf_go_to_page(1) + + # - select text + secondary_menu.click() + text_selection = self._wait.until( + EC.visibility_of_element_located((By.ID, "cursorSelectTool")) + ) + text_selection.click() + + action = ActionChains(self._driver) + paragraph = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, "span[role=presentation]") + ) + ) + action.drag_and_drop_by_offset(paragraph, 50, 10).perform() + self.assert_rendering(exp["select_text"], self._driver) + + # release select selection + action.move_by_offset(0, 150).perform() + action.click() + # make sure we go back to page 1 + self.pdf_go_to_page(1) + + # - hand tool + secondary_menu.click() + hand_tool = self._wait.until( + EC.visibility_of_element_located((By.ID, "cursorHandTool")) + ) + hand_tool.click() + action.drag_and_drop_by_offset(paragraph, 0, -200).perform() + self.assert_rendering(exp["hand_tool"], self._driver) + + return True + + def test_pdf_zoom(self, exp): + """ + C3929 + """ + + self.open_tab("http://www.pdf995.com/samples/pdf.pdf") + + self.pdf_wait_div() + + zoom_levels = [ + ("1", 1, "p1_100p"), + ("0.5", 1, "p1_50p"), + ("0.75", 1, "p1_75p"), + ("1.5", 1, "p1_150p"), + ("4", 1, "p1_400p"), + ("page-actual", 1, "p1_actual"), + ("page-fit", 1, "p1_fit"), + ("page-width", 1, "p1_width"), + ] + + for zoom, page, ref in zoom_levels: + self.pdf_select_zoom(zoom) + self.pdf_get_page(page) + self._logger.info("assert {}".format(ref)) + self.assert_rendering(exp[ref], self._driver) + + return True + + def test_pdf_download(self, exp): + """ + C936503 + """ + + self.open_tab( + "https://file-examples.com/index.php/sample-documents-download/sample-pdf-download/" + ) + + try: + consent = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, ".fc-cta-consent")) + ) + consent.click() + except TimeoutException: + self._logger.info("Wait for consent form: timed out, maybe it is not here") + + for iframe in self._driver.find_elements(By.CSS_SELECTOR, "iframe"): + self._driver.execute_script("arguments[0].remove();", iframe) + + download_button = self._wait.until( + EC.presence_of_element_located((By.CSS_SELECTOR, ".download-button")) + ) + self._driver.execute_script("arguments[0].scrollIntoView();", download_button) + self._driver.execute_script("this.window.scrollBy(0, -100);") + self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, ".download-button")) + ) + # clicking seems to break on CI because we nuke ads + self._driver.get(download_button.get_property("href")) + + self.pdf_get_page(1) + + self.assert_rendering(exp, self._driver) + + return True + + def context_menu_copy(self, element, mime_type): + action = ActionChains(self._driver) + + # Open context menu and copy + action.context_click(element).perform() + self._driver.set_context("chrome") + context_menu = self._wait.until( + EC.visibility_of_element_located((By.ID, "contentAreaContextMenu")) + ) + copy = self._wait.until( + EC.visibility_of_element_located( + ( + By.ID, + "context-copyimage-contents" + if mime_type.startswith("image/") + else "context-copy", + ) + ) + ) + copy.click() + self.wait_for_element_in_clipboard(mime_type, False) + context_menu.send_keys(Keys.ESCAPE) + + # go back to content context + self._driver.set_context("content") + + def verify_clipboard(self, mime_type, should_be_present): + self._driver.set_context("chrome") + in_clipboard = self._driver.execute_script( + "return Services.clipboard.hasDataMatchingFlavors([arguments[0]], Ci.nsIClipboard.kGlobalClipboard);", + mime_type, + ) + self._driver.set_context("content") + assert ( + in_clipboard == should_be_present + ), "type {} should/should ({}) not be in clipboard".format( + mime_type, should_be_present + ) + + def wait_for_element_in_clipboard(self, mime_type, context_change=False): + if context_change: + self._driver.set_context("chrome") + self._wait.until( + lambda d: self._driver.execute_script( + "return Services.clipboard.hasDataMatchingFlavors([arguments[0]], Ci.nsIClipboard.kGlobalClipboard);", + mime_type, + ) + is True + ) + if context_change: + self._driver.set_context("content") + + def test_copy_paste_image_text(self, exp): + """ + C464474 + """ + + mystor = self.open_tab("https://mystor.github.io/dragndrop/#") + images = self.open_tab("https://1stwebdesigner.com/image-file-types/") + + image = self._wait.until( + EC.presence_of_element_located((By.CSS_SELECTOR, ".wp-image-42224")) + ) + self._driver.execute_script("arguments[0].scrollIntoView();", image) + self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, ".wp-image-42224")) + ) + self.verify_clipboard("image/png", False) + self.context_menu_copy(image, "image/png") + self.verify_clipboard("image/png", True) + + self._driver.switch_to.window(mystor) + link = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, "#testlist > li:nth-child(11) > a:nth-child(1)") + ) + ) + link.click() + drop_area = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "html")) + ) + drop_area.click() + drop_area.send_keys(Keys.CONTROL + "v") + self.verify_clipboard("image/png", True) + + matching_text = self._wait.until( + EC.visibility_of_element_located((By.ID, "matching")) + ) + assert matching_text.text == "MATCHING", "copy/paste image should match" + + self._driver.switch_to.window(images) + text = self._wait.until( + EC.presence_of_element_located( + (By.CSS_SELECTOR, ".entry-content > p:nth-child(1)") + ) + ) + self._driver.execute_script("arguments[0].scrollIntoView();", text) + + action = ActionChains(self._driver) + action.drag_and_drop_by_offset(text, 50, 10).perform() + + self.context_menu_copy(text, "text/plain") + + self._driver.switch_to.window(mystor) + link = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, "#testlist > li:nth-child(12) > a:nth-child(1)") + ) + ) + link.click() + drop_area = self._wait.until( + EC.visibility_of_element_located((By.CSS_SELECTOR, "html")) + ) + drop_area.click() + drop_area.send_keys(Keys.CONTROL + "v") + + matching_text = self._wait.until( + EC.visibility_of_element_located((By.ID, "matching")) + ) + assert matching_text.text == "MATCHING", "copy/paste html should match" + + return True + + def accept_download(self): + # check the Firefox UI + self._driver.set_context("chrome") + download_button = self._wait.until( + EC.visibility_of_element_located((By.ID, "downloads-button")) + ) + download_button.click() + time.sleep(1) + + blocked_item = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadTarget") + ) + ) + blocked_item.click() + download_name = blocked_item.get_property("value") + + download_allow = self._wait.until( + EC.presence_of_element_located( + (By.ID, "downloadsPanel-blockedSubview-unblockButton") + ) + ) + download_allow.click() + + # back to page + self._driver.set_context("content") + + return download_name + + def wait_for_download(self): + # check the Firefox UI + self._driver.set_context("chrome") + download_button = self._wait.until( + EC.visibility_of_element_located((By.ID, "downloads-button")) + ) + download_button.click() + time.sleep(1) + + download_item = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadTarget") + ) + ) + download_name = download_item.get_property("value") + + download_progress = self._wait.until( + EC.presence_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadProgress") + ) + ) + self._wait.until(lambda d: download_progress.get_property("value") == 100) + + # back to page + self._driver.set_context("content") + return download_name + + def change_download_folder(self, previous=None, new=None): + self._logger.info("Download change folder: {} => {}".format(previous, new)) + self._driver.set_context("chrome") + self._driver.execute_script( + "Services.prefs.setIntPref('browser.download.folderList', 2);" + ) + self._driver.execute_script( + "Services.prefs.setCharPref('browser.download.dir', arguments[0]);", new + ) + download_dir_pref = self._driver.execute_script( + "return Services.prefs.getCharPref('browser.download.dir', null);" + ) + self._driver.set_context("content") + self._logger.info("Download folder pref: {}".format(download_dir_pref)) + assert ( + download_dir_pref == new + ), "download directory from pref should match new directory" + + def open_thinkbroadband(self): + download_site = self.open_tab("https://www.thinkbroadband.com/download") + try: + consent = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, ".t-acceptAllButton") + ) + ) + consent.click() + except TimeoutException: + self._logger.info("Wait for consent form: timed out, maybe it is not here") + return download_site + + def test_download_folder_change(self, exp): + """ + C1756713 + """ + + download_site = self.open_thinkbroadband() + extra_small = self._wait.until( + EC.presence_of_element_located( + ( + By.CSS_SELECTOR, + "div.module:nth-child(8) > p:nth-child(1) > a:nth-child(1)", + ) + ) + ) + self._driver.execute_script("arguments[0].click();", extra_small) + + download_name = self.accept_download() + self.wait_for_download() + + self.open_tab("about:preferences") + download_folder = self._wait.until( + EC.presence_of_element_located((By.ID, "downloadFolder")) + ) + previous_folder = ( + download_folder.get_property("value") + .replace("\u2066", "") + .replace("\u2069", "") + ) + self._logger.info( + "Download folder from about:preferences: {}".format(previous_folder) + ) + if not os.path.isabs(previous_folder): + previous_folder = os.path.join(os.environ.get("HOME", ""), previous_folder) + with tempfile.TemporaryDirectory() as tmpdir: + assert os.path.isdir(tmpdir), "tmpdir download should exists" + + download_1 = os.path.abspath(os.path.join(previous_folder, download_name)) + self._logger.info("Download 1 assert: {}".format(download_1)) + assert os.path.isfile(download_1), "downloaded file #1 should exists" + + self.change_download_folder(previous_folder, tmpdir) + + self._driver.switch_to.window(download_site) + self._driver.execute_script("arguments[0].click();", extra_small) + self.accept_download() + download_name2 = self.wait_for_download() + download_2 = os.path.join(tmpdir, download_name2) + + self._logger.info("Download 2 assert: {}".format(download_2)) + assert os.path.isfile(download_2), "downloaded file #2 should exists" + + return True + + def test_download_folder_removal(self, exp): + """ + C1756715 + """ + + download_site = self.open_thinkbroadband() + extra_small = self._wait.until( + EC.presence_of_element_located( + ( + By.CSS_SELECTOR, + "div.module:nth-child(8) > p:nth-child(1) > a:nth-child(1)", + ) + ) + ) + + with tempfile.TemporaryDirectory() as tmpdir: + self.change_download_folder(None, tmpdir) + + self._driver.switch_to.window(download_site) + self._driver.execute_script("arguments[0].click();", extra_small) + + self.accept_download() + download_name = self.wait_for_download() + download_file = os.path.join(tmpdir, download_name) + self._logger.info("Download assert: {}".format(download_file)) + assert os.path.isdir(tmpdir), "tmpdir download should exists" + assert os.path.isfile(download_file), "downloaded file should exists" + + self._driver.set_context("chrome") + download_button = self._wait.until( + EC.visibility_of_element_located((By.ID, "downloads-button")) + ) + download_button.click() + time.sleep(1) + + download_details = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadDetailsNormal") + ) + ) + assert download_details.get_property("value").startswith( + "Completed" + ), "download should be marked as completed" + + # TemporaryDirectory out of focus so folder removed + + # Close panel we will re-open it + self._driver.execute_script("this.window.DownloadsButton.hide();") + self._wait.until( + EC.invisibility_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadDetailsNormal") + ) + ) + + assert os.path.isdir(tmpdir) is False, "tmpdir should have been removed" + assert ( + os.path.isfile(download_file) is False + ), "downloaded file should have been removed" + + download_button.click() + time.sleep(1) + + download_item = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadTarget") + ) + ) + download_name_2 = download_item.get_property("value") + assert download_name == download_name_2, "downloaded names should match" + + download_details = self._wait.until( + EC.visibility_of_element_located( + (By.CSS_SELECTOR, ".download-state .downloadDetailsNormal") + ) + ) + assert download_details.get_property("value").startswith( + "File moved or missing" + ), "download panel should report file moved/missing" + + self._driver.execute_script("this.window.DownloadsButton.hide();") + + self._driver.set_context("content") + + return True + + +if __name__ == "__main__": + QATests() diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/qa_expectations.json b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/qa_expectations.json new file mode 100644 index 0000000000..f9806ffa90 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/qa_expectations.json @@ -0,0 +1,98 @@ +{ + "test_custom_fonts": { + "reference": "test_custom_fonts_ref.png" + }, + "test_h264_mov": {}, + "test_he_aac": {}, + "test_flac": {}, + "test_mp3": {}, + "test_ogg": {}, + "test_pdf_navigation": { + "base": { + "reference": "test_pdf_navigation_base.png" + }, + "next": { + "reference": "test_pdf_navigation_next.png" + }, + "previous": { + "reference": "test_pdf_navigation_previous.png" + }, + "down": { + "reference": "test_pdf_navigation_down.png" + }, + "up": { + "reference": "test_pdf_navigation_up.png" + }, + "right": { + "reference": "test_pdf_navigation_right.png" + }, + "left": { + "reference": "test_pdf_navigation_left.png" + }, + "pagedown": { + "reference": "test_pdf_navigation_pagedown.png" + }, + "pageup": { + "reference": "test_pdf_navigation_pageup.png" + }, + "end": { + "reference": "test_pdf_navigation_end.png" + }, + "home": { + "reference": "test_pdf_navigation_home.png" + }, + "firstPage": { + "reference": "test_pdf_navigation_firstPage.png" + }, + "lastPage": { + "reference": "test_pdf_navigation_lastPage.png" + }, + "pageRotateCw": { + "reference": "test_pdf_navigation_pageRotateCw.png" + }, + "pageRotateCcw": { + "reference": "test_pdf_navigation_pageRotateCcw.png" + }, + "documentProperties": { + "reference": "test_pdf_navigation_documentProperties.png" + }, + "select_text": { + "reference": "test_pdf_navigation_select_text.png" + }, + "hand_tool": { + "reference": "test_pdf_navigation_hand_tool.png" + } + }, + "test_pdf_zoom": { + "p1_50p": { + "reference": "test_pdf_zoom_p1_50p.png" + }, + "p1_75p": { + "reference": "test_pdf_zoom_p1_75p.png" + }, + "p1_100p": { + "reference": "test_pdf_zoom_p1_100p.png" + }, + "p1_150p": { + "reference": "test_pdf_zoom_p1_150p.png" + }, + "p1_400p": { + "reference": "test_pdf_zoom_p1_400p.png" + }, + "p1_actual": { + "reference": "test_pdf_zoom_p1_actual.png" + }, + "p1_fit": { + "reference": "test_pdf_zoom_p1_fit.png" + }, + "p1_width": { + "reference": "test_pdf_zoom_p1_width.png" + } + }, + "test_pdf_download": { + "reference": "test_pdf_download_base.png" + }, + "test_copy_paste_image_text": {}, + "test_download_folder_change": {}, + "test_download_folder_removal": {} +} diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_custom_fonts_ref.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_custom_fonts_ref.png Binary files differnew file mode 100644 index 0000000000..02263329e2 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_custom_fonts_ref.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_download_base.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_download_base.png Binary files differnew file mode 100644 index 0000000000..98bf604c4b --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_download_base.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_base.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_base.png Binary files differnew file mode 100644 index 0000000000..71046ad3c3 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_base.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_documentProperties.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_documentProperties.png Binary files differnew file mode 100644 index 0000000000..6eeeb95f2b --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_documentProperties.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_down.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_down.png Binary files differnew file mode 100644 index 0000000000..c3818c9726 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_down.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_end.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_end.png Binary files differnew file mode 100644 index 0000000000..86bf1f158d --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_end.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_firstPage.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_firstPage.png Binary files differnew file mode 100644 index 0000000000..1b33d8374e --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_firstPage.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_hand_tool.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_hand_tool.png Binary files differnew file mode 100644 index 0000000000..d84c9158d9 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_hand_tool.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_home.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_home.png Binary files differnew file mode 100644 index 0000000000..1b33d8374e --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_home.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_lastPage.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_lastPage.png Binary files differnew file mode 100644 index 0000000000..86bf1f158d --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_lastPage.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_left.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_left.png Binary files differnew file mode 100644 index 0000000000..aa36bda00c --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_left.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_next.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_next.png Binary files differnew file mode 100644 index 0000000000..21e930607c --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_next.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageRotateCcw.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageRotateCcw.png Binary files differnew file mode 100644 index 0000000000..19062697d9 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageRotateCcw.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageRotateCw.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageRotateCw.png Binary files differnew file mode 100644 index 0000000000..176ab1dcff --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageRotateCw.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pagedown.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pagedown.png Binary files differnew file mode 100644 index 0000000000..db05b7feb2 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pagedown.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageup.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageup.png Binary files differnew file mode 100644 index 0000000000..8df2181704 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_pageup.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_previous.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_previous.png Binary files differnew file mode 100644 index 0000000000..19c727c5e0 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_previous.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_right.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_right.png Binary files differnew file mode 100644 index 0000000000..be6d48cc30 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_right.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_select_text.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_select_text.png Binary files differnew file mode 100644 index 0000000000..95fa211e1b --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_select_text.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_up.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_up.png Binary files differnew file mode 100644 index 0000000000..cd5067574c --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_navigation_up.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_100p.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_100p.png Binary files differnew file mode 100644 index 0000000000..1b33d8374e --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_100p.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_150p.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_150p.png Binary files differnew file mode 100644 index 0000000000..add7d3a9bb --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_150p.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_400p.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_400p.png Binary files differnew file mode 100644 index 0000000000..58f832c3e5 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_400p.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_50p.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_50p.png Binary files differnew file mode 100644 index 0000000000..310bb889be --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_50p.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_75p.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_75p.png Binary files differnew file mode 100644 index 0000000000..5a21ade0c0 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_75p.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_actual.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_actual.png Binary files differnew file mode 100644 index 0000000000..d047a4fcbf --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_actual.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_fit.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_fit.png Binary files differnew file mode 100644 index 0000000000..b721fd3296 --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_fit.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_width.png b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_width.png Binary files differnew file mode 100644 index 0000000000..061eafda7f --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/qa_tests/test_pdf_zoom_p1_width.png diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/requirements.txt b/taskcluster/docker/snap-coreXX-build/snap-tests/requirements.txt new file mode 100644 index 0000000000..df0967738e --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/requirements.txt @@ -0,0 +1,22 @@ +attrs==23.1.0 +blessed==1.20.0 +certifi==2023.7.22 +exceptiongroup==1.1.3 +h11==0.14.0 +idna==3.4 +mozfile==3.0.0 +mozlog==8.0.0 +mozterm==1.0.0 +outcome==1.2.0 +Pillow==10.1.0 +PySocks==1.7.1 +PyYAML==6.0.1 +selenium==4.12.0 +six==1.16.0 +sniffio==1.3.0 +sortedcontainers==2.4.0 +trio==0.22.2 +trio-websocket==0.10.4 +urllib3==2.0.5 +wcwidth==0.2.13 +wsproto==1.2.0 diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh b/taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh new file mode 100755 index 0000000000..854ef2c9af --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/tests.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +set -ex + +pwd + +SUITE=${1:-basic} +SUITE=${SUITE//--/} + +export ARTIFACT_DIR=$TASKCLUSTER_ROOT_DIR/builds/worker/artifacts/ +mkdir -p "$ARTIFACT_DIR" + +# There's a bug in snapd ~2.60.3-2.61 that will make "snap refresh" fail +# https://bugzilla.mozilla.org/show_bug.cgi?id=1873359 +# https://bugs.launchpad.net/snapd/+bug/2048104/comments/13 +# +# So we retrieve the version and we will allow the first "snap refresh" to +# fail for versions < 2.61.1 +SNAP_VERSION=$(snap info snapd --color=never --unicode=never |grep "installed:" | awk '{ print $2 }') +SNAP_MAJOR=$(echo "${SNAP_VERSION}" | cut -d'.' -f1) +SNAP_MINOR=$(echo "${SNAP_VERSION}" | cut -d'.' -f2) +SNAP_RELEASE=$(echo "${SNAP_VERSION}" | cut -d'.' -f3) + +REFRESH_CAN_FAIL=true +if [ "${SNAP_MAJOR}" -ge 2 ]; then + if [ "${SNAP_MAJOR}" -gt 2 ]; then + REFRESH_CAN_FAIL=false + else + if [ "${SNAP_MINOR}" -ge 61 ]; then + if [ "${SNAP_MINOR}" -gt 61 ]; then + REFRESH_CAN_FAIL=false + else + if [ "${SNAP_RELEASE}" -gt 0 ]; then + REFRESH_CAN_FAIL=false + fi + fi + fi + fi +fi + +if [ "${REFRESH_CAN_FAIL}" = "true" ]; then + sudo snap refresh || true +else + sudo snap refresh +fi; + +sudo snap refresh --hold=24h firefox + +sudo snap install --name firefox --dangerous ./firefox.snap + +RUNTIME_VERSION=$(snap run firefox --version | awk '{ print $3 }') + +python3 -m pip install --user -r requirements.txt + +# Required otherwise copy/paste does not work +# Bug 1878643 +export TEST_NO_HEADLESS=1 + +if [ -n "${MOZ_LOG}" ]; then + export MOZ_LOG_FILE="${ARTIFACT_DIR}/gecko-log" +fi + +if [ "${SUITE}" = "basic" ]; then + sed -e "s/#RUNTIME_VERSION#/${RUNTIME_VERSION}/#" < basic_tests/expectations.json.in > basic_tests/expectations.json + python3 basic_tests.py basic_tests/expectations.json +else + python3 "${SUITE}"_tests.py +fi; diff --git a/taskcluster/docker/snap-coreXX-build/snap-tests/update-references.sh b/taskcluster/docker/snap-coreXX-build/snap-tests/update-references.sh new file mode 100755 index 0000000000..d8ce620aff --- /dev/null +++ b/taskcluster/docker/snap-coreXX-build/snap-tests/update-references.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +TASK_ID=${1} +THIS="$(dirname "$0")" + +if [ -z "${TASK_ID}" ]; then + echo "Please provide a task ID" + exit 1 +fi + +TASKCLUSTER_API_ROOT="https://firefox-ci-tc.services.mozilla.com" +ARTIFACTS="${TASKCLUSTER_API_ROOT}/api/queue/v1/task/${TASK_ID}/artifacts" + +for reference in $(curl "${ARTIFACTS}" | jq -r '.artifacts | . [] | select(.name | contains("public/build/new_")) | .name'); +do + name="$(basename "${reference}")" + final_name=${name//new_/} + target_name=$(find "${THIS}" -type f -name "${final_name}") + url="${TASKCLUSTER_API_ROOT}/api/queue/v1/task/${TASK_ID}/artifacts/${reference}" + echo "$url => $target_name" + curl -SL "${url}" -o "${target_name}" +done; |