mirror of
https://github.com/wizarrrr/wizarr.git
synced 2025-12-23 23:59:23 -05:00
fix: resolve circular import issue in User model and update exception handling in server checks
test: update invitation page assertion to reflect new account creation wording
This commit is contained in:
@@ -293,7 +293,8 @@ class User(db.Model, UserMixin):
|
||||
# Extract library names
|
||||
if details.library_access is None:
|
||||
# Full access - get all server libraries
|
||||
from app.models import Library
|
||||
# Import Library here to avoid circular import
|
||||
from app.models import Library # type: ignore
|
||||
|
||||
if self.server_id:
|
||||
all_libs = Library.query.filter_by(
|
||||
|
||||
@@ -302,11 +302,11 @@ def check_drop(url: str, token: str) -> tuple[bool, str]:
|
||||
response.raise_for_status()
|
||||
return True, ""
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
except req_exc.ConnectionError:
|
||||
return False, _("Could not connect to Drop server.")
|
||||
except requests.exceptions.Timeout:
|
||||
except req_exc.Timeout:
|
||||
return False, _("Connection to Drop server timed out.")
|
||||
except requests.exceptions.HTTPError as e:
|
||||
except req_exc.HTTPError as e:
|
||||
if e.response.status_code == 404:
|
||||
return False, _("Drop API not found. Check the server URL.")
|
||||
return False, f"Drop API error: {e.response.status_code}"
|
||||
|
||||
@@ -123,7 +123,16 @@ class TestInvitationUserJourney:
|
||||
# Verify invitation page loads
|
||||
expect(page.locator("h1").first).to_contain_text("been invited")
|
||||
|
||||
# Check that form is present
|
||||
# Click "Accept Invitation" button to show the form
|
||||
page.click("#accept-invite-btn")
|
||||
|
||||
# Wait for form fields to become visible (they animate in sequentially)
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
# Check that form is present after clicking Accept Invitation
|
||||
expect(page.locator("form")).to_be_visible()
|
||||
expect(page.locator("input[name='username']")).to_be_visible()
|
||||
expect(page.locator("input[name='password']")).to_be_visible()
|
||||
@@ -163,6 +172,11 @@ class TestInvitationUserJourney:
|
||||
# Navigate to invitation page
|
||||
page.goto(f"{live_server.url()}{invitation_setup['invitation_url']}")
|
||||
|
||||
# Click "Accept Invitation" button to show the form
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form to fully load and be interactive
|
||||
page.wait_for_timeout(3000)
|
||||
|
||||
# Test empty form submission
|
||||
page.click("button[type='submit']")
|
||||
|
||||
@@ -182,10 +196,9 @@ class TestInvitationUserJourney:
|
||||
page.wait_for_load_state("networkidle")
|
||||
expect(page.locator("body")).to_contain_text("been invited")
|
||||
|
||||
# Verify form elements are still visible (validation prevents progression)
|
||||
expect(page.locator("input[name='username']")).to_be_visible()
|
||||
expect(page.locator("input[name='password']")).to_be_visible()
|
||||
expect(page.locator("input[name='confirm_password']")).to_be_visible()
|
||||
# Verify form elements are still usable (validation prevents progression)
|
||||
# Test that we can still interact with the form fields
|
||||
page.fill("input[name='username']", "testuser")
|
||||
expect(page.locator("input[name='email']")).to_be_visible()
|
||||
|
||||
def test_expired_invitation(self, page: Page, live_server, app):
|
||||
@@ -254,6 +267,14 @@ class TestInvitationUserJourney:
|
||||
# Navigate to invitation page
|
||||
page.goto(f"{live_server.url()}{invitation_setup['invitation_url']}")
|
||||
|
||||
# Click "Accept Invitation" button to show the form
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible (they animate in sequentially)
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
# Fill and submit form
|
||||
page.fill("input[name='username']", "erroruser")
|
||||
page.fill("input[name='password']", "testpass123")
|
||||
@@ -346,8 +367,15 @@ class TestMultiServerInvitationFlow:
|
||||
# Should show invitation content (may not show specific server names)
|
||||
expect(page.locator("body")).to_contain_text("been invited")
|
||||
|
||||
# The form should already show the username/password fields directly
|
||||
# No need to click "Join Server" - the registration form is already there
|
||||
# Click "Accept Invitation" button to show the form
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible (they animate in sequentially)
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
# Wait for form to be visible
|
||||
page.wait_for_selector("input[name='username']", timeout=5000)
|
||||
|
||||
# Fill and submit the user registration form
|
||||
@@ -439,7 +467,15 @@ class TestMultiServerInvitationFlow:
|
||||
# Wait for page to load
|
||||
page.wait_for_load_state("networkidle")
|
||||
|
||||
# Should show invitation content and registration form directly
|
||||
# Click "Accept Invitation" button to show the form
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible (they animate in sequentially)
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
# Should show invitation content and registration form
|
||||
page.wait_for_selector("input[name='username']", timeout=10000)
|
||||
page.fill("input[name='username']", "partialuser")
|
||||
page.fill("input[name='password']", "testpass123")
|
||||
@@ -465,6 +501,14 @@ class TestInvitationUIComponents:
|
||||
"""Test basic accessibility of invitation form."""
|
||||
page.goto(f"{live_server.url()}{invitation_setup['invitation_url']}")
|
||||
|
||||
# Click "Accept Invitation" button to show the form
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible (they animate in sequentially)
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
|
||||
# Check for form labels
|
||||
expect(
|
||||
page.locator("label[for*='username'], input[name='username'][aria-label]")
|
||||
@@ -491,16 +535,34 @@ class TestInvitationUIComponents:
|
||||
# Test desktop
|
||||
page.set_viewport_size({"width": 1920, "height": 1080})
|
||||
page.goto(f"{live_server.url()}{invitation_setup['invitation_url']}")
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
expect(page.locator("form")).to_be_visible()
|
||||
|
||||
# Test tablet
|
||||
page.set_viewport_size({"width": 768, "height": 1024})
|
||||
page.reload()
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
expect(page.locator("form")).to_be_visible()
|
||||
|
||||
# Test mobile
|
||||
page.set_viewport_size({"width": 375, "height": 667})
|
||||
page.reload()
|
||||
page.click("#accept-invite-btn")
|
||||
# Wait for form fields to become visible
|
||||
page.wait_for_selector(
|
||||
"input[name='username'][style*='opacity: 1'], input[name='username']:not([style*='opacity: 0'])",
|
||||
timeout=10000,
|
||||
)
|
||||
expect(page.locator("form")).to_be_visible()
|
||||
|
||||
# Form should remain usable at all sizes
|
||||
|
||||
@@ -191,7 +191,7 @@ def test_invitation_with_no_server_association_falls_back(client, invitation_no_
|
||||
response_text = response.get_data(as_text=True)
|
||||
# Just verify that the invitation page is working with some server name
|
||||
# The specific server name depends on test execution order
|
||||
assert "Set up Account" in response_text
|
||||
assert "Create Account" in response_text
|
||||
assert "You've been invited to join" in response_text
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user