Skip to content
This repository was archived by the owner on Aug 13, 2026. It is now read-only.

test(smoke): enhance flow smoke test with comprehensive checks and Instatus incident management - #227

Open
rvignesh89 wants to merge 1 commit into
mainfrom
rvignesh/stt-smoke-test
Open

test(smoke): enhance flow smoke test with comprehensive checks and Instatus incident management#227
rvignesh89 wants to merge 1 commit into
mainfrom
rvignesh/stt-smoke-test

Conversation

@rvignesh89

@rvignesh89 rvignesh89 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add parse_via_gpt_vision and speech_to_text validation steps to test more flow capabilities
  • Make test time-independent by validating execution timestamps instead of relying on wall-clock time
  • Verify all 7 flow responses including text messages, audio, and AI-powered checks
  • Fix timezone handling for consistent execution across different environments
  • Implement incident-based Instatus integration that opens/resolves incidents (with Discord notifications) instead of just updating component status
  • Add robust timestamp matching with ±1 minute tolerance to handle CI/server clock differences

Summary by CodeRabbit

  • Bug Fixes

    • Improved simulator smoke-test validation by reliably matching results to the current test run, including tolerance for minor timing differences.
    • Enhanced verification of expected messages, audio responses, and completion status.
  • Monitoring

    • Updated service-status reporting to create a single incident when smoke tests fail, preventing duplicate notifications.
    • Automatically resolves active incidents when tests pass again.

…status incident management

- Add parse_via_gpt_vision and speech_to_text validation steps
- Make test time-independent by validating execution timestamps
- Verify 7 flow responses including text, audio, and AI-powered checks
- Fix timezone handling for consistent cross-environment execution
- Implement incident-based Instatus integration that opens/resolves incidents
  instead of just updating component status, enabling Discord notifications
