Stage 17 #2 fix: connection failures show only the spinner, never a toast
A dropped/reset/timed-out connection can surface as a Connect code other than Unavailable (Canceled/DeadlineExceeded/Unknown/…) which fell through to the generic 'internal' -> a red 'something went wrong' toast appeared alongside the Connecting spinner. Now toGatewayError (moved to the pure retry.ts, unit-tested) collapses every transport-level code to 'unavailable' so it is retried + flips offline; and handleError suppresses the toast for any connection code AND whenever the app is mid-reconnect (!connection.online), covering the race where a unary error lands before the stream reports the drop. Genuine server-internal / domain errors still toast while online.
This commit is contained in:
@@ -1,5 +1,27 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { backoffMs, isConnectionCode, retryable } from './retry';
|
||||
import { Code, ConnectError } from '@connectrpc/connect';
|
||||
import { backoffMs, isConnectionCode, retryable, toGatewayError } from './retry';
|
||||
|
||||
describe('toGatewayError', () => {
|
||||
it('collapses every transport-level failure to a connection code (so it is retried + suppressed)', () => {
|
||||
for (const c of [Code.Unavailable, Code.DeadlineExceeded, Code.Canceled, Code.Aborted, Code.Unknown]) {
|
||||
const e = toGatewayError(new ConnectError('x', c));
|
||||
expect(e.code).toBe('unavailable');
|
||||
expect(isConnectionCode(e.code)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('treats a raw (non-Connect) network error as a connection failure', () => {
|
||||
expect(toGatewayError(new TypeError('Failed to fetch')).code).toBe('unavailable');
|
||||
});
|
||||
|
||||
it('preserves rate-limit, an invalid session, and a genuine server-internal error', () => {
|
||||
expect(toGatewayError(new ConnectError('x', Code.ResourceExhausted)).code).toBe('rate_limited');
|
||||
expect(toGatewayError(new ConnectError('x', Code.Unauthenticated)).code).toBe('session_invalid');
|
||||
expect(toGatewayError(new ConnectError('x', Code.Internal)).code).toBe('internal');
|
||||
expect(isConnectionCode('internal')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('retryable', () => {
|
||||
it('retries any op on a rate-limit rejection (it never reached the backend)', () => {
|
||||
|
||||
Reference in New Issue
Block a user