Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,80 @@
# 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 marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base, PageRegion
from gaiatest.apps.music.regions.sublist_view import AlbumSublistView, ArtistSublistView
from gaiatest.apps.music.regions.player_view import PlayerView
class ListView(Base):
_list_item_locator = (By.CLASS_NAME, 'gfl-item')
def _set_active_view_locator(self, type):
self._active_view_locator = (By.CSS_SELECTOR, 'iframe.active[src*="/views/{}/index.html"]'.format(type))
@property
def media(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
elements = Wait(self.marionette).until(
expected.elements_present(*self._list_item_locator))
Wait(self.marionette).until(expected.element_displayed(elements[0]))
self.apps.switch_to_displayed_app()
return [Media(self.marionette, element, self._active_view_locator) for element in elements]
class AlbumsView(ListView):
def __init__(self, marionette):
ListView.__init__(self, marionette)
self._set_active_view_locator('albums')
class ArtistsView(ListView):
def __init__(self, marionette):
ListView.__init__(self, marionette)
self._set_active_view_locator('artists')
class SongsView(ListView):
def __init__(self, marionette):
ListView.__init__(self, marionette)
self._set_active_view_locator('songs')
class Media(PageRegion):
_first_media_link_locator = (By.CLASS_NAME, 'gfl-item first')
def __init__(self, marionette, element, _active_view_locator):
PageRegion.__init__(self, marionette, element)
self._active_view_locator = _active_view_locator
def switch_to_active_view(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
def tap_first_album(self):
self.switch_to_active_view()
self.marionette.find_element(*self._first_media_link_locator).tap()
self.apps.switch_to_displayed_app()
return AlbumSublistView(self.marionette)
def tap_first_song(self):
self.switch_to_active_view()
self.marionette.find_element(*self._first_media_link_locator).tap()
self.apps.switch_to_displayed_app()
return PlayerView(self.marionette)
def tap_first_artist(self):
self.switch_to_active_view()
self.marionette.find_element(*self._first_media_link_locator).tap()
self.apps.switch_to_displayed_app()
return ArtistSublistView(self.marionette)
def a11y_click_first_album(self):
self.switch_to_active_view()
self.accessibility.click(
self.marionette.find_element(*self._first_media_link_locator))
self.apps.switch_to_displayed_app()
return AlbumSublistView(self.marionette)

View file

@ -0,0 +1,109 @@
# 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/.
import time
from marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
class PlayerView(Base):
_audio_locator = (By.ID, 'audio')
_active_view_locator = (By.CSS_SELECTOR, 'iframe.active[src*="/views/player/index.html"]')
_player_seek_elapsed_locator = (By.ID, 'elapsed-time')
_player_controls_shadow_dom_locator = (By.ID, 'controls')
_player_controls_play_locator = (By.ID, 'toggle')
_player_controls_forward_locator = (By.ID, 'next')
_cover_image_shadow_dom_locator = (By.ID, 'artwork')
_seek_bar_shadow_dom_locator = (By.ID, 'seek-bar')
_cover_share_locator = (By.CSS_SELECTOR, '[data-l10n-id="share-song"]')
_rating_view_locator = (By.ID, 'rating')
_stars_on_locator = (By.CSS_SELECTOR, '.rating-star.star-on')
def __init__(self, marionette):
Base.__init__(self, marionette)
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
element = self.marionette.find_element(*self._cover_image_shadow_dom_locator)
Wait(self.marionette).until(lambda m: element.rect['x'] == 0 and element.is_displayed())
self.apps.switch_to_displayed_app()
def tap_play(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._player_controls_shadow_dom_locator))
self.marionette.find_element(*self._player_controls_play_locator).tap()
self.apps.switch_to_displayed_app()
def tap_forward(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._player_controls_shadow_dom_locator))
self.marionette.find_element(*self._player_controls_forward_locator).tap()
self.apps.switch_to_displayed_app()
def tap_cover_in_player_view(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._cover_image_shadow_dom_locator))
#wait until the overlay disappears
Wait(self.marionette).until(expected.element_not_displayed(*self._rating_view_locator))
self.marionette.switch_to_shadow_root()
self.marionette.find_element(*self._cover_image_shadow_dom_locator).tap()
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._cover_image_shadow_dom_locator))
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(*self._rating_view_locator))))
self.apps.switch_to_displayed_app()
def tap_share_button(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._cover_image_shadow_dom_locator))
self.marionette.find_element(*self._cover_share_locator).tap()
from gaiatest.apps.system.regions.activities import Activities
return Activities(self.marionette)
def _get_star_locator(self, rating):
return By.CSS_SELECTOR, 'button[value="%s"]' % rating
def tap_star(self, rate):
"""
give rating. (After tapping the cover to make the ratings overlay appear)
"""
self.tap_cover_in_player_view()
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._cover_image_shadow_dom_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._rating_view_locator))
Wait(self.marionette).until(expected.element_displayed(*self._get_star_locator(rate)))
self.marionette.find_element(*self._get_star_locator(rate)).tap()
self.apps.switch_to_displayed_app()
@property
def star_rating(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._cover_image_shadow_dom_locator))
rating = self.marionette.find_element(*self._rating_view_locator).get_attribute('value')
self.apps.switch_to_displayed_app()
return int(rating)
@property
def player_elapsed_time(self):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
self.marionette.switch_to_shadow_root(self.marionette.find_element(*self._seek_bar_shadow_dom_locator))
Wait(self.marionette).until(expected.element_displayed(
Wait(self.marionette).until(expected.element_present(*self._player_seek_elapsed_locator))))
elapsed_time = time.strptime(self.marionette.find_element(*self._player_seek_elapsed_locator).text, '%M:%S')
self.apps.switch_to_displayed_app()
return elapsed_time
def is_player_playing(self):
# get 4 timestamps during approx. 1 sec
# ensure that newer timestamp has greater value than previous one
timestamps = []
for i in range(4):
timestamps.append(self.player_current_timestamp)
time.sleep(.25)
return all([timestamps[i - 1] < timestamps[i] for i in range(1, 3)])
@property
def player_current_timestamp(self):
player = self.marionette.find_element(*self._audio_locator)
return float(player.get_attribute('currentTime'))

