Bug 1573406 - Remove every trace of Firefox UI update tests. r=webdriver-reviewers,ato
authorHenrik Skupin <mail@hskupin.info>
Wed, 14 Aug 2019 11:08:45 +0000
changeset 487896 2cee544a6859c721ea6abe2f47dd492e80658489
parent 487895 2c56720051ee631221924d1ec89563b6b534b303
child 487897 30be24d99ba234466072bcde7093bae7b21d5a43
push id92520
push userhskupin@mozilla.com
push dateWed, 14 Aug 2019 11:09:41 +0000
treeherderautoland@2cee544a6859 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswebdriver-reviewers, ato
bugs1573406
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1573406 - Remove every trace of Firefox UI update tests. r=webdriver-reviewers,ato Differential Revision: https://phabricator.services.mozilla.com/D41834
python/mozbuild/mozbuild/frontend/context.py
testing/firefox-ui/harness/firefox_ui_harness/__init__.py
testing/firefox-ui/harness/firefox_ui_harness/arguments/__init__.py
testing/firefox-ui/harness/firefox_ui_harness/arguments/update.py
testing/firefox-ui/harness/firefox_ui_harness/cli_update.py
testing/firefox-ui/harness/firefox_ui_harness/runners/__init__.py
testing/firefox-ui/harness/firefox_ui_harness/runners/update.py
testing/firefox-ui/harness/firefox_ui_harness/testcases.py
testing/firefox-ui/harness/setup.py
testing/firefox-ui/mach_commands.py
testing/firefox-ui/moz.build
testing/firefox-ui/tests/puppeteer/manifest.ini
testing/firefox-ui/tests/puppeteer/test_software_update.py
testing/firefox-ui/tests/puppeteer/test_update_wizard.py
testing/firefox-ui/tests/update/direct/manifest.ini
testing/firefox-ui/tests/update/direct/test_direct_update.py
testing/firefox-ui/tests/update/fallback/manifest.ini
testing/firefox-ui/tests/update/fallback/test_fallback_update.py
testing/firefox-ui/tests/update/manifest.ini
testing/marionette/puppeteer/firefox/docs/api/software_update.rst
testing/marionette/puppeteer/firefox/docs/index.rst
testing/marionette/puppeteer/firefox/docs/ui/update_wizard/dialog.rst
testing/marionette/puppeteer/firefox/firefox_puppeteer/api/software_update.py
testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/__init__.py
testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/dialog.py
testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py
tools/lint/py3.yml
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1916,20 +1916,16 @@ VARIABLES = {
     'ANDROID_INSTRUMENTATION_MANIFESTS': (ManifestparserManifestList, list,
                                           """List of manifest files defining Android instrumentation tests.
         """),
 
     'FIREFOX_UI_FUNCTIONAL_MANIFESTS': (ManifestparserManifestList, list,
                                         """List of manifest files defining firefox-ui-functional tests.
         """),
 
-    'FIREFOX_UI_UPDATE_MANIFESTS': (ManifestparserManifestList, list,
-                                    """List of manifest files defining firefox-ui-update tests.
-        """),
-
     'PUPPETEER_FIREFOX_MANIFESTS': (ManifestparserManifestList, list,
                                     """List of manifest files defining puppeteer unit tests for Firefox.
         """),
 
     'MARIONETTE_LAYOUT_MANIFESTS': (ManifestparserManifestList, list,
                                     """List of manifest files defining marionette-layout tests.
         """),
 
--- a/testing/firefox-ui/harness/firefox_ui_harness/__init__.py
+++ b/testing/firefox-ui/harness/firefox_ui_harness/__init__.py
@@ -2,9 +2,8 @@
 # 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/.
 
 from __future__ import absolute_import
 
 __version__ = '1.4.0'
 
 from . import cli_functional
-from . import cli_update
--- a/testing/firefox-ui/harness/firefox_ui_harness/arguments/__init__.py
+++ b/testing/firefox-ui/harness/firefox_ui_harness/arguments/__init__.py
@@ -1,7 +1,7 @@
 # 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/.
 
 from __future__ import absolute_import
+
 from firefox_ui_harness.arguments.base import FirefoxUIArguments
-from firefox_ui_harness.arguments.update import UpdateArguments
deleted file mode 100644
--- a/testing/firefox-ui/harness/firefox_ui_harness/arguments/update.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-from .base import FirefoxUIArguments
-
-
-class UpdateBaseArguments(object):
-    name = 'Firefox UI Update Tests'
-    args = [
-        [['--update-allow-mar-channel'], {
-            'dest': 'update_mar_channels',
-            'default': [],
-            'action': 'append',
-            'metavar': 'MAR_CHANNEL',
-            'help': 'Additional MAR channel to be allowed for updates, '
-                    'e.g. "firefox-mozilla-beta" for updating a release '
-                    'build to the latest beta build.'
-        }],
-        [['--update-channel'], {
-            'metavar': 'CHANNEL',
-            'help': 'Channel to use for the update check.'
-        }],
-        [['--update-direct-only'], {
-            'default': False,
-            'action': 'store_true',
-            'help': 'Only perform a direct update'
-        }],
-        [['--update-fallback-only'], {
-            'default': False,
-            'action': 'store_true',
-            'help': 'Only perform a fallback update'
-        }],
-        [['--update-url'], {
-            'metavar': 'URL',
-            'help': 'Force specified URL to use for update checks.'
-        }],
-        [['--update-target-version'], {
-            'metavar': 'VERSION',
-            'help': 'Version of the updated build.'
-        }],
-        [['--update-target-buildid'], {
-            'metavar': 'BUILD_ID',
-            'help': 'Build ID of the updated build.'
-        }],
-    ]
-
-    def verify_usage_handler(self, args):
-        if args.update_direct_only and args.update_fallback_only:
-            raise ValueError('Arguments --update-direct-only and --update-fallback-only '
-                             'are mutually exclusive.')
-
-
-class UpdateArguments(FirefoxUIArguments):
-
-    def __init__(self, **kwargs):
-        super(UpdateArguments, self).__init__(**kwargs)
-
-        self.register_argument_container(UpdateBaseArguments())
deleted file mode 100644
--- a/testing/firefox-ui/harness/firefox_ui_harness/cli_update.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-
-# 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/.
-
-from __future__ import absolute_import
-from marionette_harness.runtests import cli as mn_cli
-
-from firefox_ui_harness.arguments import UpdateArguments
-from firefox_ui_harness.runners import UpdateTestRunner
-
-
-def cli(args=None):
-    mn_cli(runner_class=UpdateTestRunner,
-           parser_class=UpdateArguments,
-           args=args,
-           )
-
-
-if __name__ == '__main__':
-    cli()
--- a/testing/firefox-ui/harness/firefox_ui_harness/runners/__init__.py
+++ b/testing/firefox-ui/harness/firefox_ui_harness/runners/__init__.py
@@ -1,7 +1,7 @@
 # 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/.
 
 from __future__ import absolute_import
+
 from firefox_ui_harness.runners.base import FirefoxUITestRunner
-from firefox_ui_harness.runners.update import UpdateTestRunner
deleted file mode 100644
--- a/testing/firefox-ui/harness/firefox_ui_harness/runners/update.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-import os
-import sys
-
-import mozfile
-import mozinstall
-
-from firefox_ui_harness.runners import FirefoxUITestRunner
-from firefox_ui_harness.testcases import UpdateTestCase
-
-
-DEFAULT_PREFS = {
-    'app.update.disabledForTesting': False,
-    # Bug 1355026: Re-enable when support for the new simplified UI update is available
-    'app.update.doorhanger': False,
-    'app.update.log': True,
-    'app.update.staging.enabled': True,
-    'startup.homepage_override_url': 'about:blank',
-}
-
-
-class UpdateTestRunner(FirefoxUITestRunner):
-
-    def __init__(self, **kwargs):
-        super(UpdateTestRunner, self).__init__(**kwargs)
-
-        self.original_bin = self.bin
-
-        self.prefs.update(DEFAULT_PREFS)
-
-        self.run_direct_update = not kwargs.pop('update_fallback_only', False)
-        self.run_fallback_update = not kwargs.pop('update_direct_only', False)
-
-        self.test_handlers = [UpdateTestCase]
-
-        # With bug 1355888 Marionette uses an environment variable to identify
-        # if it should be active. It's important especially for restarts of the
-        # application to set this, because if it is not present Marionette will
-        # not start. To allow updates from builds before this change, the
-        # environment variable has to be pre-emptively set.
-        # TODO: Can be removed once we no longer have to test updates from
-        # Firefox 55.0 and earlier.
-        os.environ['MOZ_MARIONETTE'] = '1'
-
-    def run_tests(self, tests):
-        # Used to store the last occurred exception because we execute
-        # run_tests() multiple times
-        self.exc_info = None
-
-        failed = 0
-        source_folder = self.get_application_folder(self.original_bin)
-
-        results = {}
-
-        def _run_tests(tags):
-            application_folder = None
-
-            try:
-                # Backup current tags
-                test_tags = self.test_tags
-
-                application_folder = self.duplicate_application(source_folder)
-                self.bin = mozinstall.get_binary(application_folder, 'Firefox')
-
-                self.test_tags = tags
-                super(UpdateTestRunner, self).run_tests(tests)
-
-            except Exception:
-                self.exc_info = sys.exc_info()
-                self.logger.error('Failure during execution of the update test.',
-                                  exc_info=self.exc_info)
-
-            finally:
-                self.test_tags = test_tags
-
-                self.logger.info('Removing copy of the application at "%s"' % application_folder)
-                try:
-                    mozfile.remove(application_folder)
-                except IOError as e:
-                    self.logger.error('Cannot remove copy of application: "%s"' % str(e))
-
-        # Run direct update tests if wanted
-        if self.run_direct_update:
-            _run_tests(tags=['direct'])
-            failed += self.failed
-            results['Direct'] = False if self.failed else True
-
-        # Run fallback update tests if wanted
-        if self.run_fallback_update:
-            _run_tests(tags=['fallback'])
-            failed += self.failed
-            results['Fallback'] = False if self.failed else True
-
-        self.logger.info("Summary of update tests:")
-        for test_type, result in results.iteritems():
-            self.logger.info("\t%s update test ran and %s" %
-                             (test_type, 'PASSED' if result else 'FAILED'))
-
-        # Combine failed tests for all run_test() executions
-        self.failed = failed
-
-        # If exceptions happened, re-throw the last one
-        if self.exc_info:
-            ex_type, exception, tb = self.exc_info
-            raise ex_type(exception).with_traceback(tb)
deleted file mode 100644
--- a/testing/firefox-ui/harness/firefox_ui_harness/testcases.py
+++ /dev/null
@@ -1,440 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-import os
-import pprint
-from datetime import datetime
-
-import mozfile
-
-from firefox_puppeteer import PuppeteerMixin
-from firefox_puppeteer.api.software_update import SoftwareUpdate
-from firefox_puppeteer.ui.update_wizard import UpdateWizardDialog
-from marionette_driver import Wait
-from marionette_driver.errors import NoSuchWindowException
-from marionette_harness import MarionetteTestCase
-
-
-class UpdateTestCase(PuppeteerMixin, MarionetteTestCase):
-
-    TIMEOUT_UPDATE_APPLY = 300
-    TIMEOUT_UPDATE_CHECK = 30
-    TIMEOUT_UPDATE_DOWNLOAD = 720
-
-    # For the old update wizard, the errors are displayed inside the dialog. For the
-    # handling of updates in the about window the errors are displayed in new dialogs.
-    # When the old wizard is open we have to set the preference, so the errors will be
-    # shown as expected, otherwise we would have unhandled modal dialogs when errors are
-    # raised. See:
-    # http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/update/nsUpdateService.js?rev=a9240b1eb2fb#4813
-    # http://mxr.mozilla.org/mozilla-central/source/toolkit/mozapps/update/nsUpdateService.js?rev=a9240b1eb2fb#4756
-    PREF_APP_UPDATE_ALTWINDOWTYPE = 'app.update.altwindowtype'
-
-    def __init__(self, *args, **kwargs):
-        super(UpdateTestCase, self).__init__(*args, **kwargs)
-
-        self.update_channel = kwargs.pop('update_channel')
-        self.update_mar_channels = set(kwargs.pop('update_mar_channels'))
-        self.update_url = kwargs.pop('update_url')
-
-        self.target_buildid = kwargs.pop('update_target_buildid')
-        self.target_version = kwargs.pop('update_target_version')
-
-    def setUp(self, is_fallback=False):
-        super(UpdateTestCase, self).setUp()
-
-        self.software_update = SoftwareUpdate(self.marionette)
-        self.download_duration = None
-
-        # If a custom update channel has to be set, force a restart of
-        # Firefox to actually get it applied as a default pref. Use the clean
-        # option to force a non in_app restart, which would allow Firefox to
-        # dump the logs to the console.
-        if self.update_channel:
-            self.software_update.update_channel = self.update_channel
-            self.restart(clean=True)
-
-            self.assertEqual(self.software_update.update_channel, self.update_channel)
-
-        # If requested modify the list of allowed MAR channels
-        if self.update_mar_channels:
-            self.software_update.mar_channels.add_channels(self.update_mar_channels)
-
-            self.assertTrue(self.update_mar_channels.issubset(
-                            self.software_update.mar_channels.channels),
-                            'Allowed MAR channels have been set: expected "{}" in "{}"'.format(
-                                ', '.join(self.update_mar_channels),
-                                ', '.join(self.software_update.mar_channels.channels)))
-
-        # Ensure that there exists no already partially downloaded update
-        self.remove_downloaded_update()
-
-        self.set_preferences_defaults()
-
-        # Dictionary which holds the information for each update
-        self.update_status = {
-            'build_pre': self.software_update.build_info,
-            'build_post': None,
-            'fallback': is_fallback,
-            'patch': {},
-            'success': False,
-        }
-
-        # Check if the user has permissions to run the update
-        self.assertTrue(self.software_update.allowed,
-                        'Current user has permissions to update the application.')
-
-    def tearDown(self):
-        try:
-            self.browser.tabbar.close_all_tabs([self.browser.tabbar.selected_tab])
-
-            # Add content of the update log file for detailed failures when applying an update
-            self.update_status['update_log'] = self.read_update_log()
-
-            # Print results for now until we have treeherder integration
-            output = pprint.pformat(self.update_status)
-            self.logger.info('Update test results: \n{}'.format(output))
-        finally:
-            super(UpdateTestCase, self).tearDown()
-
-            # Ensure that no trace of an partially downloaded update remain
-            self.remove_downloaded_update()
-
-    @property
-    def patch_info(self):
-        """ Returns information about the active update in the queue.
-
-        :returns: A dictionary with information about the active patch
-        """
-        patch = self.software_update.patch_info
-        patch['download_duration'] = self.download_duration
-
-        return patch
-
-    def check_for_updates(self, about_window, timeout=TIMEOUT_UPDATE_CHECK):
-        """Clicks on "Check for Updates" button, and waits for check to complete.
-
-        :param about_window: Instance of :class:`AboutWindow`.
-        :param timeout: How long to wait for the update check to finish. Optional,
-         defaults to 60s.
-
-        :returns: True, if an update is available.
-        """
-        self.assertEqual(about_window.deck.selected_panel,
-                         about_window.deck.check_for_updates)
-
-        about_window.deck.check_for_updates.button.click()
-        Wait(self.marionette, timeout=self.TIMEOUT_UPDATE_CHECK).until(
-            lambda _: about_window.deck.selected_panel not in
-            (about_window.deck.check_for_updates, about_window.deck.checking_for_updates),
-            message='Check for updates has been finished.')
-
-        return about_window.deck.selected_panel != about_window.deck.no_updates_found
-
-    def check_update_applied(self):
-        """Check that the update has been applied correctly"""
-        self.update_status['build_post'] = self.software_update.build_info
-
-        # Ensure that the target version is the same or higher. No downgrade
-        # should have happened.
-        version_check = self.marionette.execute_script("""
-          Components.utils.import("resource://gre/modules/Services.jsm");
-
-          return Services.vc.compare(arguments[0], arguments[1]);
-        """, script_args=(self.update_status['build_post']['version'],
-                          self.update_status['build_pre']['version']))
-
-        self.assertGreaterEqual(version_check, 0,
-                                'A downgrade from version {} to {} is not allowed'.format(
-                                    self.update_status['build_pre']['version'],
-                                    self.update_status['build_post']['version']))
-
-        self.assertNotEqual(self.update_status['build_post']['buildid'],
-                            self.update_status['build_pre']['buildid'],
-                            'The staged update to buildid {} has not been applied'.format(
-                                self.update_status['patch']['buildid']))
-
-        self.assertEqual(self.update_status['build_post']['buildid'],
-                         self.update_status['patch']['buildid'],
-                         'Unexpected target buildid after applying the patch, {} != {}'.format(
-                             self.update_status['build_post']['buildid'],
-                             self.update_status['patch']['buildid']))
-
-        self.assertEqual(self.update_status['build_post']['locale'],
-                         self.update_status['build_pre']['locale'],
-                         'Unexpected change of the locale from {} to {}'.format(
-                             self.update_status['build_pre']['locale'],
-                             self.update_status['build_post']['locale']))
-
-        self.assertEqual(self.update_status['build_post']['disabled_addons'],
-                         self.update_status['build_pre']['disabled_addons'],
-                         'Application-wide addons have been unexpectedly disabled: {}'.format(
-                             ', '.join(set(self.update_status['build_pre']['locale']) -
-                                       set(self.update_status['build_post']['locale']))
-        ))
-
-        if self.target_version:
-            self.assertEqual(self.update_status['build_post']['version'],
-                             self.target_version,
-                             'Current target version {} does not match expected version {}'.format(
-                                 self.update_status['build_post']['version'], self.target_version))
-
-        if self.target_buildid:
-            self.assertEqual(self.update_status['build_post']['buildid'],
-                             self.target_buildid,
-                             'Current target buildid {} does not match expected buildid {}'.format(
-                                 self.update_status['build_post']['buildid'], self.target_buildid))
-
-        self.update_status['success'] = True
-
-    def check_update_not_applied(self):
-        """Check that the update has not been applied due to a forced invalidation of the patch"""
-        build_info = self.software_update.build_info
-
-        # Ensure that the version has not been changed
-        version_check = self.marionette.execute_script("""
-          Components.utils.import("resource://gre/modules/Services.jsm");
-
-          return Services.vc.compare(arguments[0], arguments[1]);
-        """, script_args=(build_info['version'],
-                          self.update_status['build_pre']['version']))
-
-        self.assertEqual(version_check, 0,
-                         'An update from version {} to {} has been unexpectedly applied'.format(
-                             self.update_status['build_pre']['version'],
-                             build_info['version']))
-
-        # Check that the build id of the source build and the current build are identical
-        self.assertEqual(build_info['buildid'],
-                         self.update_status['build_pre']['buildid'],
-                         'The build id has been unexpectedly changed from {} to {}'.format(
-                             self.update_status['build_pre']['buildid'], build_info['buildid']))
-
-    def download_update(self, window, wait_for_finish=True, timeout=TIMEOUT_UPDATE_DOWNLOAD):
-        """ Download the update patch.
-
-        :param window: Instance of :class:`AboutWindow` or :class:`UpdateWizardDialog`.
-        :param wait_for_finish: If True the function has to wait for the download to be finished.
-         Optional, default to `True`.
-        :param timeout: How long to wait for the download to finish. Optional, default to 360s.
-        """
-
-        def download_via_update_wizard(dialog):
-            """ Download the update via the old update wizard dialog.
-
-            :param dialog: Instance of :class:`UpdateWizardDialog`.
-            """
-            self.marionette.set_pref(self.PREF_APP_UPDATE_ALTWINDOWTYPE, dialog.window_type)
-
-            try:
-                # If updates have already been found, proceed to download
-                if dialog.wizard.selected_panel in [dialog.wizard.updates_found_basic,
-                                                    dialog.wizard.error_patching,
-                                                    ]:
-                    dialog.select_next_page()
-
-                # If incompatible add-on are installed, skip over the wizard page
-                # TODO: Remove once we no longer support version Firefox 45.0ESR
-                if self.puppeteer.utils.compare_version(self.puppeteer.appinfo.version,
-                                                        '49.0a1') == -1:
-                    if dialog.wizard.selected_panel == dialog.wizard.incompatible_list:
-                        dialog.select_next_page()
-
-                # Updates were stored in the cache, so no download is necessary
-                if dialog.wizard.selected_panel in [dialog.wizard.finished,
-                                                    dialog.wizard.finished_background,
-                                                    ]:
-                    pass
-
-                # Download the update
-                elif dialog.wizard.selected_panel == dialog.wizard.downloading:
-                    if wait_for_finish:
-                        start_time = datetime.now()
-                        self.wait_for_download_finished(dialog, timeout)
-                        self.download_duration = (datetime.now() - start_time).total_seconds()
-
-                        Wait(self.marionette).until(lambda _: (
-                            dialog.wizard.selected_panel in [dialog.wizard.finished,
-                                                             dialog.wizard.finished_background,
-                                                             ]),
-                                                    message='Final wizard page has been selected.')
-
-                else:
-                    raise Exception('Invalid wizard page for downloading an update: {}'.format(
-                                    dialog.wizard.selected_panel))
-
-            finally:
-                self.marionette.clear_pref(self.PREF_APP_UPDATE_ALTWINDOWTYPE)
-
-        # The old update wizard dialog has to be handled differently. It's necessary
-        # for fallback updates and invalid add-on versions.
-        if isinstance(window, UpdateWizardDialog):
-            download_via_update_wizard(window)
-            return
-
-        if window.deck.selected_panel == window.deck.download_and_install:
-            window.deck.download_and_install.button.click()
-
-            # Wait for the download to start
-            Wait(self.marionette).until(lambda _: (
-                window.deck.selected_panel != window.deck.download_and_install),
-                message='Download of the update has been started.')
-
-        if wait_for_finish:
-            start_time = datetime.now()
-            self.wait_for_download_finished(window, timeout)
-            self.download_duration = (datetime.now() - start_time).total_seconds()
-
-    def download_and_apply_available_update(self, force_fallback=False):
-        """Checks, downloads, and applies an available update.
-
-        :param force_fallback: Optional, if `True` invalidate current update status.
-         Defaults to `False`.
-        """
-        # Open the about window and check for updates
-        about_window = self.browser.open_about_window()
-
-        try:
-            update_available = self.check_for_updates(about_window)
-            self.assertTrue(update_available,
-                            "Available update has been found")
-
-            # Download update and wait until it has been applied
-            self.download_update(about_window)
-            self.wait_for_update_applied(about_window)
-
-        finally:
-            self.update_status['patch'] = self.patch_info
-
-        if force_fallback:
-            # Set the downloaded update into failed state
-            self.software_update.force_fallback()
-
-        # Restart Firefox to apply the downloaded update
-        self.restart(callback=lambda: about_window.deck.apply.button.click())
-
-    def download_and_apply_forced_update(self):
-        self.check_update_not_applied()
-
-        # The update wizard dialog opens automatically after the restart but with a short delay
-        dialog = Wait(self.marionette, ignored_exceptions=[NoSuchWindowException]).until(
-            lambda _: self.puppeteer.windows.switch_to(lambda win: type(win) is UpdateWizardDialog)
-        )
-
-        # In case of a broken complete update the about window has to be used
-        if self.update_status['patch']['is_complete']:
-            about_window = None
-            try:
-                self.assertEqual(dialog.wizard.selected_panel,
-                                 dialog.wizard.error)
-                dialog.close()
-
-                # Open the about window and check for updates
-                about_window = self.browser.open_about_window()
-                update_available = self.check_for_updates(about_window)
-                self.assertTrue(update_available,
-                                'Available update has been found')
-
-                # Download update and wait until it has been applied
-                self.download_update(about_window)
-                self.wait_for_update_applied(about_window)
-
-            finally:
-                self.update_status['patch'] = self.patch_info
-
-            # Restart Firefox to apply the downloaded fallback update
-            self.assertIsNotNone(about_window)
-            self.restart(callback=lambda: about_window.deck.apply.button.click())
-
-        # For a broken partial update, the software update window is used
-        else:
-            try:
-                self.assertEqual(dialog.wizard.selected_panel,
-                                 dialog.wizard.error_patching)
-
-                # Start downloading the fallback update
-                self.download_update(dialog)
-
-            finally:
-                self.update_status['patch'] = self.patch_info
-
-            # Restart Firefox to apply the downloaded fallback update
-            self.restart(callback=lambda: dialog.wizard.finish_button.click())
-
-    def read_update_log(self):
-        """Read the content of the update log file for the last update attempt."""
-        path = os.path.join(os.path.dirname(self.software_update.staging_directory),
-                            'last-update.log')
-        try:
-            with open(path, 'rb') as f:
-                return f.read().splitlines()
-        except IOError as exc:
-            self.logger.warning(str(exc))
-            return None
-
-    def remove_downloaded_update(self):
-        """Remove an already downloaded update from the update staging directory.
-
-        Hereby not only remove the update subdir but everything below 'updates'.
-        """
-        path = os.path.dirname(self.software_update.staging_directory)
-        self.logger.info('Clean-up update staging directory: {}'.format(path))
-        mozfile.remove(path)
-
-    def restart(self, *args, **kwargs):
-        super(UpdateTestCase, self).restart(*args, **kwargs)
-
-        # After a restart default preference values as set in the former session are lost.
-        # Make sure that any of those are getting restored.
-        self.set_preferences_defaults()
-
-    def set_preferences_defaults(self):
-        """Set the default value for specific preferences to force its usage."""
-        if self.update_url:
-            self.software_update.update_url = self.update_url
-
-    def wait_for_download_finished(self, window, timeout=TIMEOUT_UPDATE_DOWNLOAD):
-        """ Waits until download is completed.
-
-        :param window: Instance of :class:`AboutWindow` or :class:`UpdateWizardDialog`.
-        :param timeout: How long to wait for the download to finish. Optional,
-         default to 360 seconds.
-        """
-        # The old update wizard dialog has to be handled differently. It's necessary
-        # for fallback updates and invalid add-on versions.
-        if isinstance(window, UpdateWizardDialog):
-            Wait(self.marionette, timeout=timeout).until(
-                lambda _: window.wizard.selected_panel != window.wizard.downloading,
-                message='Download has been completed.')
-
-            self.assertNotIn(window.wizard.selected_panel,
-                             [window.wizard.error, window.wizard.error_extra])
-            return
-
-        Wait(self.marionette, timeout=timeout).until(
-            lambda _: window.deck.selected_panel not in
-            (window.deck.download_and_install, window.deck.downloading),
-            message='Download has been completed.')
-
-        self.assertNotEqual(window.deck.selected_panel,
-                            window.deck.download_failed)
-
-    def wait_for_update_applied(self, about_window, timeout=TIMEOUT_UPDATE_APPLY):
-        """ Waits until the downloaded update has been applied.
-
-        :param about_window: Instance of :class:`AboutWindow`.
-        :param timeout: How long to wait for the update to apply. Optional,
-         default to 300 seconds
-        """
-        Wait(self.marionette, timeout=timeout).until(
-            lambda _: about_window.deck.selected_panel == about_window.deck.apply,
-            message='Final wizard page has been selected.')
-
-        # Wait for update to be staged because for update tests we modify the update
-        # status file to enforce the fallback update. If we modify the file before
-        # Firefox does, Firefox will override our change and we will have no fallback update.
-        Wait(self.marionette, timeout=timeout).until(
-            lambda _: 'applied' in self.software_update.active_update.state,
-            message='Update has been applied.')
--- a/testing/firefox-ui/harness/setup.py
+++ b/testing/firefox-ui/harness/setup.py
@@ -39,11 +39,10 @@ setup(name='firefox-ui-harness',
       license='MPL',
       packages=find_packages(),
       include_package_data=True,
       zip_safe=False,
       install_requires=read('requirements.txt').splitlines(),
       entry_points="""
         [console_scripts]
         firefox-ui-functional = firefox_ui_harness.cli_functional:cli
-        firefox-ui-update = firefox_ui_harness.cli_update:cli
       """,
       )
--- a/testing/firefox-ui/mach_commands.py
+++ b/testing/firefox-ui/mach_commands.py
@@ -21,48 +21,32 @@ from mach.decorators import (
 def setup_argument_parser_functional():
     from firefox_ui_harness.arguments.base import FirefoxUIArguments
     from mozlog.structured import commandline
     parser = FirefoxUIArguments()
     commandline.add_logging_group(parser)
     return parser
 
 
-def setup_argument_parser_update():
-    from firefox_ui_harness.arguments.update import UpdateArguments
-    from mozlog.structured import commandline
-    parser = UpdateArguments()
-    commandline.add_logging_group(parser)
-    return parser
-
-
 def run_firefox_ui_test(testtype=None, topsrcdir=None, **kwargs):
     from mozlog.structured import commandline
     from argparse import Namespace
     import firefox_ui_harness
 
     if testtype == 'functional':
         parser = setup_argument_parser_functional()
-    else:
-        parser = setup_argument_parser_update()
 
     test_types = {
         'functional': {
             'default_tests': [
                 os.path.join('puppeteer', 'manifest.ini'),
                 os.path.join('functional', 'manifest.ini'),
             ],
             'cli_module': firefox_ui_harness.cli_functional,
         },
-        'update': {
-            'default_tests': [
-                os.path.join('update', 'manifest.ini'),
-            ],
-            'cli_module': firefox_ui_harness.cli_update,
-        }
     }
 
     fxui_dir = os.path.join(topsrcdir, 'testing', 'firefox-ui')
 
     # Set the resources path which is used to serve test data via wptserve
     if not kwargs['server_root']:
         kwargs['server_root'] = os.path.join(fxui_dir, 'resources')
 
@@ -105,18 +89,8 @@ class MachCommands(MachCommandBase):
              conditions=[conditions.is_firefox],
              description='Run the functional test suite of Firefox UI tests.',
              parser=setup_argument_parser_functional,
              )
     def run_firefox_ui_functional(self, **kwargs):
         kwargs['binary'] = kwargs['binary'] or self.get_binary_path('app')
         return run_firefox_ui_test(testtype='functional',
                                    topsrcdir=self.topsrcdir, **kwargs)
-
-    @Command('firefox-ui-update', category='testing',
-             conditions=[conditions.is_firefox],
-             description='Run the update test suite of Firefox UI tests.',
-             parser=setup_argument_parser_update,
-             )
-    def run_firefox_ui_update(self, **kwargs):
-        kwargs['binary'] = kwargs['binary'] or self.get_binary_path('app')
-        return run_firefox_ui_test(testtype='update',
-                                   topsrcdir=self.topsrcdir, **kwargs)
--- a/testing/firefox-ui/moz.build
+++ b/testing/firefox-ui/moz.build
@@ -1,12 +1,11 @@
 # 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/.
 
 FIREFOX_UI_FUNCTIONAL_MANIFESTS += ["tests/functional/manifest.ini"]
-FIREFOX_UI_UPDATE_MANIFESTS += ["tests/update/manifest.ini"]
 # TODO: Move to testing/marionette/puppeteer/firefox
 PUPPETEER_FIREFOX_MANIFESTS += ["tests/puppeteer/manifest.ini"]
 
 with Files("**"):
     BUG_COMPONENT = ("Testing", "Firefox UI Tests")
     SCHEDULES.exclusive = ["firefox-ui"]
--- a/testing/firefox-ui/tests/puppeteer/manifest.ini
+++ b/testing/firefox-ui/tests/puppeteer/manifest.ini
@@ -3,25 +3,21 @@ tags = local
 
 # API tests
 [test_appinfo.py]
 skip-if = artifact # bug 1298233 - build ids are different for artifact builds
 [test_l10n.py]
 [test_places.py]
 [test_security.py]
 tags = remote
-[test_software_update.py]
 [test_utils.py]
 
 # UI tests
 [test_about_window.py]
 [test_menubar.py]
 [test_notifications.py]
 [test_page_info_window.py]
 skip-if = true # bug 1523133
 [test_tabbar.py]
 [test_toolbars.py]
 disabled = Bug 1369556
 tags = remote
-[test_update_wizard.py]
-tags = remote
-skip-if = true # bug 1552771
 [test_windows.py]
deleted file mode 100644
--- a/testing/firefox-ui/tests/puppeteer/test_software_update.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-import os
-
-from firefox_puppeteer import PuppeteerMixin
-from firefox_puppeteer.api.software_update import SoftwareUpdate
-from marionette_harness import MarionetteTestCase
-
-
-class TestSoftwareUpdate(PuppeteerMixin, MarionetteTestCase):
-
-    def setUp(self):
-        super(TestSoftwareUpdate, self).setUp()
-
-        self.software_update = SoftwareUpdate(self.marionette)
-
-        self.saved_mar_channels = self.software_update.mar_channels.channels
-        self.software_update.mar_channels.channels = set(['expected', 'channels'])
-
-    def tearDown(self):
-        try:
-            self.software_update.mar_channels.channels = self.saved_mar_channels
-        finally:
-            super(TestSoftwareUpdate, self).tearDown()
-
-    def test_abi(self):
-        self.assertTrue(self.software_update.ABI)
-
-    def test_allowed(self):
-        # Updates are only allowed when run via the UpdateTestCase class
-        self.assertFalse(self.software_update.allowed)
-
-    def test_build_info(self):
-        self.software_update.update_url = self.marionette.absolute_url(
-            'update/snippet_empty.xml?product=%PRODUCT%&version=%VERSION%&'
-            'buildid=%BUILD_ID%&locale=%LOCALE%&channel=%CHANNEL%')
-
-        try:
-            build_info = self.software_update.build_info
-            self.assertEqual(build_info['disabled_addons'], None)
-            self.assertIn('Mozilla/', build_info['user_agent'])
-            self.assertEqual(build_info['mar_channels'], set(['expected', 'channels']))
-            self.assertTrue(build_info['version'])
-            self.assertTrue(build_info['buildid'].isdigit())
-            self.assertTrue(build_info['locale'])
-            self.assertIn('force=1', build_info['update_url'])
-            self.assertIn('xml', build_info['update_snippet'])
-            self.assertEqual(build_info['channel'], self.software_update.update_channel)
-        finally:
-            # Restart Firefox to reset the custom update url
-            self.restart(clean=True)
-
-    def test_force_fallback(self):
-        status_file = os.path.join(self.software_update.staging_directory, 'update.status')
-
-        try:
-            self.software_update.force_fallback()
-            with open(status_file, 'r') as f:
-                content = f.read()
-            self.assertEqual(content, 'failed: 6\n')
-        finally:
-            os.remove(status_file)
-
-    def test_get_update_url(self):
-        update_url = self.software_update.get_formatted_update_url()
-        self.assertIn('Firefox', update_url)
-        self.assertNotIn('force=1', update_url)
-        update_url = self.software_update.get_formatted_update_url(True)
-        self.assertIn('Firefox', update_url)
-        self.assertIn('force=1', update_url)
-
-    def test_os_version(self):
-        self.assertTrue(self.software_update.os_version)
-
-    def test_staging_directory(self):
-        self.assertTrue(self.software_update.staging_directory)
-
-
-class TestUpdateChannel(PuppeteerMixin, MarionetteTestCase):
-
-    def setUp(self):
-        super(TestUpdateChannel, self).setUp()
-
-        self.software_update = SoftwareUpdate(self.marionette)
-
-        self.saved_channel = self.software_update.update_channel
-        self.software_update.update_channel = 'expected_channel'
-
-    def tearDown(self):
-        try:
-            self.software_update.update_channel = self.saved_channel
-        finally:
-            super(TestUpdateChannel, self).tearDown()
-
-    def test_update_channel_default_channel(self):
-        # Without a restart the update channel will not change.
-        self.assertEqual(self.software_update.update_channel, self.saved_channel)
-
-    def test_update_channel_set_channel(self):
-        try:
-            # Use the clean option to force a non in_app restart, which would allow
-            # Firefox to dump the logs to the console.
-            self.restart(clean=True)
-            self.assertEqual(self.software_update.update_channel, 'expected_channel')
-            self.assertEqual(self.software_update.patch_info['channel'], 'expected_channel')
-        finally:
-            self.software_update.update_channel = self.saved_channel
-            self.restart(clean=True)
-
-
-class TestMARChannels(PuppeteerMixin, MarionetteTestCase):
-
-    def setUp(self):
-        super(TestMARChannels, self).setUp()
-
-        self.software_update = SoftwareUpdate(self.marionette)
-
-        self.saved_mar_channels = self.software_update.mar_channels.channels
-        self.software_update.mar_channels.channels = set(['expected', 'channels'])
-
-    def tearDown(self):
-        try:
-            self.software_update.mar_channels.channels = self.saved_mar_channels
-        finally:
-            super(TestMARChannels, self).tearDown()
-
-    def test_mar_channels_channels(self):
-        self.assertEqual(self.software_update.mar_channels.channels, set(['expected', 'channels']))
-
-    def test_mar_channels_set_channels(self):
-        self.software_update.mar_channels.channels = set(['a', 'b', 'c'])
-        self.assertEqual(self.software_update.mar_channels.channels, set(['a', 'b', 'c']))
-
-    def test_mar_channels_add_channels(self):
-        self.software_update.mar_channels.add_channels(set(['some', 'new', 'channels']))
-        self.assertEqual(
-            self.software_update.mar_channels.channels,
-            set(['expected', 'channels', 'some', 'new']))
-
-    def test_mar_channels_remove_channels(self):
-        self.software_update.mar_channels.remove_channels(set(['expected']))
-        self.assertEqual(self.software_update.mar_channels.channels, set(['channels']))
deleted file mode 100644
--- a/testing/firefox-ui/tests/puppeteer/test_update_wizard.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-from firefox_puppeteer import PuppeteerMixin
-from firefox_puppeteer.ui.deck import Panel
-from firefox_puppeteer.ui.update_wizard import UpdateWizardDialog
-from marionette_harness import MarionetteTestCase
-
-
-class TestUpdateWizard(PuppeteerMixin, MarionetteTestCase):
-
-    def setUp(self):
-        super(TestUpdateWizard, self).setUp()
-
-        def opener(win):
-            self.marionette.execute_script("""
-              let updatePrompt = Components.classes["@mozilla.org/updates/update-prompt;1"]
-                                 .createInstance(Components.interfaces.nsIUpdatePrompt);
-              updatePrompt.checkForUpdates();
-            """)
-
-        self.dialog = self.browser.open_window(callback=opener,
-                                               expected_window_class=UpdateWizardDialog)
-        self.wizard = self.dialog.wizard
-
-    def tearDown(self):
-        try:
-            self.puppeteer.windows.close_all([self.browser])
-        finally:
-            super(TestUpdateWizard, self).tearDown()
-
-    def test_basic(self):
-        self.assertEqual(self.dialog.window_type, 'Update:Wizard')
-        self.assertNotEqual(self.dialog.dtds, [])
-        self.assertNotEqual(self.dialog.properties, [])
-
-    def test_elements(self):
-        """Test correct retrieval of elements."""
-        self.assertEqual(self.wizard.element.get_property('localName'), 'wizard')
-
-        buttons = ('cancel_button', 'extra1_button', 'extra2_button',
-                   'finish_button', 'next_button', 'previous_button',
-                   )
-        for button in buttons:
-            self.assertEqual(getattr(self.wizard, button).get_property('localName'),
-                             'button')
-
-        panels = ('checking', 'downloading', 'dummy', 'error_patching', 'error',
-                  'error_extra', 'finished', 'finished_background',
-                  'manual_update', 'no_updates_found', 'updates_found_basic',
-                  )
-        for panel in panels:
-            self.assertEqual(getattr(self.wizard, panel).element.get_property('localName'),
-                             'wizardpage')
-
-        # elements of the checking panel
-        self.assertEqual(self.wizard.checking.progress.get_property('localName'),
-                         'progress')
-
-        # elements of the downloading panel
-        self.assertEqual(self.wizard.downloading.progress.get_property('localName'),
-                         'progress')
-
-        # check wizard attributes
-        self.assertIsInstance(self.wizard.selected_index, int)
-        self.assertIsInstance(self.wizard.selected_panel, Panel)
deleted file mode 100644
--- a/testing/firefox-ui/tests/update/direct/manifest.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[DEFAULT]
-tags = direct
-
-[test_direct_update.py]
deleted file mode 100644
--- a/testing/firefox-ui/tests/update/direct/test_direct_update.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-from firefox_ui_harness.testcases import UpdateTestCase
-
-
-class TestDirectUpdate(UpdateTestCase):
-
-    def setUp(self):
-        UpdateTestCase.setUp(self, is_fallback=False)
-
-    def tearDown(self):
-        try:
-            self.puppeteer.windows.close_all([self.browser])
-        finally:
-            UpdateTestCase.tearDown(self)
-
-    def test_update(self):
-        self.download_and_apply_available_update(force_fallback=False)
-        self.check_update_applied()
deleted file mode 100644
--- a/testing/firefox-ui/tests/update/fallback/manifest.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[DEFAULT]
-tags = fallback
-
-[test_fallback_update.py]
deleted file mode 100644
--- a/testing/firefox-ui/tests/update/fallback/test_fallback_update.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-from firefox_ui_harness.testcases import UpdateTestCase
-
-
-class TestFallbackUpdate(UpdateTestCase):
-
-    def setUp(self):
-        UpdateTestCase.setUp(self, is_fallback=True)
-
-    def tearDown(self):
-        try:
-            self.puppeteer.windows.close_all([self.browser])
-        finally:
-            UpdateTestCase.tearDown(self)
-
-    def test_update(self):
-        self.download_and_apply_available_update(force_fallback=True)
-        self.download_and_apply_forced_update()
-        self.check_update_applied()
deleted file mode 100644
--- a/testing/firefox-ui/tests/update/manifest.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[include:direct/manifest.ini]
-[include:fallback/manifest.ini]
deleted file mode 100644
--- a/testing/marionette/puppeteer/firefox/docs/api/software_update.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-.. py:currentmodule:: firefox_puppeteer.api.software_update
-
-SoftwareUpdate
-==============
-
-The SoftwareUpdate class provides helpers for update tests.
-
-SoftwareUpdate
---------------
-
-.. autoclass:: SoftwareUpdate
-   :members:
-
-ActiveUpdate
-------------
-
-.. autoclass:: ActiveUpdate
-   :members:
-
-MARChannels
------------
-
-.. autoclass:: MARChannels
-   :members:
-
-UpdateChannel
--------------
-
-.. autoclass:: UpdateChannel
-   :members:
--- a/testing/marionette/puppeteer/firefox/docs/index.rst
+++ b/testing/marionette/puppeteer/firefox/docs/index.rst
@@ -61,24 +61,22 @@ future. Each library is available from a
    ui/about_window/window
    ui/deck
    ui/menu
    ui/pageinfo/window
    ui/browser/notifications
    ui/browser/tabbar
    ui/browser/toolbars
    ui/browser/window
-   ui/update_wizard/dialog
    ui/windows
    api/appinfo
    api/keys
    api/l10n
    api/places
    api/security
-   api/software_update
    api/utils
 
 
 Indices and tables
 ==================
 
 * :ref:`genindex`
 * :ref:`modindex`
deleted file mode 100644
--- a/testing/marionette/puppeteer/firefox/docs/ui/update_wizard/dialog.rst
+++ /dev/null
@@ -1,128 +0,0 @@
-Update Wizard Dialog
-====================
-
-UpdateWizardDialog
-------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.dialog.UpdateWizardDialog
-   :members:
-   :inherited-members:
-
-Wizard
-------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.Wizard
-   :members:
-   :inherited-members:
-
-CheckingPanel
--------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.CheckingPanel
-   :members:
-   :inherited-members:
-
-DownloadingPanel
-----------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.DownloadingPanel
-   :members:
-   :inherited-members:
-
-DummyPanel
-----------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.DummyPanel
-   :members:
-   :inherited-members:
-
-ErrorPatchingPanel
-------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.ErrorPatchingPanel
-   :members:
-   :inherited-members:
-
-ErrorPanel
-----------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.ErrorPanel
-   :members:
-   :inherited-members:
-
-ErrorExtraPanel
----------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.ErrorExtraPanel
-   :members:
-   :inherited-members:
-
-FinishedPanel
--------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.FinishedPanel
-   :members:
-   :inherited-members:
-
-FinishedBackgroundPanel
------------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.FinishedBackgroundPanel
-   :members:
-   :inherited-members:
-
-IncompatibleCheckPanel
-----------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.IncompatibleCheckPanel
-   :members:
-   :inherited-members:
-
-IncompatibleListPanel
----------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.IncompatibleListPanel
-   :members:
-   :inherited-members:
-
-InstalledPanel
---------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.InstalledPanel
-   :members:
-   :inherited-members:
-
-LicensePanel
-------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.LicensePanel
-   :members:
-   :inherited-members:
-
-ManualUpdatePanel
------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.ManualUpdatePanel
-   :members:
-   :inherited-members:
-
-NoUpdatesFoundPanel
--------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.NoUpdatesFoundPanel
-   :members:
-   :inherited-members:
-
-PluginUpdatesFoundPanel
------------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.PluginUpdatesFoundPanel
-   :members:
-   :inherited-members:
-
-UpdatesFoundBasicPanel
-----------------------
-
-.. autoclass:: firefox_puppeteer.ui.update_wizard.wizard.UpdatesFoundBasicPanel
-   :members:
-   :inherited-members:
deleted file mode 100644
--- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/api/software_update.py
+++ /dev/null
@@ -1,422 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-
-import ConfigParser
-import os
-import re
-import sys
-
-from six import reraise
-
-from firefox_puppeteer.base import BaseLib
-from firefox_puppeteer.api.appinfo import AppInfo
-
-
-class ActiveUpdate(BaseLib):
-
-    def __getattr__(self, attr):
-        value = self.marionette.execute_script("""
-          let ums = Components.classes['@mozilla.org/updates/update-manager;1']
-                    .getService(Components.interfaces.nsIUpdateManager);
-          return ums.activeUpdate[arguments[0]];
-        """, script_args=[attr])
-
-        if value:
-            return value
-        else:
-            raise AttributeError('{} has no attribute {}'.format(self.__class__.__name__,
-                                                                 attr))
-
-    @property
-    def exists(self):
-        """Checks if there is an active update.
-
-        :returns: True if there is an active update
-        """
-        active_update = self.marionette.execute_script("""
-          let ums = Components.classes['@mozilla.org/updates/update-manager;1']
-                    .getService(Components.interfaces.nsIUpdateManager);
-          return ums.activeUpdate;
-        """)
-
-        return bool(active_update)
-
-    def get_patch_at(self, patch_index):
-        """Use nsIUpdate.getPatchAt to return a patch from an update.
-
-        :returns: JSON data for an nsIUpdatePatch object
-        """
-        return self.marionette.execute_script("""
-          let ums = Components.classes['@mozilla.org/updates/update-manager;1']
-                    .getService(Components.interfaces.nsIUpdateManager);
-          return ums.activeUpdate.getPatchAt(arguments[0]);
-        """, script_args=[patch_index])
-
-    @property
-    def patch_count(self):
-        """Get the patchCount from the active update.
-
-        :returns: The patch count
-        """
-        return self.marionette.execute_script("""
-          let ums = Components.classes['@mozilla.org/updates/update-manager;1']
-                    .getService(Components.interfaces.nsIUpdateManager);
-          return ums.activeUpdate.patchCount;
-        """)
-
-    @property
-    def selected_patch(self):
-        """Get the selected patch for the active update.
-
-        :returns: JSON data for the selected patch
-        """
-        return self.marionette.execute_script("""
-          let ums = Components.classes['@mozilla.org/updates/update-manager;1']
-                    .getService(Components.interfaces.nsIUpdateManager);
-          return ums.activeUpdate.selectedPatch;
-    """)
-
-
-class MARChannels(BaseLib):
-    """Class to handle the allowed MAR channels as listed in update-settings.ini."""
-    INI_SECTION = 'Settings'
-    INI_OPTION = 'ACCEPTED_MAR_CHANNEL_IDS'
-
-    class MARConfigParser(ConfigParser.ConfigParser):
-        """INI parser which allows to read and write MAR config files.
-
-        Virtually identical to the original method, but delimit keys and values
-        with '=' instead of ' = '
-        """
-
-        def write(self, fp):
-            """Write an .ini-format representation of the configuration state."""
-            if self._defaults:
-                fp.write("[%s]\n" % ConfigParser.DEFAULTSECT)
-                for (key, value) in self._defaults.items():
-                    fp.write("%s=%s\n" % (key, str(value).replace('\n', '\n\t')))
-                fp.write("\n")
-            for section in self._sections:
-                fp.write("[%s]\n" % section)
-                for (key, value) in self._sections[section].items():
-                    if key == "__name__":
-                        continue
-                    if (value is not None) or (self._optcre == self.OPTCRE):
-                        key = "=".join((key, str(value).replace('\n', '\n\t')))
-                    fp.write("%s\n" % (key))
-                fp.write("\n")
-
-    def __init__(self, marionette):
-        BaseLib.__init__(self, marionette)
-
-        self.config_file_path = self.marionette.execute_script("""
-          Components.utils.import('resource://gre/modules/Services.jsm');
-
-          let file = Services.dirsvc.get('GreD', Components.interfaces.nsIFile);
-          file.append('update-settings.ini');
-
-          return file.path;
-        """)
-
-        self.config = self.MARConfigParser()
-        self.config.optionxform = str
-
-    @property
-    def channels(self):
-        """The currently accepted MAR channels.
-
-        :returns: A set of channel names
-        """
-        # Make sure to always read the current file contents
-        self.config.read(self.config_file_path)
-
-        return set(self.config.get(self.INI_SECTION, self.INI_OPTION).split(','))
-
-    @channels.setter
-    def channels(self, channels):
-        """Set the accepted MAR channels.
-
-        :param channels: A set of channel names
-        """
-        self.config.set(self.INI_SECTION, self.INI_OPTION, ','.join(channels))
-        with open(self.config_file_path, 'wb') as configfile:
-            self.config.write(configfile)
-
-    def add_channels(self, channels):
-        """Add additional MAR channels.
-
-        :param channels: A set of channel names to add
-        """
-        self.channels = self.channels | set(channels)
-
-    def remove_channels(self, channels):
-        """Remove MAR channels.
-
-        :param channels: A set of channel names to remove
-        """
-        self.channels = self.channels - set(channels)
-
-
-class SoftwareUpdate(BaseLib):
-    """The SoftwareUpdate API adds support for an easy access to the update process."""
-    PREF_APP_DISTRIBUTION = 'distribution.id'
-    PREF_APP_DISTRIBUTION_VERSION = 'distribution.version'
-    PREF_APP_UPDATE_CHANNEL = 'app.update.channel'
-    PREF_APP_UPDATE_URL = 'app.update.url'
-    PREF_DISABLED_ADDONS = 'extensions.disabledAddons'
-
-    def __init__(self, marionette):
-        BaseLib.__init__(self, marionette)
-
-        self.app_info = AppInfo(marionette)
-
-        self._mar_channels = MARChannels(marionette)
-        self._active_update = ActiveUpdate(marionette)
-
-    @property
-    def ABI(self):
-        """Get the customized ABI for the update service.
-
-        :returns: ABI version
-        """
-        return self.app_info.XPCOMABI
-
-    @property
-    def active_update(self):
-        """ Holds a reference to an :class:`ActiveUpdate` object."""
-        return self._active_update
-
-    @property
-    def allowed(self):
-        """Check if the user has permissions to run the software update
-
-        :returns: Status if the user has the permissions
-        """
-        return self.marionette.execute_script("""
-          let aus = Components.classes['@mozilla.org/updates/update-service;1']
-                    .getService(Components.interfaces.nsIApplicationUpdateService);
-          return aus.canCheckForUpdates && aus.canApplyUpdates;
-        """)
-
-    @property
-    def build_info(self):
-        """Return information of the current build version
-
-        :returns: A dictionary of build information
-        """
-        update_url = self.get_formatted_update_url(True)
-
-        return {
-            'buildid': self.app_info.appBuildID,
-            'channel': self.update_channel,
-            'disabled_addons': self.marionette.get_pref(self.PREF_DISABLED_ADDONS),
-            'locale': self.app_info.locale,
-            'mar_channels': self.mar_channels.channels,
-            'update_url': update_url,
-            'update_snippet': self.get_update_snippet(update_url),
-            'user_agent': self.app_info.user_agent,
-            'version': self.app_info.version
-        }
-
-    @property
-    def is_complete_update(self):
-        """Return true if the offered update is a complete update
-
-        :returns: True if the offered update is a complete update
-        """
-        # Throw when isCompleteUpdate is called without an update. This should
-        # never happen except if the test is incorrectly written.
-        assert self.active_update.exists, 'An active update has been found'
-
-        patch_count = self.active_update.patch_count
-        assert patch_count == 1 or patch_count == 2,\
-            'An update must have one or two patches included'
-
-        # Ensure Partial and Complete patches produced have unique urls
-        if patch_count == 2:
-            patch0_url = self.active_update.get_patch_at(0)['URL']
-            patch1_url = self.active_update.get_patch_at(1)['URL']
-            assert patch0_url != patch1_url,\
-                'Partial and Complete download URLs are different'
-
-        return self.active_update.selected_patch['type'] == 'complete'
-
-    @property
-    def mar_channels(self):
-        """ Holds a reference to a :class:`MARChannels` object."""
-        return self._mar_channels
-
-    @property
-    def os_version(self):
-        """Returns information about the OS version
-
-        :returns: The OS version
-        """
-        return self.marionette.execute_script("""
-          Components.utils.import("resource://gre/modules/Services.jsm");
-
-          let osVersion;
-          try {
-            osVersion = Services.sysinfo.getProperty("name") + " " +
-                        Services.sysinfo.getProperty("version");
-          }
-          catch (ex) {
-          }
-
-          if (osVersion) {
-            try {
-              osVersion += " (" + Services.sysinfo.getProperty("secondaryLibrary") + ")";
-            }
-            catch (e) {
-              // Not all platforms have a secondary widget library,
-              // so an error is nothing to worry about.
-            }
-            osVersion = encodeURIComponent(osVersion);
-          }
-          return osVersion;
-        """)
-
-    @property
-    def patch_info(self):
-        """ Returns information of the active update in the queue."""
-        info = {'channel': self.update_channel}
-
-        if (self.active_update.exists):
-            info['buildid'] = self.active_update.buildID
-            info['is_complete'] = self.is_complete_update
-            info['size'] = self.active_update.selected_patch['size']
-            info['type'] = self.update_type
-            info['url_mirror'] = \
-                self.active_update.selected_patch['finalURL'] or 'n/a'
-            info['version'] = self.active_update.appVersion
-
-        return info
-
-    @property
-    def staging_directory(self):
-        """ Returns the path to the updates staging directory."""
-        return self.marionette.execute_script("""
-          let aus = Components.classes['@mozilla.org/updates/update-service;1']
-                    .getService(Components.interfaces.nsIApplicationUpdateService);
-          return aus.getUpdatesDirectory().path;
-        """)
-
-    @property
-    def update_channel(self):
-        """Return the currently used update channel."""
-        return self.marionette.get_pref(self.PREF_APP_UPDATE_CHANNEL,
-                                        default_branch=True)
-
-    @update_channel.setter
-    def update_channel(self, channel):
-        """Set the update channel to be used for update checks.
-
-        :param channel: New update channel to use
-
-        """
-        writer = UpdateChannelWriter(self.marionette)
-        writer.set_channel(channel)
-
-    @property
-    def update_url(self):
-        """Return the update URL used for update checks."""
-        return self.marionette.get_pref(self.PREF_APP_UPDATE_URL,
-                                        default_branch=True)
-
-    @update_url.setter
-    def update_url(self, url):
-        """Set the update URL to be used for update checks.
-
-        :param url: New update URL to use
-
-        """
-        self.marionette.set_pref(self.PREF_APP_UPDATE_URL, url,
-                                 default_branch=True)
-
-    @property
-    def update_type(self):
-        """Returns the type of the active update."""
-        return self.active_update.type
-
-    def force_fallback(self):
-        """Update the update.status file and set the status to 'failed:6'"""
-        with open(os.path.join(self.staging_directory, 'update.status'), 'w') as f:
-            f.write('failed: 6\n')
-
-    def get_update_snippet(self, update_url):
-        """Retrieve contents of the update snippet.
-
-        :param update_url: URL to the update snippet
-        """
-        import urllib2
-        try:
-            response = urllib2.urlopen(update_url)
-            return response.read()
-        except urllib2.URLError:
-            exc, val, tb = sys.exc_info()
-            msg = "Failed to retrieve update snippet '{0}': {1}"
-            reraise(Exception, msg.format(update_url, val), tb)
-
-    def get_formatted_update_url(self, force=False):
-        """Retrieve the formatted AUS update URL the update snippet is retrieved from.
-
-        :param force: Boolean flag to force an update check
-
-        :returns: The URL of the update snippet
-        """
-        url = self.marionette.execute_async_script("""
-          let resolve = arguments[arguments.length - 1];
-          Components.utils.import("resource://gre/modules/UpdateUtils.jsm");
-          let res = UpdateUtils.formatUpdateURL(arguments[0]);
-
-          // Format the URL by replacing placeholders
-          // In 56 we switched the method to be async.
-          // For now, support both approaches.
-          if (res.then) {
-            res.then(resolve);
-          } else {
-            resolve(res);
-          }
-        """, script_args=[self.update_url])
-
-        if force:
-            if '?' in url:
-                url += '&'
-            else:
-                url += '?'
-            url += 'force=1'
-
-        return url
-
-
-class UpdateChannelWriter(BaseLib):
-    """Class to handle the update channel as listed in channel-prefs.js"""
-    REGEX_UPDATE_CHANNEL = re.compile(r'("app\.update\.channel", ")([^"].*)(?=")')
-
-    def __init__(self, *args, **kwargs):
-        BaseLib.__init__(self, *args, **kwargs)
-
-        self.file_path = self.marionette.execute_script("""
-          Components.utils.import('resource://gre/modules/Services.jsm');
-
-          let file = Services.dirsvc.get('PrfDef', Components.interfaces.nsIFile);
-          file.append('channel-prefs.js');
-
-          return file.path;
-        """)
-
-    def set_channel(self, channel):
-        """Set default update channel.
-
-        :param channel: New default update channel
-        """
-        with open(self.file_path) as f:
-            file_contents = f.read()
-
-        new_content = re.sub(
-            self.REGEX_UPDATE_CHANNEL, r'\g<1>' + channel, file_contents)
-        with open(self.file_path, 'w') as f:
-            f.write(new_content)
deleted file mode 100644
--- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-
-from .dialog import UpdateWizardDialog
deleted file mode 100644
--- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/dialog.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-
-from marionette_driver import By, Wait
-
-from firefox_puppeteer.ui.update_wizard.wizard import Wizard
-from firefox_puppeteer.ui.windows import BaseWindow, Windows
-
-
-# Bug 1143020 - Subclass from BaseDialog ui class with possible wizard mixin
-class UpdateWizardDialog(BaseWindow):
-    """Representation of the old Software Update Wizard Dialog."""
-    window_type = 'Update:Wizard'
-
-    dtds = [
-        'chrome://branding/locale/brand.dtd',
-        'chrome://mozapps/locale/update/updates.dtd',
-    ]
-
-    properties = [
-        'chrome://branding/locale/brand.properties',
-        'chrome://mozapps/locale/update/updates.properties',
-    ]
-
-    @property
-    def wizard(self):
-        """The :class:`Wizard` instance which represents the wizard.
-
-        :returns: Reference to the wizard.
-        """
-        # The deck is also the root element
-        wizard = self.marionette.find_element(By.ID, 'updates')
-        return Wizard(self.marionette, self, wizard)
-
-    def select_next_page(self):
-        """Clicks on "Next" button, and waits for the next page to show up."""
-        current_panel = self.wizard.selected_panel
-
-        self.wizard.next_button.click()
-        Wait(self.marionette).until(
-            lambda _: self.wizard.selected_panel != current_panel,
-            message='Next panel has not been selected.')
-
-
-Windows.register_window(UpdateWizardDialog.window_type, UpdateWizardDialog)
deleted file mode 100644
--- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py
+++ /dev/null
@@ -1,293 +0,0 @@
-# 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/.
-
-from __future__ import absolute_import
-
-from marionette_driver import By, Wait
-
-from firefox_puppeteer.ui.base import UIBaseLib
-from firefox_puppeteer.ui.deck import Panel
-
-
-class Wizard(UIBaseLib):
-
-    def __init__(self, *args, **kwargs):
-        super(Wizard, self).__init__(*args, **kwargs)
-
-        Wait(self.marionette).until(
-            lambda _: self.selected_panel,
-            message='No panel has been selected by default.')
-
-    def _create_panel_for_id(self, panel_id):
-        """Creates an instance of :class:`Panel` for the specified panel id.
-
-        :param panel_id: The ID of the panel to create an instance of.
-
-        :returns: :class:`Panel` instance
-        """
-        mapping = {'checking': CheckingPanel,
-                   'downloading': DownloadingPanel,
-                   'dummy': DummyPanel,
-                   'errorpatching': ErrorPatchingPanel,
-                   'errors': ErrorPanel,
-                   'errorextra': ErrorExtraPanel,
-                   'finished': FinishedPanel,
-                   'finishedBackground': FinishedBackgroundPanel,
-                   'manualUpdate': ManualUpdatePanel,
-                   'noupdatesfound': NoUpdatesFoundPanel,
-                   'updatesfoundbasic': UpdatesFoundBasicPanel,
-
-                   # TODO: Remove once we no longer support version Firefox 45.0ESR
-                   'incompatibleCheck': IncompatibleCheckPanel,
-                   'incompatibleList': IncompatibleListPanel,
-                   }
-
-        panel = self.element.find_element(By.ID, panel_id)
-        return mapping.get(panel_id, Panel)(self.marionette, self.window, panel)
-
-    # Properties for visual buttons of the wizard #
-
-    @property
-    def _buttons(self):
-        return self.element.get_property('_wizardButtons')
-
-    @property
-    def cancel_button(self):
-        return self._buttons.find_element(By.CSS_SELECTOR, '[dlgtype="cancel"]')
-
-    @property
-    def extra1_button(self):
-        return self._buttons.find_element(By.CSS_SELECTOR, '[dlgtype="extra1"]')
-
-    @property
-    def extra2_button(self):
-        return self._buttons.find_element(By.CSS_SELECTOR, '[dlgtype="extra2"]')
-
-    @property
-    def previous_button(self):
-        return self._buttons.find_element(By.CSS_SELECTOR, '[dlgtype="back"]')
-
-    @property
-    def finish_button(self):
-        return self._buttons.find_element(By.CSS_SELECTOR, '[dlgtype="finish"]')
-
-    @property
-    def next_button(self):
-        return self._buttons.find_element(By.CSS_SELECTOR, '[dlgtype="next"]')
-
-    # Properties for visual panels of the wizard #
-
-    @property
-    def checking(self):
-        """The checking for updates panel.
-
-        :returns: :class:`CheckingPanel` instance.
-        """
-        return self._create_panel_for_id('checking')
-
-    @property
-    def downloading(self):
-        """The downloading panel.
-
-        :returns: :class:`DownloadingPanel` instance.
-        """
-        return self._create_panel_for_id('downloading')
-
-    @property
-    def dummy(self):
-        """The dummy panel.
-
-        :returns: :class:`DummyPanel` instance.
-        """
-        return self._create_panel_for_id('dummy')
-
-    @property
-    def error_patching(self):
-        """The error patching panel.
-
-        :returns: :class:`ErrorPatchingPanel` instance.
-        """
-        return self._create_panel_for_id('errorpatching')
-
-    @property
-    def error(self):
-        """The errors panel.
-
-        :returns: :class:`ErrorPanel` instance.
-        """
-        return self._create_panel_for_id('errors')
-
-    @property
-    def error_extra(self):
-        """The error extra panel.
-
-        :returns: :class:`ErrorExtraPanel` instance.
-        """
-        return self._create_panel_for_id('errorextra')
-
-    @property
-    def finished(self):
-        """The finished panel.
-
-        :returns: :class:`FinishedPanel` instance.
-        """
-        return self._create_panel_for_id('finished')
-
-    @property
-    def finished_background(self):
-        """The finished background panel.
-
-        :returns: :class:`FinishedBackgroundPanel` instance.
-        """
-        return self._create_panel_for_id('finishedBackground')
-
-    @property
-    def incompatible_check(self):
-        """The incompatible check panel.
-
-        :returns: :class:`IncompatibleCheckPanel` instance.
-        """
-        return self._create_panel_for_id('incompatibleCheck')
-
-    @property
-    def incompatible_list(self):
-        """The incompatible list panel.
-
-        :returns: :class:`IncompatibleListPanel` instance.
-        """
-        return self._create_panel_for_id('incompatibleList')
-
-    @property
-    def manual_update(self):
-        """The manual update panel.
-
-        :returns: :class:`ManualUpdatePanel` instance.
-        """
-        return self._create_panel_for_id('manualUpdate')
-
-    @property
-    def no_updates_found(self):
-        """The no updates found panel.
-
-        :returns: :class:`NoUpdatesFoundPanel` instance.
-        """
-        return self._create_panel_for_id('noupdatesfound')
-
-    @property
-    def updates_found_basic(self):
-        """The updates found panel.
-
-        :returns: :class:`UpdatesFoundPanel` instance.
-        """
-        return self._create_panel_for_id('updatesfoundbasic')
-
-    @property
-    def panels(self):
-        """List of all the available :class:`Panel` instances.
-
-        :returns: List of :class:`Panel` instances.
-        """
-        panels = self.marionette.execute_script("""
-          let wizard = arguments[0];
-          let panels = [];
-
-          for (let index = 0; index < wizard.children.length; index++) {
-            if (wizard.children[index].id) {
-              panels.push(wizard.children[index].id);
-            }
-          }
-
-          return panels;
-        """, script_args=[self.element])
-
-        return [self._create_panel_for_id(panel) for panel in panels]
-
-    @property
-    def selected_index(self):
-        """The index of the currently selected panel.
-
-        :return: Index of the selected panel.
-        """
-        return int(self.element.get_property('pageIndex'))
-
-    @property
-    def selected_panel(self):
-        """A :class:`Panel` instance of the currently selected panel.
-
-        :returns: :class:`Panel` instance.
-        """
-        return self._create_panel_for_id(self.element.get_attribute('currentpageid'))
-
-
-class CheckingPanel(Panel):
-
-    @property
-    def progress(self):
-        """The DOM element which represents the progress meter.
-
-        :returns: Reference to the progress element.
-        """
-        return self.element.find_element(By.ID, 'checkingProgress')
-
-
-class DownloadingPanel(Panel):
-
-    @property
-    def progress(self):
-        """The DOM element which represents the progress meter.
-
-        :returns: Reference to the progress element.
-        """
-        return self.element.find_element(By.ID, 'downloadProgress')
-
-
-class DummyPanel(Panel):
-    pass
-
-
-class ErrorPatchingPanel(Panel):
-    pass
-
-
-class ErrorPanel(Panel):
-    pass
-
-
-class ErrorExtraPanel(Panel):
-    pass
-
-
-class FinishedPanel(Panel):
-    pass
-
-
-class FinishedBackgroundPanel(Panel):
-    pass
-
-
-class IncompatibleCheckPanel(Panel):
-
-    @property
-    def progress(self):
-        """The DOM element which represents the progress meter.
-
-        :returns: Reference to the progress element.
-        """
-        return self.element.find_element(By.ID, 'incompatibleCheckProgress')
-
-
-class IncompatibleListPanel(Panel):
-    pass
-
-
-class ManualUpdatePanel(Panel):
-    pass
-
-
-class NoUpdatesFoundPanel(Panel):
-    pass
-
-
-class UpdatesFoundBasicPanel(Panel):
-    pass
--- a/tools/lint/py3.yml
+++ b/tools/lint/py3.yml
@@ -9,17 +9,16 @@ py3:
         - dom/canvas/test
         - gfx
         - ipc/ipdl
         - layout/reftests
         - layout/style/ServoCSSPropList.mako.py
         - layout/tools/reftest
         - security/manager/ssl
         - testing/awsy
-        - testing/firefox-ui/harness/firefox_ui_harness/runners/update.py
         - testing/gtest
         - testing/mozharness
         - testing/tps
         - testing/web-platform
         - toolkit
         - tools/profiler
         - tools/rb
         - xpcom/idl-parser