mirror of https://github.com/buster-so/buster.git
fix some broken unit tests
This commit is contained in:
parent
cb58b5034e
commit
c49bdd2426
|
@ -12,6 +12,7 @@
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"typecheck:watch": "tsc --noEmit --watch",
|
"typecheck:watch": "tsc --noEmit --watch",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
|
"test:unit": "pnpm run test",
|
||||||
"test:watch": "vitest --watch",
|
"test:watch": "vitest --watch",
|
||||||
"test:ui": "vitest --ui",
|
"test:ui": "vitest --ui",
|
||||||
"test:coverage": "vitest --coverage",
|
"test:coverage": "vitest --coverage",
|
||||||
|
|
|
@ -91,7 +91,7 @@ describe('Chat Query Hooks', () => {
|
||||||
expect(requests.getListChats).toHaveBeenCalledWith({
|
expect(requests.getListChats).toHaveBeenCalledWith({
|
||||||
admin_view: false,
|
admin_view: false,
|
||||||
page_token: 0,
|
page_token: 0,
|
||||||
page_size: 3500,
|
page_size: 5000,
|
||||||
search: 'test'
|
search: 'test'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,10 +9,10 @@ import type { UseSupabaseUserContextType } from '@/lib/supabase';
|
||||||
import { timeout } from '@/lib/timeout';
|
import { timeout } from '@/lib/timeout';
|
||||||
import { useBusterNotifications } from '../BusterNotifications';
|
import { useBusterNotifications } from '../BusterNotifications';
|
||||||
import { flushSync } from 'react-dom';
|
import { flushSync } from 'react-dom';
|
||||||
import { createClient } from '@/lib/supabase/client';
|
import { createBrowserClient } from '@/lib/supabase/client';
|
||||||
|
|
||||||
const PREEMTIVE_REFRESH_MINUTES = 5;
|
const PREEMTIVE_REFRESH_MINUTES = 5;
|
||||||
const supabase = createClient();
|
const supabase = createBrowserClient();
|
||||||
|
|
||||||
const useSupabaseContextInternal = ({
|
const useSupabaseContextInternal = ({
|
||||||
supabaseContext
|
supabaseContext
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { createBrowserClient } from '@supabase/ssr';
|
import { createBrowserClient as createBrowserClientSSR } from '@supabase/ssr';
|
||||||
|
|
||||||
export function createClient() {
|
export function createBrowserClient() {
|
||||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
||||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
|
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
|
||||||
|
|
||||||
if (!supabaseUrl || !supabaseAnonKey) {
|
if (!supabaseUrl || !supabaseAnonKey) {
|
||||||
throw new Error('Missing Supabase environment variables');
|
throw new Error('Missing Supabase environment variables for browser client');
|
||||||
}
|
}
|
||||||
|
|
||||||
return createBrowserClient(supabaseUrl, supabaseAnonKey);
|
return createBrowserClientSSR(supabaseUrl, supabaseAnonKey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ export async function createSupabaseServerClient() {
|
||||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
|
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
|
||||||
|
|
||||||
if (!supabaseUrl || !supabaseAnonKey) {
|
if (!supabaseUrl || !supabaseAnonKey) {
|
||||||
throw new Error('Missing Supabase environment variables');
|
throw new Error('Missing Supabase environment variables for server client');
|
||||||
}
|
}
|
||||||
|
|
||||||
const cookieStore = await cookies();
|
const cookieStore = await cookies();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { NextRequest } from 'next/server';
|
import type { NextRequest } from 'next/server';
|
||||||
import { BusterAuthRoutes } from './busterAuthRoutes';
|
import { BusterAuthRoutes } from './busterAuthRoutes';
|
||||||
import { BusterEmbedRoutes } from './busterEmbedRoutes';
|
import { BusterEmbedRoutes } from './busterEmbedRoutes';
|
||||||
import { BusterRoutes } from './busterRoutes';
|
import { BusterRoutes, type BusterRoutesWithArgsRoute } from './busterRoutes';
|
||||||
import {
|
import {
|
||||||
createBusterRoute,
|
createBusterRoute,
|
||||||
createPathnameToBusterRoute,
|
createPathnameToBusterRoute,
|
||||||
|
@ -100,6 +100,7 @@ export const getEmbedAssetToRegularAsset = (pathnameAndQueryParams: string) => {
|
||||||
|
|
||||||
if (matched) {
|
if (matched) {
|
||||||
const params = extractPathParamsFromRoute(pathnameAndQueryParams);
|
const params = extractPathParamsFromRoute(pathnameAndQueryParams);
|
||||||
return createBusterRoute({ route: matched, ...(params as any) });
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- I am just using any here because it was a pain to type this out
|
||||||
|
return createBusterRoute({ route: matched as BusterRoutes, ...(params as any) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,3 +59,24 @@ vi.mock('remark-gfm', () => ({
|
||||||
__esModule: true,
|
__esModule: true,
|
||||||
default: vi.fn()
|
default: vi.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Mock Supabase client to prevent environment variable errors in tests
|
||||||
|
vi.mock('@/lib/supabase/client', () => ({
|
||||||
|
createBrowserClient: vi.fn(() => ({
|
||||||
|
auth: {
|
||||||
|
refreshSession: vi.fn().mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
session: {
|
||||||
|
access_token: 'mock-token',
|
||||||
|
expires_at: Date.now() / 1000 + 3600 // 1 hour from now
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: null
|
||||||
|
}),
|
||||||
|
getUser: vi.fn().mockResolvedValue({
|
||||||
|
data: { user: null },
|
||||||
|
error: null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}));
|
||||||
|
|
|
@ -27,8 +27,9 @@
|
||||||
"format": "biome format ${1:-.}",
|
"format": "biome format ${1:-.}",
|
||||||
"format:fix": "biome format --write ${1:-.}",
|
"format:fix": "biome format --write ${1:-.}",
|
||||||
"lint": "turbo lint",
|
"lint": "turbo lint",
|
||||||
"new:package": "bun run scripts/new-package.ts",
|
"new:package": "tsx scripts/new-package.ts",
|
||||||
"setup": "bash scripts/setup.sh",
|
"setup": "bash scripts/setup.sh",
|
||||||
|
"test-before-pr": "turbo run test:unit build lint",
|
||||||
"test": "dotenv -e .env -- turbo test",
|
"test": "dotenv -e .env -- turbo test",
|
||||||
"test:unit": "dotenv -e .env -- turbo run test:unit",
|
"test:unit": "dotenv -e .env -- turbo run test:unit",
|
||||||
"test:integration": "dotenv -e .env -- turbo run test:integration",
|
"test:integration": "dotenv -e .env -- turbo run test:integration",
|
||||||
|
|
|
@ -371,8 +371,10 @@ const modifyDashboardFiles = wrapTraced(
|
||||||
|
|
||||||
for (const file of dashboardFilesToUpdate) {
|
for (const file of dashboardFilesToUpdate) {
|
||||||
// Get current metric IDs from updated dashboard content
|
// Get current metric IDs from updated dashboard content
|
||||||
const newMetricIds = (file.content as DashboardYml).rows.flatMap(row => row.items).map(item => item.id);
|
const newMetricIds = (file.content as DashboardYml).rows
|
||||||
|
.flatMap((row) => row.items)
|
||||||
|
.map((item) => item.id);
|
||||||
|
|
||||||
const existingAssociations = await tx
|
const existingAssociations = await tx
|
||||||
.select({ metricFileId: metricFilesToDashboardFiles.metricFileId })
|
.select({ metricFileId: metricFilesToDashboardFiles.metricFileId })
|
||||||
.from(metricFilesToDashboardFiles)
|
.from(metricFilesToDashboardFiles)
|
||||||
|
@ -383,10 +385,12 @@ const modifyDashboardFiles = wrapTraced(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
const existingMetricIds = existingAssociations.map(a => a.metricFileId);
|
const existingMetricIds = existingAssociations.map((a) => a.metricFileId);
|
||||||
|
|
||||||
const addedMetricIds = newMetricIds.filter((id: string) => !existingMetricIds.includes(id));
|
const addedMetricIds = newMetricIds.filter(
|
||||||
|
(id: string) => !existingMetricIds.includes(id)
|
||||||
|
);
|
||||||
for (const metricId of addedMetricIds) {
|
for (const metricId of addedMetricIds) {
|
||||||
await tx
|
await tx
|
||||||
.insert(metricFilesToDashboardFiles)
|
.insert(metricFilesToDashboardFiles)
|
||||||
|
@ -396,25 +400,30 @@ const modifyDashboardFiles = wrapTraced(
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
deletedAt: null,
|
deletedAt: null,
|
||||||
createdBy: userId
|
createdBy: userId,
|
||||||
})
|
})
|
||||||
.onConflictDoUpdate({
|
.onConflictDoUpdate({
|
||||||
target: [metricFilesToDashboardFiles.metricFileId, metricFilesToDashboardFiles.dashboardFileId],
|
target: [
|
||||||
|
metricFilesToDashboardFiles.metricFileId,
|
||||||
|
metricFilesToDashboardFiles.dashboardFileId,
|
||||||
|
],
|
||||||
set: {
|
set: {
|
||||||
deletedAt: null,
|
deletedAt: null,
|
||||||
updatedAt: new Date().toISOString()
|
updatedAt: new Date().toISOString(),
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
const removedMetricIds = existingMetricIds.filter((id: string) => !newMetricIds.includes(id));
|
const removedMetricIds = existingMetricIds.filter(
|
||||||
|
(id: string) => !newMetricIds.includes(id)
|
||||||
|
);
|
||||||
if (removedMetricIds.length > 0) {
|
if (removedMetricIds.length > 0) {
|
||||||
await tx
|
await tx
|
||||||
.update(metricFilesToDashboardFiles)
|
.update(metricFilesToDashboardFiles)
|
||||||
.set({
|
.set({
|
||||||
deletedAt: new Date().toISOString(),
|
deletedAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString()
|
updatedAt: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
|
|
|
@ -220,7 +220,9 @@ describe('Retry Mechanism Integration Tests', () => {
|
||||||
|
|
||||||
// The conversation should start with the original messages
|
// The conversation should start with the original messages
|
||||||
const userMessages = result.conversationHistory.filter((msg) => msg.role === 'user');
|
const userMessages = result.conversationHistory.filter((msg) => msg.role === 'user');
|
||||||
const assistantMessages = result.conversationHistory.filter((msg) => msg.role === 'assistant');
|
const assistantMessages = result.conversationHistory.filter(
|
||||||
|
(msg) => msg.role === 'assistant'
|
||||||
|
);
|
||||||
|
|
||||||
expect(userMessages.length).toBeGreaterThan(0);
|
expect(userMessages.length).toBeGreaterThan(0);
|
||||||
expect(assistantMessages.length).toBeGreaterThan(0);
|
expect(assistantMessages.length).toBeGreaterThan(0);
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
#!/usr/bin/env tsx
|
||||||
|
|
||||||
|
import { execSync } from 'node:child_process';
|
||||||
|
import { performance } from 'node:perf_hooks';
|
||||||
|
|
||||||
|
interface Step {
|
||||||
|
name: string;
|
||||||
|
command: string;
|
||||||
|
emoji: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const steps: Step[] = [
|
||||||
|
{
|
||||||
|
name: 'lint',
|
||||||
|
command: 'turbo run lint --ui=stream',
|
||||||
|
emoji: '🔍',
|
||||||
|
description: 'Running linter checks'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'build',
|
||||||
|
command: 'turbo run build --ui=stream',
|
||||||
|
emoji: '🏗️',
|
||||||
|
description: 'Building all packages'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
command: 'turbo run test',
|
||||||
|
emoji: '🧪',
|
||||||
|
description: 'Running all tests'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function formatTime(ms: number): string {
|
||||||
|
if (ms < 1000) {
|
||||||
|
return `${Math.round(ms)}ms`;
|
||||||
|
}
|
||||||
|
const seconds = ms / 1000;
|
||||||
|
if (seconds < 60) {
|
||||||
|
return `${seconds.toFixed(1)}s`;
|
||||||
|
}
|
||||||
|
const minutes = Math.floor(seconds / 60);
|
||||||
|
const remainingSeconds = Math.floor(seconds % 60);
|
||||||
|
return `${minutes}m ${remainingSeconds}s`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function runStep(step: Step, stepNumber: number, totalSteps: number): boolean {
|
||||||
|
console.log(`\n${step.emoji} [${stepNumber}/${totalSteps}] ${step.description}...`);
|
||||||
|
console.log(`📝 Command: ${step.command}`);
|
||||||
|
|
||||||
|
const startTime = performance.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
execSync(step.command, {
|
||||||
|
stdio: 'inherit',
|
||||||
|
cwd: process.cwd()
|
||||||
|
});
|
||||||
|
|
||||||
|
const endTime = performance.now();
|
||||||
|
const duration = formatTime(endTime - startTime);
|
||||||
|
|
||||||
|
console.log(`✅ ${step.name} completed successfully in ${duration}`);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
const endTime = performance.now();
|
||||||
|
const duration = formatTime(endTime - startTime);
|
||||||
|
|
||||||
|
console.log(`❌ ${step.name} failed after ${duration}`);
|
||||||
|
console.error(`💥 Error in ${step.name}:`, error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
console.log('🚀 Starting pre-PR checks...\n');
|
||||||
|
console.log('🎯 This will run: lint → build → test');
|
||||||
|
console.log('⏱️ Grab a coffee, this might take a while!\n');
|
||||||
|
console.log('═'.repeat(50));
|
||||||
|
|
||||||
|
const overallStartTime = performance.now();
|
||||||
|
let failedSteps: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < steps.length; i++) {
|
||||||
|
const step = steps[i];
|
||||||
|
const success = runStep(step, i + 1, steps.length);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
failedSteps.push(step.name);
|
||||||
|
break; // Stop on first failure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const overallEndTime = performance.now();
|
||||||
|
const totalDuration = formatTime(overallEndTime - overallStartTime);
|
||||||
|
|
||||||
|
console.log('\n' + '═'.repeat(50));
|
||||||
|
|
||||||
|
if (failedSteps.length === 0) {
|
||||||
|
console.log('🎉 All pre-PR checks passed!');
|
||||||
|
console.log('✨ Your code is ready for review!');
|
||||||
|
console.log(`⏰ Total time: ${totalDuration}`);
|
||||||
|
console.log('🚢 Safe to create that PR! 🚢');
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.log('💥 Pre-PR checks failed!');
|
||||||
|
console.log(`❌ Failed steps: ${failedSteps.join(', ')}`);
|
||||||
|
console.log(`⏰ Total time: ${totalDuration}`);
|
||||||
|
console.log('🔧 Please fix the issues above before creating a PR.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Ctrl+C gracefully
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
console.log('\n\n🛑 Pre-PR checks interrupted by user');
|
||||||
|
console.log('👋 See you next time!');
|
||||||
|
process.exit(130);
|
||||||
|
});
|
||||||
|
|
||||||
|
main();
|
Loading…
Reference in New Issue