Skip to content

Commit e256be8

Browse files
authored
fix metrics test (#916)
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- RECURSEML_SUMMARY:START --> ## High-level PR Summary This PR fixes a test in the internal metrics endpoint by replacing a simple wait timer with a more robust retry mechanism. Instead of waiting for a fixed 3000ms delay to allow for asynchronous event logging, the PR implements a `Result.retry` approach that attempts to fetch metrics up to 5 times with exponential backoff, only proceeding when the metrics response differs from the initial state. This change makes the test more reliable by ensuring proper test conditions are met before assertions are made rather than relying on an arbitrary timeout. ⏱️ Estimated Review Time: 5-15 minutes <details> <summary>💡 Review Order Suggestion</summary> | Order | File Path | |-------|-----------| | 1 | `apps/e2e/tests/backend/endpoints/api/v1/internal-metrics.test.ts` | </details> [![Need help? Join our Discord](https://img.shields.io/badge/Need%20help%3F%20Join%20our%20Discord-5865F2?style=plastic&logo=discord&logoColor=white)](https://discord.gg/n3SsVDAW6U) <!-- RECURSEML_SUMMARY:END --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Improved backend metrics verification with a retry-based approach to handle eventual consistency, reducing test flakiness. * Replaced static waits with structured retries for faster, more reliable execution. * Strengthened assertions on metrics fields (e.g., totals and recent activity) for clearer validation. * Maintains checks to ensure anonymous users remain excluded from metrics. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 3fe82b6 commit e256be8

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

apps/e2e/tests/backend/endpoints/api/v1/internal-metrics.test.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { wait } from "@stackframe/stack-shared/dist/utils/promises";
22
import { expect } from "vitest";
33
import { NiceResponse, it } from "../../../../helpers";
44
import { Auth, InternalApiKey, Project, backendContext, createMailbox, niceBackendFetch } from "../../../backend-helpers";
5+
import { Result } from "@stackframe/stack-shared/dist/utils/results";
56

67
async function ensureAnonymousUsersAreStillExcluded(metricsResponse: NiceResponse) {
78
for (let i = 0; i < 2; i++) {
@@ -125,29 +126,38 @@ it("should exclude anonymous users from metrics", async ({ expect }) => {
125126
await Auth.Anonymous.signUp();
126127
}
127128

128-
await wait(3000); // the event log is async, so let's give it some time to be written to the DB
129+
// the event log is async, so let's give it some time to be written to the DB
130+
const result = await Result.retry(async () => {
131+
const response = await niceBackendFetch("/api/v1/internal/metrics", { accessType: 'admin' });
132+
if (JSON.stringify(response.body) === JSON.stringify(beforeMetrics.body)) {
133+
return Result.ok(response);
134+
}
135+
return Result.error(response);
136+
}, 5, { exponentialDelayBase: 200 });
129137

130-
const response = await niceBackendFetch("/api/v1/internal/metrics", { accessType: 'admin' });
131-
expect(beforeMetrics.body).toEqual(response.body);
138+
if (result.status === "error") {
139+
expect(beforeMetrics.body).toEqual(result.error);
140+
throw new Error("Metrics response mismatch, should never be reached");
141+
}
132142

133143
// Verify that total_users only counts the 1 regular user, not the anonymous ones
134-
expect(response.body.total_users).toBe(1);
144+
expect(result.data.body.total_users).toBe(1);
135145

136146
// Verify anonymous users don't appear in recently_registered
137-
expect(response.body.recently_registered.length).toBe(1);
138-
expect(response.body.recently_registered.every((user: any) => !user.is_anonymous)).toBe(true);
147+
expect(result.data.body.recently_registered.length).toBe(1);
148+
expect(result.data.body.recently_registered.every((user: any) => !user.is_anonymous)).toBe(true);
139149

140150
// Verify anonymous users don't appear in recently_active
141-
expect(response.body.recently_active.every((user: any) => !user.is_anonymous)).toBe(true);
151+
expect(result.data.body.recently_active.every((user: any) => !user.is_anonymous)).toBe(true);
142152

143153
// Verify anonymous users aren't counted in daily_users
144-
const lastDayUsers = response.body.daily_users[response.body.daily_users.length - 1];
154+
const lastDayUsers = result.data.body.daily_users[result.data.body.daily_users.length - 1];
145155
expect(lastDayUsers.activity).toBe(1);
146156

147157
// Verify users_by_country only includes regular users
148-
expect(response.body.users_by_country["US"]).toBe(1);
158+
expect(result.data.body.users_by_country["US"]).toBe(1);
149159

150-
await ensureAnonymousUsersAreStillExcluded(response);
160+
await ensureAnonymousUsersAreStillExcluded(result.data);
151161
});
152162

153163
it("should handle anonymous users with activity correctly", async ({ expect }) => {

0 commit comments

Comments
 (0)