Skip to content

Commit

Permalink
added service worker registration to HTML files
Browse files Browse the repository at this point in the history
 fixed typo in API function name
 modified schedule data in generateTable.js
 added GitHub Actions to generate screenshots for manifest.json
 Updated docker GitHub Actions workflow to wait for image generation action to complete
  • Loading branch information
Mr-Comand committed Oct 3, 2024
1 parent 509bcee commit 647fa3d
Showing 10 changed files with 298 additions and 46 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -7,8 +7,37 @@ on:
workflow_dispatch: # Allows manual triggering

jobs:
wait_for_other_action:
runs-on: ubuntu-latest
steps:
- name: Wait for Other Action to Complete
id: check_status
run: |
# Set the necessary variables
WORKFLOW_NAME="Run Headless Browser Tests"
REPO="${{ github.repository }}" # Automatically get the repository name
BRANCH="${{ github.ref }}" # Get the ref, which includes refs/heads/main
# Loop until the workflow is complete
while true; do
# Query the GitHub API for the workflow run status
STATUS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/$REPO/actions/workflows/${WORKFLOW_NAME}/runs?branch=${BRANCH}&per_page=1" | \
jq -r '.workflow_runs[0].status')
# Check if the status is completed
if [[ "$STATUS" == "completed" ]]; then
echo "Other action is complete."
break
fi
echo "Waiting for other action to complete..."
sleep 10 # Wait for 10 seconds before checking again
done
build:
runs-on: ubuntu-latest
needs: wait_for_other_action # Ensure this job waits for the previous job to finish

steps:
- name: Checkout code
51 changes: 51 additions & 0 deletions .github/workflows/screenshots.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Run Headless Browser Tests

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest

