Browse Source

fix: improve type safety and fix Playwright test dialog handling

**Type Safety Improvements:**
- Replace `unknown[]` with proper `SqlValue[]` type in database query methods
- Add `SqlValue` import to PlatformServiceMixin.ts for better type definitions
- Update interface definitions for `$dbGetOneRow` and `$one` methods
- Fix database row mapping to use `Array<SqlValue>` instead of `unknown[]`

**Test Reliability Fix:**
- Add backup seed modal handling to 60-new-activity.spec.ts
- Follow established dialog handling pattern from 00-noid-tests.spec.ts
- Use `waitForFunction` to detect backup seed modal appearance
- Gracefully handle modal dismissal with "No, Remind me Later" button
- Add error handling for cases where backup modal doesn't appear

**Files Changed:**
- src/utils/PlatformServiceMixin.ts: Enhanced type safety for database operations
- test-playwright/60-new-activity.spec.ts: Fixed dialog interception causing test failures

**Impact:**
- Eliminates TypeScript linting errors for database query types
- Resolves Playwright test timeout caused by backup seed modal blocking clicks
- Improves test reliability by following established dialog handling patterns
- Maintains backward compatibility while enhancing type safety

**Testing:**
- TypeScript compilation passes without errors
- Linting checks pass with improved type definitions
- Playwright test now handles backup seed modal properly
pull/188/head
Matthew Raymer 1 week ago
parent
commit
ccb1f29df4
  1. 28
      src/utils/PlatformServiceMixin.ts
  2. 16
      test-playwright/60-new-activity.spec.ts

28
src/utils/PlatformServiceMixin.ts

@ -52,7 +52,11 @@ import { logger } from "@/utils/logger";
import { Contact, ContactMaybeWithJsonStrings } from "@/db/tables/contacts"; import { Contact, ContactMaybeWithJsonStrings } from "@/db/tables/contacts";
import { Account } from "@/db/tables/accounts"; import { Account } from "@/db/tables/accounts";
import { Temp } from "@/db/tables/temp"; import { Temp } from "@/db/tables/temp";
import { QueryExecResult, DatabaseExecResult } from "@/interfaces/database"; import {
QueryExecResult,
DatabaseExecResult,
SqlValue,
} from "@/interfaces/database";
import { import {
generateInsertStatement, generateInsertStatement,
generateUpdateStatement, generateUpdateStatement,
@ -285,7 +289,7 @@ export const PlatformServiceMixin = {
return []; return [];
} }
return result.values.map((row: unknown[]) => row[0] as string); return result.values.map((row: SqlValue[]) => row[0] as string);
} catch (error) { } catch (error) {
logger.error( logger.error(
"[PlatformServiceMixin] Error getting available account DIDs:", "[PlatformServiceMixin] Error getting available account DIDs:",
@ -498,7 +502,10 @@ export const PlatformServiceMixin = {
/** /**
* Enhanced database single row query method with error handling * Enhanced database single row query method with error handling
*/ */
async $dbGetOneRow(sql: string, params?: unknown[]) { async $dbGetOneRow(
sql: string,
params?: unknown[],
): Promise<SqlValue[] | undefined> {
try { try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
return await (this as any).platformService.dbGetOneRow(sql, params); return await (this as any).platformService.dbGetOneRow(sql, params);
@ -699,7 +706,7 @@ export const PlatformServiceMixin = {
if (availableAccounts?.values?.length) { if (availableAccounts?.values?.length) {
const accountDids = availableAccounts.values.map( const accountDids = availableAccounts.values.map(
(row: unknown[]) => row[0] as string, (row: SqlValue[]) => row[0] as string,
); );
logger.debug( logger.debug(
"[PlatformServiceMixin] Available accounts for user selection:", "[PlatformServiceMixin] Available accounts for user selection:",
@ -749,7 +756,9 @@ export const PlatformServiceMixin = {
const result = await this.$dbQuery( const result = await this.$dbQuery(
"SELECT did FROM accounts ORDER BY dateCreated, did", "SELECT did FROM accounts ORDER BY dateCreated, did",
); );
return result?.values?.map((row: unknown[]) => row[0] as string) || []; return (
result?.values?.map((row: Array<SqlValue>) => row[0] as string) || []
);
}, },
/** /**
@ -856,7 +865,7 @@ export const PlatformServiceMixin = {
async $one( async $one(
sql: string, sql: string,
params: unknown[] = [], params: unknown[] = [],
): Promise<unknown[] | undefined> { ): Promise<SqlValue[] | undefined> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
return await (this as any).platformService.dbGetOneRow(sql, params); return await (this as any).platformService.dbGetOneRow(sql, params);
}, },
@ -1900,7 +1909,10 @@ export interface IPlatformServiceMixin {
params?: unknown[], params?: unknown[],
): Promise<QueryExecResult | undefined>; ): Promise<QueryExecResult | undefined>;
$dbExec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>; $dbExec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
$dbGetOneRow(sql: string, params?: unknown[]): Promise<unknown[] | undefined>; $dbGetOneRow(
sql: string,
params?: unknown[],
): Promise<SqlValue[] | undefined>;
$getMasterSettings(fallback?: Settings | null): Promise<Settings | null>; $getMasterSettings(fallback?: Settings | null): Promise<Settings | null>;
$getMergedSettings( $getMergedSettings(
defaultKey: string, defaultKey: string,
@ -2004,7 +2016,7 @@ declare module "@vue/runtime-core" {
// Ultra-concise database methods (shortest possible names) // Ultra-concise database methods (shortest possible names)
$db(sql: string, params?: unknown[]): Promise<QueryExecResult | undefined>; $db(sql: string, params?: unknown[]): Promise<QueryExecResult | undefined>;
$exec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>; $exec(sql: string, params?: unknown[]): Promise<DatabaseExecResult>;
$one(sql: string, params?: unknown[]): Promise<unknown[] | undefined>; $one(sql: string, params?: unknown[]): Promise<SqlValue[] | undefined>;
// Query + mapping combo methods // Query + mapping combo methods
$query<T = Record<string, unknown>>( $query<T = Record<string, unknown>>(

16
test-playwright/60-new-activity.spec.ts

@ -71,6 +71,22 @@ test('New offers for another user', async ({ page }) => {
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone
// Handle backup seed modal if it appears (following 00-noid-tests.spec.ts pattern)
try {
// Wait for backup seed modal to appear
await page.waitForFunction(() => {
const alert = document.querySelector('div[role="alert"]');
return alert && alert.textContent?.includes('Backup Your Identifier Seed');
}, { timeout: 3000 });
// Dismiss backup seed modal
await page.getByRole('button', { name: 'No, Remind me Later' }).click();
await expect(page.locator('div[role="alert"]').filter({ hasText: 'Backup Your Identifier Seed' })).toBeHidden();
} catch (error) {
// Backup modal might not appear, that's okay
console.log('Backup seed modal did not appear, continuing...');
}
// make another offer to user 1 // make another offer to user 1
const randomString2 = Math.random().toString(36).substring(2, 5); const randomString2 = Math.random().toString(36).substring(2, 5);
await page.getByTestId('offerButton').click(); await page.getByTestId('offerButton').click();

Loading…
Cancel
Save