@ai-qa/workflow 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/DESIGN.md ADDED
File without changes
package/install.js CHANGED
@@ -57,6 +57,7 @@ const NPM_SCRIPTS = {
57
57
  'qa:list': 'node ai-qa-workflow.js list',
58
58
  'dashboard': 'cd qa-dashboard && npm start',
59
59
  'dashboard:dev': 'cd qa-dashboard && npx nodemon app.js',
60
+ 'dashboard:stop': 'npx kill-port 4000',
60
61
  };
61
62
 
62
63
  const BANNER = `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-qa/workflow",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "One-command AI QA Pipeline — User Story to Test Report. Auto-detects project config, generates Playwright tests, self-heals failures, dashboard UI.",
5
5
  "keywords": [
6
6
  "qa",
@@ -33,6 +33,7 @@
33
33
  "qa:status": "node ai-qa-workflow.js status",
34
34
  "qa:list": "node ai-qa-workflow.js list",
35
35
  "dashboard": "cd qa-dashboard && npm start",
36
- "dashboard:dev": "cd qa-dashboard && npx nodemon app.js"
36
+ "dashboard:dev": "cd qa-dashboard && npx nodemon app.js",
37
+ "dashboard:stop": "npx kill-port 4000"
37
38
  }
38
39
  }
@@ -9,6 +9,33 @@ const pm = require('./services/project-manager');
9
9
  const app = express();
10
10
  const PORT = process.env.PORT || 4000;
11
11
 
12
+ // Auto-shutdown: when client closes the tab, shutdown after timeout
13
+ let shutdownTimer = null;
14
+ const SHUTDOWN_DELAY = 10000; // 10 seconds — allows page navigation
15
+
16
+ function resetShutdownTimer() {
17
+ if (shutdownTimer) {
18
+ clearTimeout(shutdownTimer);
19
+ shutdownTimer = null;
20
+ }
21
+ }
22
+
23
+ function scheduleShutdown() {
24
+ resetShutdownTimer();
25
+ shutdownTimer = setTimeout(() => {
26
+ console.log('\n Dashboard tab closed — shutting down.');
27
+ process.exit(0);
28
+ }, SHUTDOWN_DELAY);
29
+ }
30
+
31
+ // Reset timer on every request (handles page navigation)
32
+ app.use((req, res, next) => {
33
+ if (req.path !== '/shutdown') {
34
+ resetShutdownTimer();
35
+ }
36
+ next();
37
+ });
38
+
12
39
  app.set('view engine', 'ejs');
13
40
  app.set('views', path.join(__dirname, 'views'));
14
41
  app.use(expressLayouts);
@@ -18,6 +45,30 @@ app.use(express.urlencoded({ extended: true }));
18
45
  app.use(express.json());
19
46
  app.use(morgan('dev'));
20
47
 
48
+ // Client signals it's leaving (tab close / navigation)
49
+ app.post('/shutdown', (req, res) => {
50
+ scheduleShutdown();
51
+ res.json({ shutdown: true });
52
+ });
53
+
54
+ // SSE Endpoint for React-like live reload
55
+ app.get('/live-reload', (req, res) => {
56
+ res.setHeader('Content-Type', 'text/event-stream');
57
+ res.setHeader('Cache-Control', 'no-cache');
58
+ res.setHeader('Connection', 'keep-alive');
59
+ res.flushHeaders();
60
+
61
+ // Keep connection open
62
+ const keepAlive = setInterval(() => {
63
+ res.write(': keepalive\n\n');
64
+ }, 30000);
65
+
66
+ req.on('close', () => {
67
+ clearInterval(keepAlive);
68
+ res.end();
69
+ });
70
+ });
71
+
21
72
  // Serve Allure reports for each registered project
22
73
  app.use('/allure-report', (req, res, next) => {
23
74
  const projectId = req.query.project;
@@ -43,4 +94,5 @@ app.use((req, res) => { res.status(404).render('error', { message: 'Page not fou
43
94
 
44
95
  app.listen(PORT, () => {
45
96
  console.log(`QA Dashboard running at http://localhost:${PORT}`);
97
+ console.log(`Close the browser tab to stop the server.`);
46
98
  });