Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
remove old tests
  • Loading branch information
icecrasher321 committed Jul 28, 2025
commit 689ca2ce470baf25035298429338cffe9d80f66c
209 changes: 0 additions & 209 deletions apps/sim/app/api/webhooks/trigger/[path]/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,219 +284,10 @@ describe('Webhook Trigger API Route', () => {
expect(text).toMatch(/not found/i) // Response should contain "not found" message
})

/**
* Test duplicate webhook request handling
* Verifies that duplicate requests are detected and not processed multiple times
*/
it('should handle duplicate webhook requests', async () => {
// Set up duplicate detection
hasProcessedMessageMock.mockResolvedValue(true) // Simulate duplicate
processGenericDeduplicationMock.mockResolvedValue(
new Response('Duplicate request', { status: 200 })
)

// Configure DB mock to return a webhook and workflow
const { db } = await import('@/db')
const limitMock = vi.fn().mockReturnValue([
{
webhook: {
id: 'webhook-id',
path: 'test-path',
isActive: true,
provider: 'generic', // Not Airtable to test standard path
workflowId: 'workflow-id',
providerConfig: {},
},
workflow: {
id: 'workflow-id',
userId: 'user-id',
},
},
])

const whereMock = vi.fn().mockReturnValue({ limit: limitMock })
const innerJoinMock = vi.fn().mockReturnValue({ where: whereMock })
const fromMock = vi.fn().mockReturnValue({ innerJoin: innerJoinMock })

// @ts-ignore - mocking the query chain
db.select.mockReturnValue({ from: fromMock })

// Create a mock request
const req = createMockRequest('POST', { event: 'test' })

// Mock the path param
const params = Promise.resolve({ path: 'test-path' })

// Import the handler after mocks are set up
const { POST } = await import('@/app/api/webhooks/trigger/[path]/route')

// Call the handler
const response = await POST(req, { params })

// Expect 200 response for duplicate
expect(response.status).toBe(200)

// Verify response text indicates duplication
const text = await response.text()
expect(text).toMatch(/duplicate|received/i) // Response might be "Duplicate message" or "Request received"
})

/**
* Test Slack-specific webhook handling
* Verifies that Slack signature verification is performed
*/
// TODO: Fix failing test - returns 500 instead of 200
// it('should handle Slack webhooks with signature verification', async () => { ... })

/**
* Test error handling during webhook execution
*/
it('should handle errors during workflow execution', async () => {
// Mock the setTimeout to be faster for testing
// @ts-ignore - Replace global setTimeout for this test
global.setTimeout = vi.fn((callback) => {
callback() // Execute immediately
return 123 // Return a timer ID
})

// Set up error handling mocks
processWebhookMock.mockImplementation(() => {
throw new Error('Webhook execution failed')
})
executeMock.mockRejectedValue(new Error('Webhook execution failed'))

// Configure DB mock to return a webhook and workflow
const { db } = await import('@/db')
const limitMock = vi.fn().mockReturnValue([
{
webhook: {
id: 'webhook-id',
path: 'test-path',
isActive: true,
provider: 'generic', // Not Airtable to ensure we use the timeout path
workflowId: 'workflow-id',
providerConfig: {},
},
workflow: {
id: 'workflow-id',
userId: 'user-id',
},
},
])

const whereMock = vi.fn().mockReturnValue({ limit: limitMock })
const innerJoinMock = vi.fn().mockReturnValue({ where: whereMock })
const fromMock = vi.fn().mockReturnValue({ innerJoin: innerJoinMock })

// @ts-ignore - mocking the query chain
db.select.mockReturnValue({ from: fromMock })

// Create a mock request
const req = createMockRequest('POST', { event: 'test' })

// Mock the path param
const params = Promise.resolve({ path: 'test-path' })

// Import the handler after mocks are set up
const { POST } = await import('@/app/api/webhooks/trigger/[path]/route')

// Call the handler
const response = await POST(req, { params })

// Verify response exists and check status code
// For non-Airtable webhooks, we expect 200 from the timeout response
expect(response).toBeDefined()
expect(response.status).toBe(200)

// Verify response text
const text = await response.text()
expect(text).toMatch(/received|processing/i)
})

