db.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /**
  2. * ================================================================
  3. * E2E Test Database Reset Global Setup
  4. * ================================================================
  5. * Runs reset-db.sh before all E2E tests to ensure clean database state
  6. *
  7. * Usage:
  8. * Add to playwright.config.js:
  9. * globalSetup: path.join(__dirname, 'e2e', 'helpers', 'db.js')
  10. * ================================================================
  11. */
  12. var path = require('path');
  13. var child_process = require('child_process');
  14. var SCRIPT_PATH = path.join(__dirname, '..', 'reset-db.sh');
  15. /**
  16. * Reset database by executing reset-db.sh
  17. * This function is called as globalSetup before all E2E tests
  18. * @throws {Error} - If script execution fails
  19. */
  20. function resetDatabase() {
  21. console.log('============================================================');
  22. console.log('E2E Global Setup: Running Database Reset');
  23. console.log('============================================================');
  24. console.log('Script path: ' + SCRIPT_PATH);
  25. console.log('============================================================');
  26. try {
  27. var mysqlHost = process.env.MYSQL_HOST || '192.168.16.251';
  28. var mysqlUser = process.env.MYSQL_USER || 'zxyj';
  29. var mysqlPass = process.env.MYSQL_PASS || 'zxyj@123';
  30. var mysqlDb = process.env.MYSQL_DB || 'zxyj';
  31. // On Windows, use mysql.exe directly since bash is unavailable
  32. if (process.platform === 'win32') {
  33. var seedFile = path.join(__dirname, '..', 'seed-data.sql');
  34. console.log('[INFO] Windows detected, using mysql.exe directly');
  35. console.log('[INFO] DB: ' + mysqlDb + ' @ ' + mysqlHost);
  36. // Try to seed the main database (may fail if DB doesn't match)
  37. try {
  38. child_process.execSync(
  39. 'mysql -h ' + mysqlHost + ' -u ' + mysqlUser + ' -p"' + mysqlPass + '" ' + mysqlDb + ' < "' + seedFile + '"',
  40. { stdio: 'inherit', cwd: __dirname, shell: true, timeout: 15000 }
  41. );
  42. } catch (seedErr) {
  43. console.log('[WARN] Main seed failed (expected if DB schema differs), continuing...');
  44. }
  45. } else {
  46. // Execute the reset-db.sh script
  47. // Using execSync for synchronous execution in globalSetup
  48. child_process.execSync('bash ' + SCRIPT_PATH, {
  49. stdio: 'inherit',
  50. cwd: __dirname
  51. });
  52. }
  53. // Always refresh verification codes for test users
  54. // Important: Insert MULTIPLE codes per phone because desktop+mobile projects
  55. // run in parallel with 2 workers. Each worker consumes a verification code
  56. // (single-use: backend sets used=1 on verify), so we need enough codes for
  57. // all concurrent login attempts.
  58. console.log('[INFO] Refreshing verification codes for test users (5 per phone for parallel workers)...');
  59. var phones = ['13701366188','13701366189','13701366190','13800000001','13800000010','13800000020','13800000030','13800138001','13800138000'];
  60. var values = [];
  61. // 5 codes per phone to handle up to 5 concurrent workers
  62. for (var p = 0; p < phones.length; p++) {
  63. for (var i = 0; i < 5; i++) {
  64. var type = phones[p] === '13800138000' ? 'admin_login' : 'login';
  65. values.push("('" + phones[p] + "', '123456', '" + type + "', 300, NOW(), '2026-07-28 23:59:59', 0)");
  66. }
  67. }
  68. child_process.execSync(
  69. 'mysql -h ' + mysqlHost + ' -u ' + mysqlUser + ' -p"' + mysqlPass + '" ' + mysqlDb +
  70. ' -e "DELETE FROM verification_codes WHERE phone IN (\'13701366188\',\'13701366189\',\'13701366190\',\'13800000001\',\'13800000010\',\'13800000020\',\'13800000030\',\'13800138001\',\'13800138000\'); INSERT INTO verification_codes (phone, code, type, expires_in, created_at, expires_at, used) VALUES ' + values.join(',') + ';"',
  71. { stdio: 'inherit', cwd: __dirname, shell: true, timeout: 30000 }
  72. );
  73. // Ensure required test data exists (seed-data.sql may not fully execute)
  74. try {
  75. // Use a single mysql call with multiple statements to ensure all critical data exists
  76. var ensureSQL =
  77. "UPDATE users SET password='5da27d18ad7ba1228d02ce9c3c5f6c87' WHERE id=1001 AND password IS NULL;" +
  78. "UPDATE families SET creator_id=1002 WHERE id=2001 AND creator_id IS NULL;" +
  79. "INSERT IGNORE INTO family_members (id, family_id, user_id, nickname, phone, gender, birthday, generation, is_spouse, show_to_family, total_points, system_points, streak_days, created_at, updated_at, relationship_type) VALUES " +
  80. "(1000, 2001, 1002, '家长用户', '13701366188', 'male', '1985-01-01', 0, 0, 1, 0, 0, 0, NOW(), NOW(), 'other');" +
  81. "INSERT IGNORE INTO family_members (id, family_id, user_id, nickname, phone, gender, birthday, generation, is_spouse, show_to_family, total_points, system_points, streak_days, created_at, updated_at, relationship_type) VALUES " +
  82. "(1001, 2001, 1003, '孩子用户A', '13701366189', 'male', '2015-06-15', -1, 0, 1, 0, 0, 0, NOW(), NOW(), 'other');" +
  83. "INSERT IGNORE INTO family_members (id, family_id, user_id, nickname, phone, gender, birthday, generation, is_spouse, show_to_family, total_points, system_points, streak_days, created_at, updated_at, relationship_type) VALUES " +
  84. "(1002, 2001, 1004, '孩子用户B', '13701366190', 'female', '2018-03-20', -1, 0, 1, 0, 0, 0, NOW(), NOW(), 'other');" +
  85. "INSERT IGNORE INTO family_members (id, family_id, user_id, nickname, relationship_type, created_at) VALUES (1003, 2001, NULL, '测试孩子', 'other', NOW());";
  86. child_process.execSync(
  87. 'mysql -h "' + mysqlHost + '" -u "' + mysqlUser + '" -p"' + mysqlPass + '" "' + mysqlDb + '" -e "' + ensureSQL.replace(/"/g, '\\"') + '"',
  88. { stdio: 'inherit', cwd: __dirname, shell: true, timeout: 15000 }
  89. );
  90. } catch (ensureErr) {
  91. console.log('[WARN] Data ensure step failed (non-fatal): ' + ensureErr.message);
  92. }
  93. console.log('============================================================');
  94. console.log('E2E Global Setup: Database Seed Complete');
  95. console.log('============================================================');
  96. } catch (error) {
  97. console.error('============================================================');
  98. console.error('E2E Global Setup: Verification code seed FAILED');
  99. console.error('============================================================');
  100. console.error('Error: ' + error.message);
  101. console.error('============================================================');
  102. console.error('[WARN] Codes not refreshed — tests may fail 401 if codes expired.');
  103. console.error('============================================================');
  104. }
  105. }
  106. // Run if executed directly
  107. resetDatabase();
  108. // ================================================================
  109. // Module exports (CommonJS)
  110. // ================================================================
  111. module.exports = resetDatabase;