Skip to content

Commit

Permalink
✅ Add Mobile Live status test written by elreydetoda
Browse files Browse the repository at this point in the history
  • Loading branch information
CGBassPlayer committed Feb 6, 2023
1 parent b244af0 commit d36770f
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 25 deletions.
134 changes: 111 additions & 23 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,96 @@
from pathlib import Path
from typing import Generator
from typing import Generator, Callable
from pytest import fixture
from _pytest.fixtures import SubRequest
from pytest_base_url.plugin import base_url
from playwright.sync_api import Playwright, APIRequestContext
from playwright.sync_api import Playwright, APIRequestContext, Route, Page, Browser


@fixture
def get_test_dir() -> Path:
return Path(__file__).parent.absolute()


@fixture
def screenshot_dir() -> Path:
return Path('screenshots/')


@fixture(
# doing session so it doesn't have to be re-created for each usage
scope="session",
# some example phone sizes to use
params=[
"iPhone 13",
"Pixel 5",
"Galaxy S9+",
]
)
def mobile_device_tuple(
# how to access the params
request: SubRequest,
# browser object given by playwright built-in fixture
browser: Browser,
# Playwright object given by playwright built-in fixture
playwright: Playwright,
# from the pytest-base-url plugin Playwright installs (automatically)
# so we're not having to hard-code the URL
base_url: base_url,
) -> tuple[Page, str]:
"""
identified all possible device types by running the following in a python interpreter + shell commands
# python interpreter
with sync_playwright() as playwright:
Path('./devices.json').write_text(j_dumps(playwright.devices, indent=2))
# shell cmd
jq '. | keys' devices.json| less
also should be able to view them here:
https://github.com/microsoft/playwright/blob/v1.25.2/packages/playwright-core/src/server/deviceDescriptorsSource.json
"""

# based on here: https://playwright.dev/python/docs/emulation#devices
context = browser.new_context(
base_url=base_url,
# based on this info: https://playwright.dev/python/docs/emulation#devices
**playwright.devices[request.param]
)
try:
# essentially a "return", but used with generators
yield context.new_page(), request.param
except Exception as e:
raise e
finally:
# supposed to get rid of cookies/other stored info after generator is done
# https://playwright.dev/python/docs/api/class-apirequestcontext#api-request-context-dispose
# https://github.com/microsoft/playwright.dev/blob/d9b4a2f3bd0510ea89c87ed230b8241eb33b6688/python/docs/api-testing.mdx#writing-api-test
context.close()


@fixture(scope="session")
def api_request_context(
playwright: Playwright, # base playwright context/object
# From the pytest-base-url plugin Playwright installs (automatically) so we're not having to hard-code the URL
base_url: base_url,
) -> Generator[APIRequestContext, None, None]: # Generator is returned based on Playwright docs
"""
https://playwright.dev/python/docs/api-testing#configure
used for doing similar requests to API calls
"""
# creates APIRequestContext to allow requests to be made
# using the base_url variable (from the plugin) to define
# the base_url which'll allow requests relative to that base_url
request_context = playwright.request.new_context(base_url=base_url)
# essentially a "return", but used with generators
yield request_context
# supposed to get rid of coookies/other stored info after generator is done
# https://playwright.dev/python/docs/api/class-apirequestcontext#api-request-context-dispose
# https://github.com/microsoft/playwright.dev/blob/d9b4a2f3bd0510ea89c87ed230b8241eb33b6688/python/docs/api-testing.mdx#writing-api-test
request_context.dispose()


@fixture
def expected_rss_feeds() -> list[dict[str, str, ]]:
return [
Expand Down Expand Up @@ -81,24 +162,31 @@ def expect_nav_items() -> list[dict[str, str]]:
]


# https://playwright.dev/python/docs/api-testing#configure
# used for doing similar requests to API calls
@fixture(scope="session")
def api_request_context(
# base playwright context/object
playwright: Playwright,
# from the pytest-base-url plugin Playwright installs (automatically)
# so we're not having to hard-code the URL
base_url: base_url,
# Generator is returned based on Playwright docs
) -> Generator[APIRequestContext, None, None]:
# creates APIRequestContext to allow requests to be made
# using the base_url variable (from the plugin) to define
# the base_url which'll allow requests relative to that base_url
request_context = playwright.request.new_context(base_url=base_url)
# essentially a "return", but used with generators
yield request_context
# supposed to get rid of coookies/other stored info after generator is done
# https://playwright.dev/python/docs/api/class-apirequestcontext#api-request-context-dispose
# https://github.com/microsoft/playwright.dev/blob/d9b4a2f3bd0510ea89c87ed230b8241eb33b6688/python/docs/api-testing.mdx#writing-api-test
request_context.dispose()
@fixture
def get_live_event(get_test_dir: Path) -> str:
return Path(get_test_dir / 'fixture_files/jb-live_sample-live-event.json').read_text()


