Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/live-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Run live provider tests

on:
pull_request:
branches: [ "dev" ]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: live-tests-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
run-live-tests:
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- uses: actions/checkout@v4
- name: Install uv and Python
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
python-version: "3.13"
enable-cache: true
- name: Install dependencies
run: uv sync --locked
- name: Test live provider contracts
run: uv run pytest -m live live_tests/
44 changes: 44 additions & 0 deletions live_tests/test_academic_providers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import pytest

from pittapi.cal import CalendarClient, Event
from pittapi.course import CourseClient
from pittapi.textbook import TextbookClient

pytestmark = pytest.mark.live


@pytest.mark.parametrize(
"method_name",
[
"get_academic_calendar",
"get_grades_calendar",
"get_enrollment_calendar",
"get_course_calendar",
"get_graduation_calendar",
],
)
def test_calendar_feed(method_name):
with CalendarClient() as calendar:
events = getattr(calendar, method_name)()

assert isinstance(events, tuple)
assert all(isinstance(event, Event) for event in events)


def test_course_catalog():
with CourseClient() as courses:
subject = courses.get_subject_courses("CS")

assert subject.subject_code == "CS"
assert subject.courses
assert all(course.course_id for course in subject.courses)


def test_textbook_terms_and_subjects():
with TextbookClient() as textbooks:
terms = textbooks.get_terms()
term = next(term for term in terms if term.inquiry_enabled)
textbooks.select_term(term)
textbooks.initialize_subjects()

assert textbooks.subject_ids
63 changes: 63 additions & 0 deletions live_tests/test_campus_providers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import pytest
import requests

from pittapi.dining import DiningClient
from pittapi.gym import GymClient
from pittapi.lab import LabClient
from pittapi.laundry import LaundryClient
from pittapi.shuttle import ShuttleClient

pytestmark = pytest.mark.live


def test_dining_locations():
try:
with DiningClient() as dining:
locations = dining.get_locations()
except requests.HTTPError as error:
if error.response is not None and error.response.status_code == 403:
pytest.xfail("DineOnCampus blocks requests from some CI environments")
raise

assert locations
assert all(location.id and location.name for location in locations)


def test_gym_occupancy():
with GymClient() as gyms:
occupancy = gyms.get_all_gyms_info()

assert occupancy
assert all(gym.location_id and gym.facility_id for gym in occupancy)
assert all(gym.current_count >= 0 and gym.total_capacity >= 0 for gym in occupancy)


def test_lab_discovery_and_status():
with LabClient() as labs:
locations = labs.get_locations()
status = labs.get_status(locations[0])

counted_computers = (
status.available_computers + status.off_computers + status.in_use_computers + status.out_of_service_computers
)
assert locations
assert status.total_computers == counted_computers


def test_laundry_discovery_and_machines():
with LaundryClient() as laundry:
locations = laundry.get_locations()
machines = laundry.get_machine_statuses(locations[0])

assert locations
assert isinstance(machines, tuple)


def test_shuttle_configuration_and_routes():
with ShuttleClient() as shuttle:
configuration = shuttle.get_configuration()
routes = shuttle.get_routes(configuration)

assert configuration.api_key
assert routes
assert all(route.route_id for route in routes)
36 changes: 36 additions & 0 deletions live_tests/test_content_providers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest

from pittapi.library import LibraryClient
from pittapi.news import NewsClient
from pittapi.people import PeopleClient

pytestmark = pytest.mark.live


def test_library_catalog_and_hillman_reservations():
with LibraryClient() as library:
documents = library.get_documents("computer science")
reservation_total = library.hillman_total_reserved()

assert documents.num_results > 0
assert documents.documents
assert reservation_total >= 0


def test_pittwire_topics_and_articles():
with NewsClient() as news:
topics = news.get_topics()
articles = news.get_articles_by_topic(topics[0], max_num_results=1)

assert topics
assert articles
assert articles[0].url.startswith("https://www.pittwire.pitt.edu/")


def test_people_directory_service_account():
with PeopleClient() as people:
matches = people.get_person("Technology Help Desk")

assert matches
assert matches[0].name == "Help Desk, Technology"
assert any(field.name == "Email" for field in matches[0].fields)
23 changes: 23 additions & 0 deletions live_tests/test_status_and_sports_providers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pytest

from pittapi.sports import FOOTBALL_URL, MENS_BASKETBALL_URL, SportsClient
from pittapi.status import StatusClient

pytestmark = pytest.mark.live


@pytest.mark.parametrize("url", [FOOTBALL_URL, MENS_BASKETBALL_URL])
def test_espn_team_feed(url):
with SportsClient() as sports:
data = sports.get_team_data(url)

assert data["team"]["id"]
assert data["team"]["displayName"]


def test_pitt_service_status():
with StatusClient() as status:
summary = status.get_status()

assert summary.components
assert all(component.name and component.status for component in summary.components)
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ dev = [
line-length = 127
target-version = ["py313"]

[tool.pytest.ini_options]
markers = [
"live: makes requests to live provider services",
]

[tool.setuptools.packages.find]
exclude = ["docs*", "tests*"]
namespaces = false
Loading