/**
* Test Airtable webhook specific handling
* Verifies that Airtable webhooks use the synchronous processing path
*/
it('should handle Airtable webhooks synchronously', async () => {
// Create webhook payload for Airtable
const airtablePayload = {
base: {
id: 'appn9RltLQQMsquyL',
},
webhook: {
id: 'achpbXeBqNLsRFAnD',
},
timestamp: new Date().toISOString(),
}

// Reset fetch and process mock
fetchAndProcessAirtablePayloadsMock.mockResolvedValue(undefined)

// Configure DB mock to return an Airtable webhook
const { db } = await import('@/db')
const limitMock = vi.fn().mockReturnValue([
{
webhook: {
id: 'airtable-webhook-id',
path: 'airtable-path',
isActive: true,
provider: 'airtable', // Set provider to airtable to test that path
workflowId: 'workflow-id',
providerConfig: {
baseId: 'appn9RltLQQMsquyL',
externalId: 'achpbXeBqNLsRFAnD',
},
},
workflow: {
id: 'workflow-id',
userId: 'user-id',
},
},
])

const whereMock = vi.fn().mockReturnValue({ limit: limitMock })
const innerJoinMock = vi.fn().mockReturnValue({ where: whereMock })
const fromMock = vi.fn().mockReturnValue({ innerJoin: innerJoinMock })

// Configure db.select to return the appropriate mock for this test
// @ts-ignore - Ignore TypeScript errors for test mocks
db.select = vi.fn().mockReturnValue({ from: fromMock })

// Also mock the DB for the Airtable notification check
const whereMock2 = vi.fn().mockReturnValue({ limit: vi.fn().mockReturnValue([]) })
const fromMock2 = vi.fn().mockReturnValue({ where: whereMock2 })

// We need to handle multiple calls to db.select
let callCount = 0
// @ts-ignore - Ignore TypeScript errors for test mocks
db.select = vi.fn().mockImplementation(() => {
callCount++
if (callCount === 1) {
return { from: fromMock }
}
return { from: fromMock2 }
})

// Create a mock request with Airtable payload
const req = createMockRequest('POST', airtablePayload)

// Mock the path param
const params = Promise.resolve({ path: 'airtable-path' })

// Import the handler after mocks are set up
const { POST } = await import('@/app/api/webhooks/trigger/[path]/route')

// Call the handler
const response = await POST(req, { params })

// For Airtable we expect 200 after synchronous processing
expect(response.status).toBe(200)

// Verify that the Airtable-specific function was called
expect(fetchAndProcessAirtablePayloadsMock).toHaveBeenCalledTimes(1)

// The response should indicate success
const text = await response.text()
expect(text).toMatch(/success|processed/i)
})
})
17 changes: 3 additions & 14 deletions apps/sim/trigger/webhook-execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const webhookExecution = task({
executionId,
})

// Initialize logging session outside try block so it's available in catch
const loggingSession = new LoggingSession(payload.workflowId, executionId, 'webhook', requestId)

try {
// Check usage limits first
const usageCheck = await checkServerSideUsageLimits(payload.userId)
Expand Down Expand Up @@ -94,14 +97,6 @@ export const webhookExecution = task({
decryptedEnvVars = Object.fromEntries(decryptedPairs)
}

// Initialize logging session
const loggingSession = new LoggingSession(
payload.workflowId,
executionId,
'webhook',
requestId
)

// Start logging session
await loggingSession.safeStart({
userId: payload.userId,
Expand Down Expand Up @@ -276,12 +271,6 @@ export const webhookExecution = task({

// Complete logging session with error (matching workflow-execution pattern)
try {
const loggingSession = new LoggingSession(
payload.workflowId,
executionId,
'webhook',
requestId
)
await loggingSession.safeCompleteWithError({
endedAt: new Date().toISOString(),
totalDurationMs: 0,
Expand Down