- Add robust timestamp matching with ±1 minute tolerance for CI/server clock differences

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The smoke test now derives a UTC execution timestamp, searches for a matching completion marker within a one-minute tolerance, and validates the seven messages from that simulator run. Instatus reporting now lists named open incidents, creates an investigating incident on the first failure, suppresses duplicate failures, and resolves open incidents after a passing run using the supplied template.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changes: smoke test enhancements and Instatus incident management.
Description check ✅ Passed The description matches the changeset, covering the smoke test validation updates and incident-based Instatus integration.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cypress/e2e/smoke.spec.ts`:
- Around line 27-59: Move the Date.now()-based timestamp candidate and
finishedRe construction into a .then() chained after previewButton.click() or
the flow-triggering command. Keep the existing ±1-minute matching and
message-slice logic unchanged, but ensure the timestamp anchor is captured when
the flow starts rather than while Cypress is still queuing commands.

In `@cypress/plugins/instatus.ts`:
- Around line 46-60: Update createIncident and resolveIncident to validate each
fetch response with res.ok before logging success; throw an error containing the
operation and HTTP status when either request fails, so callers do not treat
unsuccessful lifecycle operations as completed. In resolveIncident, remove the
JSON Content-Type header or provide an appropriate request body, while
preserving the existing successful-request behavior.
- Around line 78-88: Update the reportToInstatus call in the Cypress
configuration example to pass resolveTemplateId as the fourth argument and
passed as the fifth argument, matching the function signature and preserving
correct status reporting for both passing and failing runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: aade0ac0-d4a7-4ad2-b5be-b075324ee3a0

📥 Commits

Reviewing files that changed from the base of the PR and between f5a60e7 and d8b20ae.

📒 Files selected for processing (2)
  • cypress/e2e/smoke.spec.ts
  • cypress/plugins/instatus.ts

Comment thread cypress/e2e/smoke.spec.ts
Comment on lines +27 to +59
const fmt = (d: Date): string => {
const p = (n: number): string => String(n).padStart(2, '0');
return `${p(d.getUTCDate())}-${p(d.getUTCMonth() + 1)}-${d.getUTCFullYear()} ${p(
d.getUTCHours()
)}:${p(d.getUTCMinutes())}`;
};
const now = Date.now();
const candidates = [-60000, 0, 60000].map((offset) => fmt(new Date(now + offset)));
const escaped = candidates.map((c) => c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
const finishedRe = new RegExp(`Test Finished - (${escaped.join('|')})`);

// The full flow is slow — wait (retrying) for THIS run's unique finish marker.
cy.contains('[data-testid="simulatorMessage"]', finishedRe, { timeout: 180000 }).should(
'exist'
);
cy.get('[data-testid="simulatedMessages"]')
.find('[data-testid="simulatorMessage"]')
.then(($messages) => {
const lastThree = $messages.slice(-3);
// Anchor on the last matching "Test Finished" bubble and take the 7 bubbles
// of that run. Bounding the slice with the same timestamp on both ends means
// a truncated/failed run (which jumps straight to "Test Finished") fails the
// "Test on" assertion instead of borrowing a prior run's bubbles.
let endIdx = -1;
let execTime = '';
$messages.each((i, el) => {
const match = Cypress.$(el).text().match(finishedRe);
if (match) {
endIdx = i;
[, execTime] = match;
}
});
expect(endIdx, 'index of the "Test Finished" message').to.be.gte(6);
const responses = $messages.slice(endIdx - 6, endIdx + 1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd 'smoke.spec.ts' -x cat -n {}
fd 'cypress.config' -x cat -n {}

Repository: glific/cypress-testing

Length of output: 7771


Anchor the timestamp after the flow starts

Date.now() is evaluated while Cypress is still queuing commands, so this anchor can drift well ahead of the actual previewButton.click()/flow start. Capture now and build finishedRe in a .then() chained off the trigger command; otherwise a slow run can push the real server minute outside the ±1 minute window and make the smoke test miss its own finish marker.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 35-35: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(Test Finished - (${escaped.join('|')}))
Note: [CWE-1333] Inefficient Regular Expression Complexity

(regexp-from-variable)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cypress/e2e/smoke.spec.ts` around lines 27 - 59, Move the Date.now()-based
timestamp candidate and finishedRe construction into a .then() chained after
previewButton.click() or the flow-triggering command. Keep the existing
±1-minute matching and message-slice logic unchanged, but ensure the timestamp
anchor is captured when the flow starts rather than while Cypress is still
queuing commands.