@fixture
def set_live(get_live_event: str) -> tuple[Callable, str]:
return _replace_live_event, get_live_event
# return replace_live_event


@staticmethod
def _replace_live_event(page: Page, live_event: str) -> None:
def handle_route(route: Route) -> None:
# fetch original response
response = page.request.fetch(route.request)

# setting live event
route.fulfill(
# Pass all fields from the response
response=response,
# override body
body=live_event.strip()
)
page.route(
"https://jupiter.tube/api/v1/video-channels/live/videos?isLive=true&skipCount=false&count=1&sort=-createdAt",
handle_route
)
1 change: 0 additions & 1 deletion test/e2e/test_contact.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from playwright.sync_api import Page, FrameLocator, Locator



@fixture(autouse=True)
def setup(page: Page):
"""
Expand Down
1 change: 0 additions & 1 deletion test/e2e/test_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ def test_rss_feeds(page: Page, expected_rss_feeds: List[Dict[str, str]]):
expect(element).to_contain_text(rss_feed['title'])


@mark.dev
def test_dropdowns(page: Page, expected_dropdown_items: Dict[str, List[Dict[str, str]]]):
"""
Tests dropdowns to make sure the dropdown items have links, and all items specified in conftest are present
Expand Down
92 changes: 92 additions & 0 deletions test/e2e/test_live.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from pathlib import Path
from typing import Tuple, Callable
from playwright.sync_api import Page, expect, Locator, FrameLocator


def test_live_indicator(
page: Page,
set_live: Tuple[Callable, str]
):
# explicitly defining tuple objects for clarity
replace_live_event: Callable = set_live[0]
live_event: str = set_live[1]

# intercepting reponses for live event, and make live
replace_live_event(page, live_event)

# go to the live page
page.goto("/live")

# validate live button is red
expect(page.locator("#mainnavigation.is-live").locator("#livebutton")).to_have_css(
name="background-color",
value="rgb(255, 0, 0)", # red
)

# waiting for peertube iframe to load
jbtube_video: FrameLocator = page.frame_locator("#liveStream")
video_player_peertube_icon: Locator = jbtube_video.locator(".peertube-dock-avatar")
expect(video_player_peertube_icon).to_be_visible()

page.evaluate("window.scrollTo(0, 0)")


def test_mobile_live_indicator(
mobile_device_tuple: Tuple[Page, str],
set_live: Tuple[Callable, str],
screenshot_dir: Path,
):
# explicitly defining tuple objects for clarity
replace_live_event: Callable = set_live[0]
live_event: str = set_live[1]

# set mobile page to variable
mobile_device = mobile_device_tuple[0]

# intercepting reponses for live event, and make live
replace_live_event(mobile_device, live_event)

mobile_device.goto("/live")

navbar: Locator = mobile_device.locator("#mainnavigation.is-live",).locator(
".navbar-burger",
)

# wait for navbar to be visible
expect(navbar).to_be_visible()

# check if live indicator is red
assert (
navbar.evaluate(
# integrated docs for python evaluate function:
# https://github.com/microsoft/playwright/blob/a30aac56687598c373c51255308ef5833de0c9bb/docs/src/api/class-jshandle.md?plain=1#L77-L80
# use evaluate function in python: https://playwright.dev/python/docs/api/class-page#page-evaluate
# use getComputerStyle w/playwright: https://stackoverflow.com/a/71433333
"element => window.getComputedStyle(element, ':before').backgroundColor"
)
== "rgb(255, 0, 0)"
)

# waiting for peertube iframe to load
jbtube_video: FrameLocator = mobile_device.frame_locator("#liveStream")
video_player_peertube_icon: Locator = jbtube_video.locator(".peertube-dock-avatar")
expect(video_player_peertube_icon).to_be_visible()

