dashboard-tests.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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("Insights")'];
  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 first expanding the "Catalog" section
  99. // and then clicking the "Products" link in the sidebar
  100. console.log('Expanding Catalog section...');
  101. const catalogSection = await page.locator('button:has-text("Catalog")').first();
  102. if (!catalogSection) {
  103. throw new Error('Catalog section not found');
  104. }
  105. await catalogSection.click();
  106. // Wait for the section to expand and Products link to be visible
  107. console.log('Waiting for Products link to be visible...');
  108. await page.waitForSelector('a:has-text("Products")', { timeout: 5000 });
  109. const productsLink = await page.locator('a:has-text("Products")').first();
  110. if (!productsLink) {
  111. throw new Error('Products link not found after expanding Catalog section');
  112. }
  113. await productsLink.click();
  114. // wait for the page to load and verify we're on the Products page
  115. await page.waitForLoadState('networkidle');
  116. // Wait for the Products page H1 to appear
  117. console.log('Waiting for Products page to load...');
  118. try {
  119. await page.waitForSelector('h1:has-text("Products")', { timeout: 10000 });
  120. console.log('Products page loaded successfully');
  121. } catch (e) {
  122. throw new Error('Products page did not load - H1 with "Products" text not found');
  123. }
  124. // get a list of the products in the product list page
  125. const products = await page.locator('tbody tr').all();
  126. console.log(`Found ${products.length} products`);
  127. // Take a screenshot for debugging
  128. await page.screenshot({ path: '/tmp/dashboard-test-products.png' });
  129. console.log('Screenshot saved to /tmp/dashboard-test-products.png');
  130. if (products.length !== 10) {
  131. throw new Error('Expected 10 products, but found ' + products.length);
  132. }
  133. // Check for the test component from our plugin
  134. console.log('Checking for dashboard extensiontest component...');
  135. try {
  136. await page.waitForSelector('div[data-testid="test-component"]', { timeout: 5000 });
  137. console.log('Test component found successfully');
  138. } catch (e) {
  139. throw new Error('Test component not found - div with data-testid="test-component" is missing');
  140. }
  141. console.log('Dashboard tests passed!');
  142. } catch (error) {
  143. console.error('Dashboard test failed:', error.message);
  144. // Take a screenshot on failure
  145. try {
  146. await page.screenshot({ path: '/tmp/dashboard-test-failure.png' });
  147. console.log('Failure screenshot saved to /tmp/dashboard-test-failure.png');
  148. } catch (screenshotError) {
  149. console.log('Could not save failure screenshot:', screenshotError.message);
  150. }
  151. throw error;
  152. } finally {
  153. await browser.close();
  154. }
  155. }
  156. // Main execution
  157. async function main() {
  158. try {
  159. // Note: The workflow uses wait-on to ensure the dashboard is available
  160. // before running this script, so we can proceed directly to tests
  161. await runDashboardTests();
  162. process.exit(0);
  163. } catch (error) {
  164. console.error('Dashboard tests failed:', error);
  165. process.exit(1);
  166. }
  167. }
  168. main();