Comment on lines +46 to +60
async function createIncident(apiKey: string, pageId: string, componentId: string): Promise<void> {
const res = await fetch(`${API_BASE}/${pageId}/incidents`, {
method: 'POST',
headers: authHeaders(apiKey),
body: JSON.stringify({
name: INCIDENT_NAME,
message: 'The automated Glific flow smoke test failed.',
status: 'INVESTIGATING',
notify: true,
components: [componentId],
statuses: [{ id: componentId, status: 'MAJOROUTAGE' }],
}),
});
console.log(`Instatus: opened incident (notify) → HTTP ${res.status}`);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

createIncident and resolveIncident don't check res.ok — silent failures break the incident lifecycle.

Both functions log the HTTP status but never check whether the response succeeded. This causes two problems:

  1. createIncident (lines 59): Logs "opened incident" even on a 4xx/5xx response. If creation fails, the next run's getOpenIncidents returns empty (incident was never created), so it tries to create again — re-notifying Discord on every failing run, defeating the "one incident per outage" design.

  2. resolveIncident (line 75): Logs "resolved incident" even on failure. If resolution fails, the incident stays open indefinitely and the error is only visible in CI logs.

Additionally, resolveIncident sends a POST with Content-Type: application/json but no body. Some API gateways reject this combination with a 400.

[major_severity]

🔧 Proposed fix: add `res.ok` checks and throw on failure
 async function createIncident(apiKey: string, pageId: string, componentId: string): Promise<void> {
   const res = await fetch(`${API_BASE}/${pageId}/incidents`, {
     method: 'POST',
     headers: authHeaders(apiKey),
     body: JSON.stringify({
       name: INCIDENT_NAME,
       message: 'The automated Glific flow smoke test failed.',
       status: 'INVESTIGATING',
       notify: true,
       components: [componentId],
       statuses: [{ id: componentId, status: 'MAJOROUTAGE' }],
     }),
   });
-  console.log(`Instatus: opened incident (notify) → HTTP ${res.status}`);
+  if (!res.ok) {
+    throw new Error(`Instatus: failed to open incident → HTTP ${res.status}`);
+  }
+  console.log(`Instatus: opened incident (notify) → HTTP ${res.status}`);
 }
 async function resolveIncident(
   apiKey: string,
   pageId: string,
   incidentId: string,
   resolveTemplateId: string
 ): Promise<void> {
   const res = await fetch(
     `${API_BASE_V2}/${pageId}/incidents/${incidentId}/incident-updates/${resolveTemplateId}`,
     {
       method: 'POST',
       headers: authHeaders(apiKey),
+      body: JSON.stringify({}),
     }
   );
-  console.log(`Instatus: resolved incident ${incidentId} (notify) → HTTP ${res.status}`);
+  if (!res.ok) {
+    throw new Error(`Instatus: failed to resolve incident ${incidentId} → HTTP ${res.status}`);
+  }
+  console.log(`Instatus: resolved incident ${incidentId} (notify) → HTTP ${res.status}`);
 }

Also applies to: 62-76

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cypress/plugins/instatus.ts` around lines 46 - 60, Update createIncident and
resolveIncident to validate each fetch response with res.ok before logging
success; throw an error containing the operation and HTTP status when either
request fails, so callers do not treat unsuccessful lifecycle operations as
completed. In resolveIncident, remove the JSON Content-Type header or provide an
appropriate request body, while preserving the existing successful-request
behavior.

Comment on lines 78 to 88
export async function reportToInstatus(
apiKey: string,
pageId: string,
componentId: string,
resolveTemplateId: string,
passed: boolean
): Promise<null> {
if (!apiKey || !pageId || !componentId) {
if (!apiKey || !pageId || !componentId || !resolveTemplateId) {
console.warn('Instatus credentials not set — skipping status report');
return null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the actual cypress.config.ts passes resolveTemplateId to reportToInstatus.
# If only cypress.config.ts.example exists, the contract is broken.

# Find the actual config file (not the .example)
fd -t f 'cypress.config.ts' --exclude '*.example' .

# If found, check how reportToInstatus is called
fd -t f 'cypress.config.ts' --exclude '*.example' . -x sed -n '1,80p' {} | grep -A 10 'reportToInstatus'

# Also check for INSTATUS_RESOLVE_TEMPLATE_ID in env/config
rg -n 'INSTATUS_RESOLVE_TEMPLATE_ID|resolveTemplateId' --type ts

Repository: glific/cypress-testing

Length of output: 160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Files =="
git ls-files | rg '(^|/)cypress\.config\.ts$|(^|/)cypress\.config\.ts\.example$|(^|/)instatus\.ts$'

echo
echo "== reportToInstatus references =="
rg -n 'reportToInstatus|INSTATUS_RESOLVE_TEMPLATE_ID|resolveTemplateId' .

echo
echo "== cypress.plugins.instatus.ts (relevant lines) =="
sed -n '1,220p' cypress/plugins/instatus.ts

Repository: glific/cypress-testing

Length of output: 5108


Pass resolveTemplateId from cypress.config.ts.example.
cypress.config.ts.example:39 still calls reportToInstatus(...) with four args, so passed shifts into resolveTemplateId and the real passed flag becomes undefined. Passing runs will open incidents, and failing runs will skip reporting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cypress/plugins/instatus.ts` around lines 78 - 88, Update the
reportToInstatus call in the Cypress configuration example to pass
resolveTemplateId as the fourth argument and passed as the fifth argument,
matching the function signature and preserving correct status reporting for both
passing and failing runs.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant