2026-03-09 21:13:35 -04:00
|
|
|
|
from selenium.common.exceptions import NoSuchElementException
|
2026-03-08 01:52:03 -05:00
|
|
|
|
from selenium.webdriver.common.action_chains import ActionChains
|
|
|
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
|
|
|
|
|
|
|
|
from .base import FunctionalTest
|
2026-03-09 21:13:35 -04:00
|
|
|
|
from apps.applets.models import Applet
|
2026-03-08 01:52:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GameboardNavigationTest(FunctionalTest):
|
2026-03-09 21:13:35 -04:00
|
|
|
|
def setUp(self):
|
|
|
|
|
|
super().setUp()
|
|
|
|
|
|
Applet.objects.get_or_create(slug="new-game", defaults={"name": "New Game", "context": "gameboard"})
|
|
|
|
|
|
Applet.objects.get_or_create(slug="my-games", defaults={"name": "My Games", "context": "gameboard"})
|
|
|
|
|
|
Applet.objects.get_or_create(slug="game-kit", defaults={"name": "Game Kit", "context": "gameboard"})
|
|
|
|
|
|
|
2026-03-08 01:52:03 -05:00
|
|
|
|
def test_footer_links_to_gameboard(self):
|
|
|
|
|
|
# 1. Log in, nav to dashboard
|
|
|
|
|
|
self.create_pre_authenticated_session("capman@test.io")
|
|
|
|
|
|
self.browser.get(self.live_server_url)
|
|
|
|
|
|
# 2. Assert footer nav present w. dash- & gameboard tabs
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_footer_nav")
|
|
|
|
|
|
self.browser.find_element(By.CSS_SELECTOR, '#id_footer_nav a[href="/"]')
|
|
|
|
|
|
self.browser.find_element(By.CSS_SELECTOR, '#id_footer_nav a[href="/gameboard/"]')
|
|
|
|
|
|
# 3. Click the gameboard tab
|
|
|
|
|
|
self.browser.find_element(
|
|
|
|
|
|
By.CSS_SELECTOR, '#id_footer_nav a[href="/gameboard/"]'
|
|
|
|
|
|
).click()
|
|
|
|
|
|
# 4. Assert user landed on gameboard
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertRegex(self.browser.current_url, r"/gameboard/$")
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def test_gameboard_shows_game_applets(self):
|
|
|
|
|
|
# 1. Log in, nav directly to gameboard
|
|
|
|
|
|
self.create_pre_authenticated_session("capman@test.io")
|
|
|
|
|
|
self.browser.get(self.live_server_url + "/gameboard/")
|
|
|
|
|
|
# 2. Assert My Games applet present
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.browser.find_element(By.ID, "id_applet_my_games")
|
|
|
|
|
|
)
|
|
|
|
|
|
# 3. Assert no games listed yet for new user
|
|
|
|
|
|
my_games = self.browser.find_element(By.ID, "id_applet_my_games")
|
|
|
|
|
|
game_items = my_games.find_elements(By.CSS_SELECTOR, ".game-item")
|
|
|
|
|
|
self.assertEqual(len(game_items), 0)
|
|
|
|
|
|
# 4. Assert New Game applet present
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_applet_new_game")
|
|
|
|
|
|
|
|
|
|
|
|
def test_game_kit_panel_shows_token_inventory(self):
|
|
|
|
|
|
# 1. Log in, nav to gameboard
|
|
|
|
|
|
self.create_pre_authenticated_session("capman@test.io")
|
|
|
|
|
|
self.browser.get(self.live_server_url + "/gameboard/")
|
|
|
|
|
|
# 2. Assert game kit & gear btns both present (stacked vertically)
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.browser.find_element(By.ID, "id_game_kit_btn")
|
|
|
|
|
|
)
|
2026-03-09 21:13:35 -04:00
|
|
|
|
self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
|
2026-03-08 01:52:03 -05:00
|
|
|
|
# 3. Click game kit btn to open panel
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_game_kit_btn").click()
|
|
|
|
|
|
# 4. Wait for game kit panel to become visible
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertTrue(
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_game_kit").is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
# 5. Assert Coin-on-a-String present in kit
|
|
|
|
|
|
coin = self.browser.find_element(By.ID, "id_kit_coin_on_a_string")
|
|
|
|
|
|
# 6. Hover over it; assert tooltip shows name, entry text & reuse description
|
|
|
|
|
|
ActionChains(self.browser).move_to_element(coin).perform()
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertTrue(
|
|
|
|
|
|
self.browser.find_element(
|
|
|
|
|
|
By.CSS_SELECTOR, "#id_kit_coin_on_a_string .token-tooltip"
|
|
|
|
|
|
).is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
coin_tooltip = self.browser.find_element(
|
|
|
|
|
|
By.CSS_SELECTOR, "#id_kit_coin_on_a_string .token-tooltip"
|
|
|
|
|
|
).text
|
|
|
|
|
|
self.assertIn("Coin-on-a-String", coin_tooltip)
|
|
|
|
|
|
self.assertIn("Admit 1 Entry", coin_tooltip)
|
|
|
|
|
|
self.assertIn("and another after that", coin_tooltip)
|
|
|
|
|
|
# 7. Assert 1× Free Token (complimentary) present in kit
|
|
|
|
|
|
free_token = self.browser.find_element(By.ID, "id_kit_free_token_0")
|
|
|
|
|
|
# 8. Hover over it; assert tooltip shows name, entry text & expiry date
|
|
|
|
|
|
ActionChains(self.browser).move_to_element(free_token).perform()
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertTrue(
|
|
|
|
|
|
self.browser.find_element(
|
|
|
|
|
|
By.CSS_SELECTOR, "#id_kit_free_token_0 .token-tooltip"
|
|
|
|
|
|
).is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
free_tooltip = self.browser.find_element(
|
|
|
|
|
|
By.CSS_SELECTOR, "#id_kit_free_token_0 .token-tooltip"
|
|
|
|
|
|
).text
|
|
|
|
|
|
self.assertIn("Free Token", free_tooltip)
|
|
|
|
|
|
self.assertIn("Admit 1 Entry", free_tooltip)
|
|
|
|
|
|
self.assertIn("Expires", free_tooltip)
|
|
|
|
|
|
# 9. Assert card deck & dice set placeholder present
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_kit_card_deck")
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_kit_dice_set")
|
2026-03-09 21:13:35 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GameboardAppletMenuTest(FunctionalTest):
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
|
super().setUp()
|
|
|
|
|
|
Applet.objects.get_or_create(slug="new-game", defaults={"name": "New Game", "context": "gameboard"})
|
|
|
|
|
|
Applet.objects.get_or_create(slug="my-games", defaults={"name": "My Games", "context": "gameboard"})
|
|
|
|
|
|
self.create_pre_authenticated_session("gamer@test.io")
|
|
|
|
|
|
self.browser.get(self.live_server_url + "/gameboard/")
|
|
|
|
|
|
|
|
|
|
|
|
def test_user_can_toggle_applet_visibility_via_gear_menu(self):
|
|
|
|
|
|
# 1. Assert both applets present
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.browser.find_element(By.ID, "id_applet_my_games")
|
|
|
|
|
|
)
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_applet_new_game")
|
|
|
|
|
|
# 2. Click gear; wait for menu
|
|
|
|
|
|
self.browser.find_element(By.CSS_SELECTOR, ".gear-btn").click()
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertTrue(
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_game_applet_menu").is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
# 3. Find checkboxes; assert both checked
|
|
|
|
|
|
menu = self.browser.find_element(By.ID, "id_game_applet_menu")
|
|
|
|
|
|
my_games_cb = menu.find_element(By.CSS_SELECTOR, '[name="applets"][value="my-games"]')
|
|
|
|
|
|
new_game_cb = menu.find_element(By.CSS_SELECTOR, '[name="applets"][value="new-game"]')
|
|
|
|
|
|
self.assertTrue(my_games_cb.is_selected())
|
|
|
|
|
|
self.assertTrue(new_game_cb.is_selected())
|
|
|
|
|
|
# 4. Uncheck my-games; plant no-reload marker; submit
|
|
|
|
|
|
my_games_cb.click()
|
|
|
|
|
|
self.assertFalse(my_games_cb.is_selected())
|
|
|
|
|
|
self.browser.execute_script("window.__no_reload_marker = true")
|
|
|
|
|
|
menu.find_element(By.CSS_SELECTOR, '[type="submit"]').click()
|
|
|
|
|
|
# 5. Wait for menu to close; assert my-games gone, new game remains
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertFalse(
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_game_applet_menu").is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertRaises(
|
|
|
|
|
|
NoSuchElementException,
|
|
|
|
|
|
self.browser.find_element,
|
|
|
|
|
|
By.ID, "id_applet_my_games",
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_applet_new_game")
|
|
|
|
|
|
# 6. Re-check my-games; assert it reappears
|
|
|
|
|
|
self.browser.find_element(By.CSS_SELECTOR, ".gear-btn").click()
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertTrue(
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_game_applet_menu").is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
menu = self.browser.find_element(By.ID, "id_game_applet_menu")
|
|
|
|
|
|
my_games_cb = menu.find_element(By.CSS_SELECTOR, '[name="applets"][value="my-games"]')
|
|
|
|
|
|
self.assertFalse(my_games_cb.is_selected())
|
|
|
|
|
|
my_games_cb.click()
|
|
|
|
|
|
menu.find_element(By.CSS_SELECTOR, '[type="submit"]').click()
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertFalse(
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_game_applet_menu").is_displayed()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
self.wait_for(
|
|
|
|
|
|
lambda: self.assertTrue(
|
|
|
|
|
|
self.browser.find_element(By.ID, "id_applet_my_games")
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
# 7. Assert no full page reload occurred
|
|
|
|
|
|
self.assertTrue(self.browser.execute_script("return window.__no_reload_marker === true"))
|