mobile_device.evaluate("window.scrollTo(0, 0)")

# click navbar to expand
navbar.click()

# repeat test_live_indicator for mobile device
expect(
mobile_device.locator("#mainnavigation.is-live",).locator(
"#livebutton",
),
).to_have_css(
name="background-color",
value="rgb(255, 0, 0)", # red
)

mobile_device.locator("#mainnavigation").locator(
".navbar-menu.is-active"
).screenshot(path=f"{screenshot_dir}/live-mobile_navbar.png")
98 changes: 98 additions & 0 deletions test/fixture_files/jb-live_sample-live-event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"total": 1,
"data": [
{
"id": 50,
"uuid": "55b2e9d1-ccf3-4914-9f3f-c5d8a59bd4c1",
"shortUUID": "bzMpxgG2rDKn9C99GSab92",
"url": "https://jupiter.tube/videos/watch/55b2e9d1-ccf3-4914-9f3f-c5d8a59bd4c1",
"name": "LINUX Unplugged 471 - We Broke Our Server",
"category": {
"id": 15,
"label": "Science & Technology"
},
"licence": {
"id": 5,
"label": "Attribution - Non Commercial - Share Alike"
},
"language": {
"id": "en",
"label": "English"
},
"privacy": {
"id": 1,
"label": "Public"
},
"nsfw": false,
"description": "We broke our server, so lets see if we can fix it live before the show is over!",
"isLocal": true,
"duration": 0,
"views": 0,
"viewers": 19,
"likes": 0,
"dislikes": 0,
"thumbnailPath": "/static/thumbnails/b610e5f5-bbb5-4ee1-ac24-421c50f0daf5.jpg",
"previewPath": "/lazy-static/previews/fcd582d8-68c5-4f00-8a4a-0a8ffde1a4a5.jpg",
"embedPath": "/videos/embed/55b2e9d1-ccf3-4914-9f3f-c5d8a59bd4c1",
"createdAt": "2022-08-14T16:26:27.938Z",
"updatedAt": "2022-08-14T18:53:15.544Z",
"publishedAt": "2022-08-14T18:53:15.543Z",
"originallyPublishedAt": null,
"isLive": true,
"account": {
"id": 3,
"displayName": "JBLive Stream",
"name": "jblive",
"url": "https://jupiter.tube/accounts/jblive",
"host": "jupiter.tube",
"avatars": [
{
"width": 48,
"path": "/lazy-static/avatars/e4d17e7f-a144-4a4a-b5d8-b297b06b727f.png",
"createdAt": "2022-06-07T23:43:56.565Z",
"updatedAt": "2022-06-07T23:43:56.565Z"
},
{
"width": 120,
"path": "/lazy-static/avatars/1340f3e9-d0a7-4bc4-bcbd-a8c865eaf1b8.png",
"createdAt": "2022-05-30T20:36:19.005Z",
"updatedAt": "2022-05-30T20:36:19.005Z"
}
],
"avatar": {
"width": 48,
"path": "/lazy-static/avatars/e4d17e7f-a144-4a4a-b5d8-b297b06b727f.png",
"createdAt": "2022-06-07T23:43:56.565Z",
"updatedAt": "2022-06-07T23:43:56.565Z"
}
},
"channel": {
"id": 2,
"name": "live",
"displayName": "live",
"url": "https://jupiter.tube/video-channels/live",
"host": "jupiter.tube",
"avatars": [
{
"width": 48,
"path": "/lazy-static/avatars/8acfd2a2-ab4e-48aa-990c-3156a2765d2e.png",
"createdAt": "2022-06-07T23:43:56.607Z",
"updatedAt": "2022-06-07T23:43:56.607Z"
},
{
"width": 120,
"path": "/lazy-static/avatars/e9bcfdb7-90a2-479c-b1da-1ab0e5fc9442.png",
"createdAt": "2022-05-30T20:38:33.632Z",
"updatedAt": "2022-05-30T20:38:33.632Z"
}
],
"avatar": {
"width": 48,
"path": "/lazy-static/avatars/8acfd2a2-ab4e-48aa-990c-3156a2765d2e.png",
"createdAt": "2022-06-07T23:43:56.607Z",
"updatedAt": "2022-06-07T23:43:56.607Z"
}
}
}
]
}

0 comments on commit d36770f

Please sign in to comment.