dashboard-tests.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. const { chromium } = require('playwright');
  2. /**
  3. * This script is run as part of the "publish & install" workflow, and performs
  4. * browser-based tests of the Vendure Dashboard to ensure it loads and login works.
  5. */
  6. async function runDashboardTests() {
  7. console.log('Starting dashboard tests...');
  8. const browser = await chromium.launch({
  9. headless: true,
  10. args: ['--no-sandbox', '--disable-setuid-sandbox'],
  11. });
  12. let page;
  13. try {
  14. page = await browser.newPage();
  15. // Navigate to the dashboard
  16. console.log('Navigating to dashboard...');
  17. await page.goto('http://localhost:5173');
  18. // Wait for the page to load
  19. await page.waitForLoadState('networkidle');
  20. // Check if the login form is present
  21. console.log('Checking for login form...');
  22. const loginForm = await page.locator('form').first();
  23. if (!loginForm) {
  24. throw new Error('Login form not found');
  25. }
  26. // Fill in login credentials - try multiple selectors
  27. console.log('Filling login credentials...');
  28. const usernameInput = await page
  29. .locator(
  30. 'input[name="username"], input[type="text"], input[placeholder*="username"], input[placeholder*="Username"]',
  31. )
  32. .first();
  33. const passwordInput = await page
  34. .locator(
  35. 'input[name="password"], input[type="password"], input[placeholder*="password"], input[placeholder*="Password"]',
  36. )
  37. .first();
  38. if (!usernameInput || !passwordInput) {
  39. throw new Error('Username or password input fields not found');
  40. }
  41. await usernameInput.fill('superadmin');
  42. await passwordInput.fill('superadmin');
  43. // Submit the form - try multiple selectors
  44. console.log('Submitting login form...');
  45. const submitButton = await page
  46. .locator(
  47. 'button[type="submit"], input[type="submit"], button:has-text("Login"), button:has-text("Sign In")',
  48. )
  49. .first();
  50. if (!submitButton) {
  51. throw new Error('Submit button not found');
  52. }
  53. await submitButton.click();
  54. // Wait for navigation after login
  55. await page.waitForLoadState('networkidle');
  56. // Check if we're logged in by looking for admin dashboard elements
  57. console.log('Verifying successful login...');
  58. // Wait for dashboard elements to appear with a more robust approach
  59. const dashboardSelectors = ['h1:has-text("Dashboard")'];
  60. // Try to wait for any dashboard element to appear
  61. let dashboardElement = null;
  62. let foundSelector = null;
  63. for (const selector of dashboardSelectors) {
  64. try {
  65. // Wait up to 10 seconds for each selector
  66. await page.waitForSelector(selector, { timeout: 10000 });
  67. dashboardElement = await page.locator(selector).first();
  68. if (dashboardElement && (await dashboardElement.count()) > 0) {
  69. foundSelector = selector;
  70. console.log(`Found dashboard element with selector: ${selector}`);
  71. break;
  72. }
  73. } catch (e) {
  74. // Continue to next selector
  75. console.log(`Selector ${selector} not found, trying next...`);
  76. }
  77. }
  78. if (!foundSelector) {
  79. // Fallback: check if we're still on a login page
  80. const currentUrl = page.url();
  81. const pageContent = await page.content();
  82. if (
  83. currentUrl.includes('login') ||
  84. currentUrl.includes('auth') ||
  85. pageContent.includes('login') ||
  86. pageContent.includes('Login')
  87. ) {
  88. throw new Error('Login failed - still on login page');
  89. }
  90. // If we're not on login page, assume login was successful
  91. console.log('Login appears successful - not on login page');
  92. } else {
  93. console.log('Dashboard loaded successfully');
  94. }
  95. // Take a screenshot for debugging
  96. await page.screenshot({ path: '/tmp/dashboard-test-login.png' });
  97. console.log('Screenshot saved to /tmp/dashboard-test-login.png');
  98. // navigate to the product list page by clicking the "Products" link in the sidebar
  99. // based on the text label "Products"
  100. const productsLink = await page.locator('a:has-text("Products")').first();
  101. if (!productsLink) {
  102. throw new Error('Products link not found');
  103. }
  104. await productsLink.click();
  105. // wait for the page to load and verify we're on the Products page
  106. await page.waitForLoadState('networkidle');
  107. // Wait for the Products page H1 to appear
  108. console.log('Waiting for Products page to load...');
  109. try {
  110. await page.waitForSelector('h1:has-text("Products")', { timeout: 10000 });
  111. console.log('Products page loaded successfully');
  112. } catch (e) {
  113. throw new Error('Products page did not load - H1 with "Products" text not found');
  114. }
  115. // get a list of the products in the product list page
  116. const products = await page.locator('tbody tr').all();
  117. console.log(`Found ${products.length} products`);
  118. // Take a screenshot for debugging
  119. await page.screenshot({ path: '/tmp/dashboard-test-products.png' });
  120. console.log('Screenshot saved to /tmp/dashboard-test-products.png');
  121. if (products.length !== 10) {
  122. throw new Error('Expected 10 products, but found ' + products.length);
  123. }
  124. // Check for the test component from our plugin
  125. console.log('Checking for dashboard extensiontest component...');
  126. try {
  127. await page.waitForSelector('div[data-testid="test-component"]', { timeout: 5000 });
  128. console.log('Test component found successfully');
  129. } catch (e) {
  130. throw new Error('Test component not found - div with data-testid="test-component" is missing');
  131. }
  132. console.log('Dashboard tests passed!');
  133. } catch (error) {
  134. console.error('Dashboard test failed:', error.message);
  135. // Take a screenshot on failure
  136. try {
  137. await page.screenshot({ path: '/tmp/dashboard-test-failure.png' });
  138. console.log('Failure screenshot saved to /tmp/dashboard-test-failure.png');
  139. } catch (screenshotError) {
  140. console.log('Could not save failure screenshot:', screenshotError.message);
  141. }
  142. throw error;
  143. } finally {
  144. await browser.close();
  145. }
  146. }
  147. // Wait for the dashboard to be available
  148. async function awaitDashboardStartup() {
  149. console.log('Checking for availability of Dashboard...');
  150. let attempts = 0;
  151. const maxAttempts = 30;
  152. while (attempts < maxAttempts) {
  153. try {
  154. const response = await fetch('http://localhost:5173');
  155. if (response.ok) {
  156. console.log('Dashboard is running!');
  157. return;
  158. }
  159. } catch (e) {
  160. // Ignore errors and continue polling
  161. }
  162. attempts++;
  163. if (attempts < maxAttempts) {
  164. console.log('Dashboard not yet available, waiting 2s...');
  165. await new Promise(resolve => setTimeout(resolve, 2000));
  166. }
  167. }
  168. throw new Error('Unable to establish connection to Dashboard server!');
  169. }
  170. // Main execution
  171. async function main() {
  172. try {
  173. await awaitDashboardStartup();
  174. await runDashboardTests();
  175. process.exit(0);
  176. } catch (error) {
  177. console.error('Dashboard tests failed:', error);
  178. process.exit(1);
  179. }
  180. }
  181. main();