""" Selenium test suite for Stark import system Tests the complete Stark material import workflow """ import unittest import time import os from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.keys import Keys import requests import json class StarkImportTests(unittest.TestCase): """Test Stark material import functionality""" @classmethod def setUpClass(cls): """Initialize Selenium driver""" options = webdriver.ChromeOptions() # Uncomment for headless mode: # options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') cls.driver = webdriver.Chrome(options=options) cls.base_url = os.getenv('BASE_URL', 'http://localhost:3000') cls.wait = WebDriverWait(cls.driver, 15) @classmethod def tearDownClass(cls): """Close driver""" cls.driver.quit() def setUp(self): """Before each test""" self.driver.get(f'{self.base_url}/materials') time.sleep(2) def test_01_page_loads(self): """Test that materials page loads""" self.assertEqual(self.driver.title, 'Tilbudgivern - Materialer') def test_02_stark_button_visible(self): """Test Stark import button is visible""" try: button = self.wait.until( EC.presence_of_element_located((By.XPATH, "//button[contains(text(), 'Importer Stark')]")) ) self.assertTrue(button.is_displayed()) except Exception as e: self.fail(f"Stark button not found: {e}") def test_03_open_modal(self): """Test opening Stark import modal""" button = self.driver.find_element(By.XPATH, "//button[contains(text(), 'Importer Stark')]") button.click() time.sleep(1) modal = self.wait.until( EC.presence_of_element_located((By.XPATH, "//*[contains(text(), 'Importer Stark Katalog')]")) ) self.assertTrue(modal.is_displayed()) def test_04_file_input_exists(self): """Test file input element exists in modal""" button = self.driver.find_element(By.XPATH, "//button[contains(text(), 'Importer Stark')]") button.click() time.sleep(1) file_input = self.wait.until( EC.presence_of_element_located((By.XPATH, "//input[@type='file']")) ) self.assertTrue(file_input is not None) def test_05_upload_csv_file(self): """Test uploading CSV file""" # Create test CSV file test_csv = '/tmp/stark_selenium_test.csv' csv_content = """ProduktNr;Produktnavn;Kategori;Enhed;Pris;Lager 280;B7 Tagplader gul;Tagmaterialer;m2;245.50;ja 1001;Regugle 38x73;Materialer;meter;12.75;ja 1500;Tagskrue 4.8x35;Beslag;kg;89.50;ja""" with open(test_csv, 'w') as f: f.write(csv_content) # Open modal button = self.driver.find_element(By.XPATH, "//button[contains(text(), 'Importer Stark')]") button.click() time.sleep(1) # Upload file file_input = self.driver.find_element(By.XPATH, "//input[@type='file']") file_input.send_keys(os.path.abspath(test_csv)) time.sleep(2) # Check if filename appears filename_element = self.driver.find_elements(By.XPATH, "//*[contains(text(), 'stark_selenium_test')]") self.assertTrue(len(filename_element) > 0, "Filename not displayed after upload") def test_06_submit_import(self): """Test submitting import""" # Create test CSV test_csv = '/tmp/stark_selenium_test2.csv' csv_content = """ProduktNr;Produktnavn;Kategori;Enhed;Pris;Lager 280;B7 Tagplader gul;Tagmaterialer;m2;245.50;ja""" with open(test_csv, 'w') as f: f.write(csv_content) # Open modal and upload button = self.driver.find_element(By.XPATH, "//button[contains(text(), 'Importer Stark')]") button.click() time.sleep(1) file_input = self.driver.find_element(By.XPATH, "//input[@type='file']") file_input.send_keys(os.path.abspath(test_csv)) time.sleep(2) # Find and click submit button submit_buttons = self.driver.find_elements(By.XPATH, "//button[contains(text(), 'Importer')]") if submit_buttons: submit_buttons[0].click() time.sleep(3) def test_07_api_stark_status(self): """Test Stark status API endpoint""" response = requests.get(f'{self.base_url}/api/stark/status') self.assertEqual(response.status_code, 200) data = response.json() self.assertIn('stark_materials_cache_count', data) self.assertGreaterEqual(data['stark_materials_cache_count'], 0) def test_08_api_import_history(self): """Test import history API endpoint""" response = requests.get(f'{self.base_url}/api/stark/import-history') self.assertEqual(response.status_code, 200) data = response.json() self.assertIn('imports', data) self.assertIsInstance(data['imports'], list) def test_09_stark_materials_in_database(self): """Test that Stark materials exist in database""" response = requests.get(f'{self.base_url}/api/materials?supplier=Stark') # Should either return 200 with data or 404 (both are OK) self.assertIn(response.status_code, [200, 404, 400]) def test_10_api_upload_endpoint_exists(self): """Test that upload endpoint is available""" response = requests.get(f'{self.base_url}/api/stark/upload') # GET should not be allowed, but endpoint should exist # Status will be 404 (method not allowed) or 405 (method not allowed) self.assertIn(response.status_code, [404, 405, 500]) # 500 is OK if no file provided class StarkIntegrationTests(unittest.TestCase): """Integration tests for Stark materials in project workflow""" @classmethod def setUpClass(cls): """Initialize""" cls.base_url = os.getenv('BASE_URL', 'http://localhost:3000') def test_01_stark_materials_exist(self): """Test that Stark materials are in system""" response = requests.get(f'{self.base_url}/api/materials') self.assertEqual(response.status_code, 200) def test_02_stark_cache_populated(self): """Test that Stark cache has data""" response = requests.get(f'{self.base_url}/api/stark/status') if response.status_code == 200: data = response.json() # Cache should have some items (from our test inserts) self.assertGreaterEqual(data.get('stark_materials_cache_count', 0), 0) def run_tests(): """Run all tests""" # Create test suite loader = unittest.TestLoader() suite = unittest.TestSuite() # Add tests suite.addTests(loader.loadTestsFromTestCase(StarkImportTests)) suite.addTests(loader.loadTestsFromTestCase(StarkIntegrationTests)) # Run with verbose output runner = unittest.TextTestRunner(verbosity=2) result = runner.run(suite) return result.wasSuccessful() if __name__ == '__main__': success = run_tests() exit(0 if success else 1)