View file

@ -0,0 +1,49 @@
# 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 marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.apps.music.regions.player_view import PlayerView
class SublistView(Base):
_list_locator = (By.ID, 'list')
_first_song_locator = (By.CLASS_NAME, 'gfl-item first')
def _set_active_view(self, type):
self._active_view_locator = (By.CSS_SELECTOR, 'iframe.active[src*="/views/{}-detail/index.html"]'.format(type))
def switch_to_active_view(self):
Wait(self.marionette).until(expected.element_displayed(*self._active_view_locator))
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
def wait_sublist_view_draw(self):
self.switch_to_active_view()
element = self.marionette.find_element(*self._list_locator)
Wait(self.marionette).until(lambda m: element.rect['x'] == 0 and element.is_displayed())
self.apps.switch_to_displayed_app()
def tap_first_song(self):
self.switch_to_active_view()
song = Wait(self.marionette).until(
expected.element_present(*self._first_song_locator))
song.tap()
self.apps.switch_to_displayed_app()
return PlayerView(self.marionette)
class AlbumSublistView(SublistView):
def __init__(self, marionette):
Base.__init__(self, marionette)
self._set_active_view('album')
self.wait_sublist_view_draw()
class ArtistSublistView(SublistView):
def __init__(self, marionette):
Base.__init__(self, marionette)
self._set_active_view('artist')
self.wait_sublist_view_draw()

View file

@ -0,0 +1,29 @@
# 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 marionette_driver import expected, By, Wait
from gaiatest.apps.base import Base
from gaiatest.apps.music.regions.player_view import PlayerView
class TileView(Base):
_active_view_locator = (By.CSS_SELECTOR, 'iframe.active[src*="/views/home/index.html"]')
_tile_group_locator = (By.ID, 'tiles')
def __init__(self, marionette):
Base.__init__(self, marionette)
# there are two type of tiles - main and sub. There should be at least one main tile
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
Wait(self.marionette).until(expected.element_displayed(*self._tile_group_locator))
self.apps.switch_to_displayed_app()
def tap_song(self, filename):
self.marionette.switch_to_frame(self.marionette.find_element(*self._active_view_locator))
_pick_tile_locator = (By.CSS_SELECTOR, '.tile[data-file-path$="{}"]'.format(filename))
self.marionette.find_element(*_pick_tile_locator).tap()
self.apps.switch_to_displayed_app()
return PlayerView(self.marionette)