mirror of
https://github.com/openzim/zimit.git
synced 2025-09-22 03:12:04 -04:00
Automate daily tests of ZIM behavior - Youtube only for now
This commit is contained in:
parent
751e10473a
commit
6d078c4dcf
27
.github/workflows/DailyTests.yaml
vendored
Normal file
27
.github/workflows/DailyTests.yaml
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
name: DailyTests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 4 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
jobs:
|
||||
run-daily-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: build zimit image
|
||||
run: docker build -t local-zimit .
|
||||
|
||||
- name: run crawl of test website
|
||||
run: docker run -v $PWD/output3:/output local-zimit zimit --url https://website.test.openzim.org/ --name tests_eng_test-website --zim-file tests_eng_test-website.zim
|
||||
|
||||
- name: build selenium test image
|
||||
run: docker build -t local-selenium tests-daily
|
||||
|
||||
- name: run integration test suite
|
||||
run: docker run -v $PWD/tests-daily/daily.py:/app/daily.py -v $PWD/output3:/output local-selenium bash -c "cd /app && pytest -h && pytest -v --log-level=INFO --log-format='%(levelname)s - %(message)s' daily.py"
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
|
||||
- Add `--custom-behaviors` argument to support path/HTTP(S) URL custom behaviors to pass to the crawler (#313)
|
||||
- Add daily automated end-to-end tests of a page with Youtube player (#330)
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -39,6 +39,7 @@ test = [
|
||||
dev = [
|
||||
"pre-commit==3.7.1",
|
||||
"debugpy==1.8.1",
|
||||
"selenium==4.23.0", # used in daily tests, convenient for dev purpose (autocompletion)
|
||||
"zimit[scripts]",
|
||||
"zimit[lint]",
|
||||
"zimit[test]",
|
||||
|
75
tests-daily/Dockerfile
Normal file
75
tests-daily/Dockerfile
Normal file
@ -0,0 +1,75 @@
|
||||
# Let's extract kiwix-tools as usual on alpine temporary build container
|
||||
FROM alpine:3.18 as kiwix-serve
|
||||
LABEL org.opencontainers.image.source https://github.com/openzim/kiwix-tools
|
||||
|
||||
# TARGETPLATFORM is injected by docker build
|
||||
ARG TARGETPLATFORM
|
||||
ARG KIWIX_TOOLS_VERSION
|
||||
|
||||
RUN set -e && \
|
||||
# default (no KIWIX_TOOLS_VERSION set) to today's nightly
|
||||
if [ -z "$KIWIX_TOOLS_VERSION" ] ; then KIWIX_TOOLS_VERSION=$(date +"%Y-%m-%d") ; fi && \
|
||||
apk --no-cache add dumb-init curl && \
|
||||
echo "TARGETPLATFORM: $TARGETPLATFORM" && \
|
||||
if [ "$TARGETPLATFORM" = "linux/386" ]; then ARCH="i586"; \
|
||||
# linux/arm64/v8 points to linux/arm64
|
||||
elif [ "$TARGETPLATFORM" = "linux/arm64/v8" \
|
||||
-o "$TARGETPLATFORM" = "linux/arm64" ]; then ARCH="aarch64"; \
|
||||
# linux/arm translates to linux/arm/v7
|
||||
elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then ARCH="armv8"; \
|
||||
elif [ "$TARGETPLATFORM" = "linux/arm/v6" ]; then ARCH="armv6"; \
|
||||
elif [ "$TARGETPLATFORM" = "linux/amd64/v3" \
|
||||
-o "$TARGETPLATFORM" = "linux/amd64/v2" \
|
||||
-o "$TARGETPLATFORM" = "linux/amd64" ]; then ARCH="x86_64"; \
|
||||
# we dont suppot any other arch so let it fail
|
||||
else ARCH="unknown"; fi && \
|
||||
# download requested kiwix-tools version
|
||||
url="http://mirror.download.kiwix.org/nightly/$KIWIX_TOOLS_VERSION/kiwix-tools_linux-$ARCH-$KIWIX_TOOLS_VERSION.tar.gz" && \
|
||||
echo "URL: $url" && \
|
||||
mkdir /kiwix-serve && \
|
||||
curl -k -L $url | tar -xz -C /kiwix-serve --strip-components 1
|
||||
|
||||
# Build real "workload" container
|
||||
FROM python:3.12-slim-bookworm
|
||||
|
||||
# Add kiwix-serve
|
||||
COPY --from=kiwix-serve /kiwix-serve /usr/local/bin
|
||||
|
||||
# Update apt + install dependencies + install Google Chrome dependencies + clean-up apt lists
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -qqy wget xvfb unzip jq && \
|
||||
apt-get install -qqy libxss1 libappindicator1 libgconf-2-4 \
|
||||
fonts-liberation libasound2 libnspr4 libnss3 libx11-xcb1 libxtst6 lsb-release xdg-utils \
|
||||
libgbm1 libnss3 libatk-bridge2.0-0 libgtk-3-0 libx11-xcb1 libxcb-dri3-0 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Fetch the latest version numbers and URLs for Chrome and ChromeDriver
|
||||
RUN wget -q -O /tmp/versions.json https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json
|
||||
|
||||
# Install chrome
|
||||
RUN CHROME_URL=$(jq -r '.channels.Stable.downloads.chrome[] | select(.platform=="linux64") | .url' /tmp/versions.json) && \
|
||||
wget -q --continue -O /tmp/chrome-linux64.zip $CHROME_URL && \
|
||||
unzip /tmp/chrome-linux64.zip -d /opt/chrome
|
||||
|
||||
RUN chmod +x /opt/chrome/chrome-linux64/chrome
|
||||
|
||||
# Install chromedriver
|
||||
RUN CHROMEDRIVER_URL=$(jq -r '.channels.Stable.downloads.chromedriver[] | select(.platform=="linux64") | .url' /tmp/versions.json) && \
|
||||
wget -q --continue -O /tmp/chromedriver-linux64.zip $CHROMEDRIVER_URL && \
|
||||
unzip /tmp/chromedriver-linux64.zip -d /opt/chromedriver && \
|
||||
chmod +x /opt/chromedriver/chromedriver-linux64/chromedriver
|
||||
|
||||
# Set up Chromedriver Environment variables
|
||||
ENV CHROMEDRIVER_DIR /opt/chromedriver
|
||||
ENV PATH $CHROMEDRIVER_DIR:$PATH
|
||||
|
||||
# Clean up
|
||||
RUN rm /tmp/chrome-linux64.zip /tmp/chromedriver-linux64.zip /tmp/versions.json
|
||||
|
||||
# Update pip, install selenium, create work directory
|
||||
RUN \
|
||||
python -m pip install --no-cache-dir -U \
|
||||
pip \
|
||||
selenium==4.23.0 \
|
||||
pytest==8.2.2 \
|
||||
&& mkdir -p /work
|
124
tests-daily/daily.py
Normal file
124
tests-daily/daily.py
Normal file
@ -0,0 +1,124 @@
|
||||
import logging
|
||||
import subprocess
|
||||
from time import sleep
|
||||
|
||||
import pytest
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.chrome.service import Service as ChromeService
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support import expected_conditions
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
KIWIX_SERVE_START_SLEEP = 1
|
||||
|
||||
ZIM_NAME = "tests_eng_test-website"
|
||||
YOUTUBE_VIDEO_PATH = "youtube.fuzzy.replayweb.page/embed/g5skcrNXdDM"
|
||||
|
||||
CHECK_VIDEO_IS_PLAYING_AFTER_SECS = 30
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def chrome_driver():
|
||||
"""Start chrome and setup chrome driver / selenium"""
|
||||
|
||||
logger.info("Starting Chrome")
|
||||
chrome_options = Options()
|
||||
chrome_options.add_argument("--headless")
|
||||
chrome_options.add_argument("--no-sandbox")
|
||||
# Other options of interest:
|
||||
# --disable-dev-shm-usage (not needed anymore with recent chrome versions)
|
||||
# --disable-gpu (important for some versions of Chrome)
|
||||
# --remote-debugging-port=9222 (should you need to remote debug)
|
||||
|
||||
# Set path to Chrome binary
|
||||
chrome_options.binary_location = "/opt/chrome/chrome-linux64/chrome"
|
||||
|
||||
# Set path to ChromeDriver
|
||||
chrome_service = ChromeService(
|
||||
executable_path="/opt/chromedriver/chromedriver-linux64/chromedriver"
|
||||
)
|
||||
|
||||
# Set up driver
|
||||
driver = webdriver.Chrome(service=chrome_service, options=chrome_options)
|
||||
|
||||
yield driver
|
||||
|
||||
# Cleanup
|
||||
logger.info("Quitting Chrome")
|
||||
driver.quit()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def kiwix_serve():
|
||||
"""Start kiwix-serve with given ZIM"""
|
||||
|
||||
logger.info("Starting kiwix-serve")
|
||||
process = subprocess.Popen(
|
||||
[
|
||||
"/usr/bin/env",
|
||||
"/usr/local/bin/kiwix-serve",
|
||||
f"/output/{ZIM_NAME}.zim",
|
||||
]
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"Waiting {KIWIX_SERVE_START_SLEEP} secs to be 'sure' that kiwix-serve is ready"
|
||||
)
|
||||
sleep(KIWIX_SERVE_START_SLEEP)
|
||||
|
||||
if process.poll() is not None:
|
||||
raise Exception("kiwix-serve has terminated too early")
|
||||
|
||||
yield process
|
||||
|
||||
# Cleanup
|
||||
logger.info("Quitting kiwix-serve")
|
||||
process.terminate()
|
||||
|
||||
|
||||
def test_youtube_video(chrome_driver, kiwix_serve): # noqa: ARG001
|
||||
"""Test that youtube video loads, and still plays after a while"""
|
||||
|
||||
chrome_driver.get(f"http://localhost:80/content/{ZIM_NAME}/{YOUTUBE_VIDEO_PATH}")
|
||||
|
||||
if chrome_driver.title == "Content not found":
|
||||
raise Exception("Wrong URL, kiwix-serve said that content is not found")
|
||||
|
||||
button = WebDriverWait(chrome_driver, 1).until(
|
||||
expected_conditions.presence_of_element_located(
|
||||
(By.XPATH, "//button[@title='Play']")
|
||||
)
|
||||
)
|
||||
|
||||
logger.info("Play button found in page")
|
||||
|
||||
button.click()
|
||||
|
||||
video = WebDriverWait(chrome_driver, 1).until(
|
||||
expected_conditions.presence_of_element_located((By.TAG_NAME, "video"))
|
||||
)
|
||||
|
||||
logger.info("Video found in page")
|
||||
|
||||
# arguments[0] is the video tag passed to execute_script
|
||||
if not chrome_driver.execute_script("return arguments[0].paused === false", video):
|
||||
raise Exception("Video is not playing, failed to start probably")
|
||||
|
||||
logger.info("Video is playing")
|
||||
|
||||
logger.info(
|
||||
f"Waiting {CHECK_VIDEO_IS_PLAYING_AFTER_SECS} secs to check video is still "
|
||||
"playing"
|
||||
)
|
||||
sleep(CHECK_VIDEO_IS_PLAYING_AFTER_SECS)
|
||||
|
||||
# arguments[0] is the video tag passed to execute_script
|
||||
if not chrome_driver.execute_script("return arguments[0].paused === false", video):
|
||||
raise Exception(
|
||||
"Video is not playing anymore after "
|
||||
f"{CHECK_VIDEO_IS_PLAYING_AFTER_SECS} secs"
|
||||
)
|
||||
logger.info("Video is still playing")
|
Loading…
x
Reference in New Issue
Block a user