import pytest import asyncio from playwright.async_api import expect @pytest.mark.asyncio class TestBillingAdminFlow: async def test_01_admin_login(self, page, base_url): await page.goto(f"{base_url}/") await page.wait_for_load_state("networkidle") await page.fill('input[name="username"]', 'adminuser') await page.fill('input[name="password"]', 'adminpassword123') await page.click('button[type="submit"]') await page.wait_for_load_state("networkidle") await expect(page.locator('text=Dashboard')).to_be_visible() async def test_02_navigate_to_admin_billing(self, page, base_url): await page.goto(f"{base_url}/") await page.wait_for_load_state("networkidle") await page.fill('input[name="username"]', 'adminuser') await page.fill('input[name="password"]', 'adminpassword123') await page.click('button[type="submit"]') await page.wait_for_load_state("networkidle") await page.click('text=Admin') await page.wait_for_load_state("networkidle") await page.click('text=Billing') await page.wait_for_url("**/admin/billing") await expect(page.locator('h2:has-text("Billing Administration")')).to_be_visible() async def test_03_view_revenue_statistics(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('.stats-cards')).to_be_visible() await expect(page.locator('.stat-card:has-text("Total Revenue")')).to_be_visible() await expect(page.locator('.stat-card:has-text("Total Invoices")')).to_be_visible() await expect(page.locator('.stat-card:has-text("Pending Invoices")')).to_be_visible() async def test_04_verify_revenue_value_display(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") revenue_stat = page.locator('.stat-card:has-text("Total Revenue") .stat-value') await expect(revenue_stat).to_be_visible() revenue_text = await revenue_stat.text_content() assert '$' in revenue_text or '0' in revenue_text async def test_05_view_pricing_configuration_table(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('.pricing-config-section')).to_be_visible() await expect(page.locator('h3:has-text("Pricing Configuration")')).to_be_visible() await expect(page.locator('.pricing-table')).to_be_visible() async def test_06_verify_pricing_config_rows(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('.pricing-table tbody tr')).to_have_count(6, timeout=5000) await expect(page.locator('td:has-text("Storage cost per GB per month")')).to_be_visible() await expect(page.locator('td:has-text("Bandwidth egress cost per GB")')).to_be_visible() await expect(page.locator('td:has-text("Free tier storage")')).to_be_visible() async def test_07_click_edit_pricing_button(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") edit_buttons = page.locator('.btn-edit') await expect(edit_buttons.first).to_be_visible() page.on('dialog', lambda dialog: dialog.dismiss()) await edit_buttons.first.click() await page.wait_for_timeout(1000) async def test_08_edit_pricing_value(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") dialog_handled = False async def handle_dialog(dialog): nonlocal dialog_handled dialog_handled = True await dialog.accept(text="0.005") page.on('dialog', handle_dialog) edit_button = page.locator('.btn-edit').first await edit_button.click() await page.wait_for_timeout(1000) if dialog_handled: await page.wait_for_timeout(2000) async def test_09_view_invoice_generation_section(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('.invoice-generation-section')).to_be_visible() await expect(page.locator('h3:has-text("Generate Invoices")')).to_be_visible() async def test_10_verify_invoice_generation_form(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('#invoiceYear')).to_be_visible() await expect(page.locator('#invoiceMonth')).to_be_visible() await expect(page.locator('#generateInvoices')).to_be_visible() async def test_11_set_invoice_generation_date(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await page.fill('#invoiceYear', '2024') await page.fill('#invoiceMonth', '11') year_value = await page.input_value('#invoiceYear') month_value = await page.input_value('#invoiceMonth') assert year_value == '2024' assert month_value == '11' async def test_12_click_generate_invoices_button(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await page.fill('#invoiceYear', '2024') await page.fill('#invoiceMonth', '10') page.on('dialog', lambda dialog: dialog.dismiss()) await page.click('#generateInvoices') await page.wait_for_timeout(1000) async def test_13_verify_all_stat_cards_present(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") stat_cards = page.locator('.stat-card') await expect(stat_cards).to_have_count(3) async def test_14_verify_pricing_table_headers(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('th:has-text("Configuration")')).to_be_visible() await expect(page.locator('th:has-text("Current Value")')).to_be_visible() await expect(page.locator('th:has-text("Unit")')).to_be_visible() await expect(page.locator('th:has-text("Actions")')).to_be_visible() async def test_15_verify_all_edit_buttons_present(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") edit_buttons = page.locator('.btn-edit') count = await edit_buttons.count() assert count == 6 async def test_16_scroll_through_admin_dashboard(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await page.evaluate("window.scrollTo(0, 0)") await page.wait_for_timeout(500) await page.evaluate("window.scrollTo(0, document.body.scrollHeight / 2)") await page.wait_for_timeout(500) await page.evaluate("window.scrollTo(0, document.body.scrollHeight)") await page.wait_for_timeout(500) await page.evaluate("window.scrollTo(0, 0)") await page.wait_for_timeout(500) async def test_17_verify_responsive_layout(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") await expect(page.locator('.admin-billing')).to_be_visible() bounding_box = await page.locator('.admin-billing').bounding_box() assert bounding_box['width'] > 0 assert bounding_box['height'] > 0 async def test_18_verify_page_title(self, page, base_url): await page.goto(f"{base_url}/admin/billing") await page.wait_for_load_state("networkidle") title = await page.title() assert title is not None