from datetime import datetime
import pytest
from playwright_tests.planning import build_plan
from playwright_tests.setup_page import SetupPage
@pytest.fixture
def config():
return {
"setup": {"run_session": True, "run_token": True},
"trading_token_idas": {"product_codes": "IDAS,IDASTEST01", "market_code": "NATIONAL"},
}
def test_combined_plan_dates_and_products(config):
plan = build_plan(config, now=datetime(2026, 9, 8, 10, 0))
assert plan["session"] == ("08/09/2026 10:07", "08/09/2026 20:30")
assert [t["product_code"] for t in plan["tokens"]] == ["IDAS", "IDASTEST01"]
assert plan["tokens"][0]["delivery_date"] == "09/09/2026"
assert plan["tokens"][0]["rows"][0] == ("ORDER_NOR", "10:10", "18:30")
def test_login_ignores_expired_mutation_settings(config):
assert build_plan(config, "login", now=datetime(2026, 9, 8, 23)) == {"session": None, "tokens": []}
def test_token_override_does_not_modify_config(config):
plan = build_plan(config, "token", "IDASTEST02", datetime(2026, 9, 8, 10))
assert plan["session"] is None
assert [t["product_code"] for t in plan["tokens"]] == ["IDASTEST02"]
assert config["trading_token_idas"]["product_codes"] == "IDAS,IDASTEST01"
@pytest.mark.parametrize("flow, message", [("session", "Session end_time"), ("token", "expiry_time")])
def test_reject_expired_schedule(config, flow, message):
with pytest.raises(ValueError, match=message):
build_plan(config, flow, now=datetime(2026, 9, 8, 23))
def test_reject_inverted_time_session(config):
config["trading_token_idas"]["time_sessions"] = {"ORDER_NOR": {"start_time": "19:00", "end_time": "18:30"}}
with pytest.raises(ValueError, match="ORDER_NOR"):
build_plan(config, "token", now=datetime(2026, 9, 8, 10))
def test_save_waits_for_delayed_confirmation(page, tmp_path):
page.set_content('''
''')
app = SetupPage(page, tmp_path)
app.save("//button", "saved", timeout=2)
assert len(app.screenshots) == 1
def test_save_rejects_error_dialog(page, tmp_path):
page.set_content('''''')
app = SetupPage(page, tmp_path)
with pytest.raises(AssertionError, match="Invalid session"):
app.save("//button", "saved", timeout=2)
assert not app.screenshots
def test_save_accepts_success_dialog(page, tmp_path):
page.set_content('''''')
app = SetupPage(page, tmp_path)
app.save("//button", "activated", timeout=2)
assert app.screenshots
def test_save_does_not_pass_on_click_alone(page, tmp_path):
page.set_content("")
with pytest.raises(AssertionError, match="no explicit success"):
SetupPage(page, tmp_path).save("//button", "saved", timeout=0.2)
def test_grid_button_targets_exact_time_session(page, tmp_path):
page.set_content('''
ORDER_NOR
ORDER_EXCH
''')
SetupPage(page, tmp_path).grid_button("Details", "ORDER_EXCH")
assert page.evaluate("window.selected") == "exchange"
def test_login_clicks_automatically_after_complete_captcha(page, tmp_path):
page.route("https://setup.test/", lambda route: route.fulfill(body='''
TRADING MAINTENANCE
''', content_type="text/html"))
app = SetupPage(page, tmp_path)
app.login({"url": "https://setup.test/", "login": {"username": "sample", "password": "sample"}}, 2000)
assert page.evaluate("window.clickedValue") == "123456"
def test_token_details_button_can_be_outside_grid(page, tmp_path):
page.set_content('''''')
SetupPage(page, tmp_path).grid_button("Token Details")
assert page.evaluate("window.opened") is True
@pytest.mark.parametrize("configured,displayed", [("ORDER_NOR", "ORDER_NORMAL"), ("ORDER_EXCH", "ORDER_EXCHANGE")])
def test_time_session_aliases_match_live_labels(page, tmp_path, configured, displayed):
page.set_content(f'''{displayed}_OTHER
{displayed}
''')
SetupPage(page, tmp_path).grid_button("Details", configured)
assert page.evaluate("window.selected") == "correct"
def test_dropdown_preserves_already_selected_value(page, tmp_path):
page.set_content('')
SetupPage(page, tmp_path).choose(page.locator("#market"), "NATIONAL")
assert page.evaluate("window.clicked === undefined")
@pytest.mark.parametrize("message,passes", [("1|Token updated successfully", True), ("0|Invalid session", False)])
def test_token_save_requires_own_response_despite_old_banner(page, tmp_path, message, passes):
from tests.locators import Locator
page.route("https://setup.test/", lambda route: route.fulfill(content_type="text/html", body='''
Previous token saved successfully
'''))
page.route("**/tokenCtrl/updateTimeSessionMap", lambda route: route.fulfill(json={"message": message}))
page.goto("https://setup.test/")
app = SetupPage(page, tmp_path)
if passes:
app.save(Locator.savetimesessionbtn, "saved", timeout=2)
assert app.screenshots
else:
with pytest.raises(AssertionError, match="Invalid session"):
app.save(Locator.savetimesessionbtn, "saved", timeout=2)
def test_activation_rejects_null_message_even_with_zero_status(page, tmp_path):
from tests.locators import Locator
page.route("https://setup.test/", lambda route: route.fulfill(content_type="text/html", body='''
'''))
page.route("**/tokenCtrl/updateTokenMstr", lambda route: route.fulfill(json={"message": None, "status": 0}))
page.goto("https://setup.test/")
app = SetupPage(page, tmp_path)
app.token_id = "TOKEN123"
with pytest.raises(AssertionError, match="Activation not confirmed for token TOKEN123"):
app.save(Locator.savetokenandactivatebtn, "activated", timeout=2)
assert not app.screenshots