services:
chrome:
image: selenium/standalone-chrome
options: >-
--shm-size 2g
ports:
- 4444:4444

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8' # Specify your desired Python version

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r /devtools/screenshotsrequirements.txt
- name: Start web server
run: |
python -m http.server 5500 & # Start the HTTP server in the background
- name: Wait for server to start
run: sleep 5 # Wait for a few seconds to ensure the server is up
- name: Run tests
run: |
cd ./devtools/screenshots
python main.py
- name: Add and commit screenshots
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add public/screenshots/*
git add manifest.json
git commit -m "Add screenshots from headless browser tests" || echo "No changes to commit"
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use the GitHub token for authentication
137 changes: 137 additions & 0 deletions devtools/screenshots/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import time
import os
import json
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from PIL import Image
screenshots_dir = '../../public/screenshots'
manifest_path = '../../manifest.json'
screenshots_uri = '/public/screenshots/'
# List of websites with optional interactions
websites = [
{
"url": "https://localhost:5500/login.html",
"name": "login",
},
{
"url": "https://localhost:5500/onboarding.html",
"name": "getting-started",
},
{
"url": "https://localhost:5500/",
"name": "example",
},
{
"url": "https://localhost:5500/",
"name": "example2",
"interactions": lambda driver: interact_example(driver)
}
# Add more websites with specific interactions here
]

def interact_example(driver):
"""Example interaction: Click a button, wait for element."""
try:
time.sleep(1)
driver.find_element(By.ID, "m1").click()
time.sleep(1)
except Exception as e:
print(f"Interaction failed: {e}")


def interact_example2(driver):
"""Example interaction: Scroll to bottom."""
try:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2) # Wait for scroll to complete
except Exception as e:
print(f"Interaction failed: {e}")



manifest = {"screenshots": []}

# Ensure the screenshots directory exists
if not os.path.exists(screenshots_dir):
os.makedirs(screenshots_dir)

# Load existing manifest.json if it exists
if os.path.exists(manifest_path):
with open(manifest_path, 'r') as f:
manifest = json.load(f)

# Set up Chrome options for Selenium
chrome_options = Options()
# chrome_options.add_argument('--headless') # Run in headless mode
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--window-size=1280x800')

# Initialize WebDriver
driver = webdriver.Chrome(options=chrome_options)
if not screenshots_uri.endswith('/'):
screenshots_uri += '/'
if not screenshots_dir.endswith('/'):
screenshots_dir += '/'

def capture_screenshot(site, viewport_size, form_factor):
"""Capture screenshot for the given viewport size."""
driver.set_window_rect(0,0,*viewport_size)
screenshot_path = f"{screenshots_dir}{site['name']}-{form_factor}.png"
driver.save_screenshot(screenshot_path)

# Use PIL to open the screenshot and get its size
with Image.open(screenshot_path) as img:
actual_width, actual_height = img.size
# Check the aspect ratio condition
if form_factor == "wide" and actual_width > 2.3 * actual_height:
print(f"Error: Screenshot width ({actual_width}px) exceeds 2.3 times the height ({actual_height}px).")
print(f"Captured screenshot for {site['name']} - {form_factor}: {actual_width}x{actual_height}") # Print actual sizes

# Check if the screenshot src already exists in the manifest
existing_entry = next((entry for entry in manifest["screenshots"] if entry["src"] == f"{screenshots_uri}{site['name']}-{form_factor}.png"), None)

if existing_entry:
# Update the existing entry
existing_entry["sizes"] = f"{actual_width}x{actual_height}" # Update sizes
existing_entry["type"] = "image/png" # Ensure type is set
existing_entry["form_factor"] = form_factor # Update form factor
else:
# Add a new entry to the manifest
manifest["screenshots"].append({
"src": f"{screenshots_uri}{site['name']}-{form_factor}.png",
"sizes": f"{actual_width}x{actual_height}", # Use actual dimensions
"type": "image/png",
"form_factor": form_factor
})

for site in websites:
try:
# Visit the website
driver.get(site["url"])

# Perform any interactions defined for this website
if "interactions" in site and callable(site["interactions"]):
site["interactions"](driver)

# Capture wide (desktop) screenshot
capture_screenshot(site, (1000, 654), "wide") # Example width

# Capture narrow (mobile) screenshot
capture_screenshot(site, (469, 505), "narrow") # Maintain existing size or adjust slightly if necessary



print(f"Captured screenshots for {site['url']}")

except Exception as e:
print(f"Failed to capture {site['url']}: {e}")

# Close the WebDriver
driver.quit()

# Write the updated manifest.json file back
with open(manifest_path, 'w') as f:
json.dump(manifest, f, indent=2)

print("Manifest updated at ../../manifest.json.")
2 changes: 2 additions & 0 deletions devtools/screenshots/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
selenium>=4.0.0
Pillow>=9.0.0
9 changes: 9 additions & 0 deletions login.html
Original file line number Diff line number Diff line change
@@ -5,6 +5,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login | TMF Timetable</title>
<link rel="stylesheet" href="/styles/login.css">
<link rel="manifest" href="manifest.json">
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log("Registered!");
}).catch(console.error);
}
</script>
</head>
<body>
<div class="center-wrapper">
3 changes: 2 additions & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -30,5 +30,6 @@
"theme_color": "#1565c0",
"start_url": "./?utm_source=web_app_manifest",
"display": "fullscreen",
"orientation": "any"
"orientation": "any",
"screenshots": [ ]
}
9 changes: 9 additions & 0 deletions onboarding.html
Original file line number Diff line number Diff line change
@@ -6,6 +6,15 @@
<title>Onboarding | BetterUntis</title>
<link rel="stylesheet" href="/styles/onboarding.css">
<link href="MultiSelect.css" rel="stylesheet" type="text/css">
<link rel="manifest" href="manifest.json">
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log("Registered!");
}).catch(console.error);
}
</script>
</head>
<body>
<div class="center-wrapper">
9 changes: 9 additions & 0 deletions register.html
Original file line number Diff line number Diff line change
@@ -5,6 +5,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register | TMF Timetable</title>
<link rel="stylesheet" href="/styles/register.css">
<link rel="manifest" href="manifest.json">
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(registration => {
console.log("Registered!");
}).catch(console.error);
}
</script>
</head>
<body>
<div class="center-wrapper">
2 changes: 1 addition & 1 deletion src/api/untis.js
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ export async function getAllClasses(accesstoken) {
}
}

async function getAllRoooms(accesstoken) {
async function getAllRooms(accesstoken) {
const url = `http://${apiurl}/untis/rooms`;

try {
93 changes: 49 additions & 44 deletions src/generateTable.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
const scheduleData = [
//mon
{ row: 1, day: 'm', value: 'rev2, Fi, 314', cancelled: '' },
{ row: 2, day: 'm', value: 'rev2, Fi, 314', cancelled: '' },
{ row: 3, day: 'm', value: 'E1, Rs, 323', cancelled: '' },
{ row: 4, day: 'm', value: 'E1, Rs, 323', cancelled: '' },
{ row: 8, day: 'm', value: 'mu1, Hz, 422', cancelled: '' },
{ row: 9, day: 'm', value: 'mu1, Hz, 422', cancelled: '' },
//tue
{ row: 1, day: 't', value: 'D2, Rt, 414', cancelled: '' },
{ row: 2, day: 't', value: 'D2, Rt, 414', cancelled: '' },
{ row: 3, day: 't', value: 'ph1, Hr, 424', cancelled: '' },
{ row: 4, day: 't', value: 'ph1, Hr, 424', cancelled: '' },
{ row: 5, day: 't', value: 'f1, Kth, 422', cancelled: '' },
{ row: 6, day: 't', value: 'f1, Kth, 422', cancelled: '' },
{ row: 10, day: 't', value: 's3, Er, SHA', cancelled: 'True' },
{ row: 11, day: 't', value: 's3, Er, SHA', cancelled: 'True' },
//wed
{ row: 2, day: 'w', value: 'm2, Pl, 321', cancelled: '' },
{ row: 3, day: 'w', value: 'geo4, Lk, 414', cancelled: 'True' },
{ row: 4, day: 'w', value: 'geo4, Lk, 414', cancelled: 'True' },
{ row: 5, day: 'w', value: 'G1, An, 324', cancelled: '' },
{ row: 6, day: 'w', value: 'G1, An, 324', cancelled: '' },
{ row: 7, day: 'w', value: 'G1, An, 324', cancelled: '' },
{ row: 9, day: 'w', value: 'E1, Rs, 323', cancelled: '' },
{ row: 10, day: 'w', value: 'E1, Rs, 323', cancelled: '' },
//thur
{ row: 1, day: 'th', value: 'G1, An, 321', cancelled: '' },
{ row: 2, day: 'th', value: 'G1, An, 321', cancelled: '' },
{ row: 3, day: 'th', value: 'D2, Rt, 323', cancelled: '' },
{ row: 4, day: 'th', value: 'D2, Rt, 323', cancelled: '' },
{ row: 5, day: 'th', value: 'f1, Kth, 113', cancelled: '' },
{ row: 8, day: 'th', value: 'inf, Hr, 423', cancelled: '' },
{ row: 9, day: 'th', value: 'inf, Hr, 423', cancelled: '' },
{ row: 10, day: 'th', value: 'ph1, Hr, 424', cancelled: '' },
{ row: 11, day: 'th', value: 'ph1, Hr, 424', cancelled: '' },
{ row: 12, day: 'th', value: 'TEST SUBJECT', cancelled: '' },
//fri
{ row: 3, day: 'f', value: 'm2, Pl, 121', cancelled: '' },
{ row: 4, day: 'f', value: 'm2, Pl, 121', cancelled: '' },
{ row: 5, day: 'f', value: 'E1, Rs, 322', cancelled: '' },
{ row: 6, day: 'f', value: 'D2, Rt, 312', cancelled: '' },
{ row: 8, day: 'f', value: 'lth, Sch, 410', cancelled: '' },
{ row: 9, day: 'f', value: 'lth, Sch, 410', cancelled: '' },

// Monday
{ row: 1, day: 'm', value: 'Math, Mr. Smith, 101', cancelled: '' },
{ row: 2, day: 'm', value: 'Math, Mr. Smith, 101', cancelled: '' },
{ row: 3, day: 'm', value: 'English, Ms. Johnson, 102', cancelled: '' },
{ row: 4, day: 'm', value: 'English, Ms. Johnson, 102', cancelled: '' },
{ row: 5, day: 'm', value: 'History, Mr. Clark, 103', cancelled: 'True' },
{ row: 8, day: 'm', value: 'Biology, Ms. Lee, 104', cancelled: '' },
{ row: 9, day: 'm', value: 'Biology, Ms. Lee, 104', cancelled: '' },

// Tuesday
{ row: 1, day: 't', value: 'Physics, Mr. Green, 201', cancelled: '' },
{ row: 2, day: 't', value: 'Physics, Mr. Green, 201', cancelled: '' },
{ row: 3, day: 't', value: 'Chemistry, Ms. White, 202', cancelled: '' },
{ row: 4, day: 't', value: 'Chemistry, Ms. White, 202', cancelled: '' },
{ row: 5, day: 't', value: 'Art, Mr. Blue, 203', cancelled: 'True' },
{ row: 6, day: 't', value: 'Art, Mr. Blue, 203', cancelled: 'True' },
{ row: 9, day: 't', value: 'Computer Science, Mr. Yellow, 302', cancelled: '' },
{ row: 10, day: 't', value: 'Geography, Ms. Black, 204', cancelled: '' },
{ row: 11, day: 't', value: 'Geography, Ms. Black, 204', cancelled: '' },

// Wednesday
{ row: 1, day: 'w', value: 'Music, Mr. Grey, 301', cancelled: '' },
{ row: 2, day: 'w', value: 'Music, Mr. Grey, 301', cancelled: '' },
{ row: 3, day: 'w', value: 'Sports, Ms. Brown, Gym', cancelled: '' },
{ row: 4, day: 'w', value: 'Sports, Ms. Brown, Gym', cancelled: '' },
{ row: 5, day: 'w', value: 'Computer Science, Mr. Yellow, 302', cancelled: '' },
{ row: 6, day: 'w', value: 'Computer Science, Mr. Yellow, 302', cancelled: '' },


// Thursday
{ row: 1, day: 'th', value: 'Math, Mr. Silver, 401', cancelled: '' },
{ row: 2, day: 'th', value: 'Math, Mr. Silver, 401', cancelled: '' },
{ row: 3, day: 'th', value: 'History, Mr. Brown, 402', cancelled: '' },
{ row: 4, day: 'th', value: 'History, Mr. Brown, 402', cancelled: '' },
{ row: 5, day: 'th', value: 'Chemistry, Ms. Green, 403', cancelled: '' },

{ row: 8, day: 'th', value: 'Literature, Ms. Purple, 303', cancelled: '' },
{ row: 9, day: 'th', value: 'Literature, Ms. Purple, 303', cancelled: '' },
{ row: 10, day: 'th', value: 'Literature, Ms. Purple, 303', cancelled: '' },

// Friday
{ row: 1, day: 'f', value: 'Math, Ms. Red, 501', cancelled: '' },
{ row: 2, day: 'f', value: 'Math, Ms. Red, 501', cancelled: '' },
{ row: 3, day: 'f', value: 'History, Ms. Blue, 502', cancelled: '' },
{ row: 4, day: 'f', value: 'History, Ms. Blue, 502', cancelled: '' },
{ row: 5, day: 'f', value: 'English, Mr. Yellow, 503', cancelled: '' },
{ row: 6, day: 'f', value: 'English, Mr. Yellow, 503', cancelled: '' },

];


function generateSchedule(data) {
const scheduleBody = document.getElementById("scheduleBody");
// find highest row number in the data (--> latest session) to know how many rows to create

0 comments on commit 647fa3d

Please sign in to comment.