Skip to main content
Glama

mcp-google-sheets

flow.test.ts24 kB
import { WebhookRenewStrategy } from '@activepieces/pieces-framework' import { FlowOperationType, FlowStatus, FlowTriggerType, FlowVersionState, PackageType, PieceType, PopulatedFlow, PrincipalType, PropertyExecutionType, TriggerStrategy, TriggerTestStrategy, WebhookHandshakeStrategy, } from '@activepieces/shared' import { FastifyInstance } from 'fastify' import { StatusCodes } from 'http-status-codes' import { initializeDatabase } from '../../../../src/app/database' import { databaseConnection } from '../../../../src/app/database/database-connection' import { setupServer } from '../../../../src/app/server' import { generateMockToken } from '../../../helpers/auth' import { createMockFlow, createMockFlowVersion, createMockPieceMetadata, mockAndSaveBasicSetup, } from '../../../helpers/mocks' let app: FastifyInstance | null = null beforeAll(async () => { await initializeDatabase({ runMigrations: false }) app = await setupServer() }) afterAll(async () => { await databaseConnection().destroy() await app?.close() }) describe('Flow API', () => { describe('Create Flow endpoint', () => { it('Adds an empty flow', async () => { const { mockProject, mockOwner } = await mockAndSaveBasicSetup() const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id, id: mockOwner.id, }) const mockCreateFlowRequest = { displayName: 'test flow', projectId: mockProject.id, metadata: { foo: 'bar', }, } // act const response = await app?.inject({ method: 'POST', url: '/v1/flows', query: { projectId: mockProject.id, }, headers: { authorization: `Bearer ${mockToken}`, }, body: mockCreateFlowRequest, }) // assert expect(response?.statusCode).toBe(StatusCodes.CREATED) const responseBody = response?.json() expect(Object.keys(responseBody)).toHaveLength(10) expect(responseBody?.id).toHaveLength(21) expect(responseBody?.created).toBeDefined() expect(responseBody?.updated).toBeDefined() expect(responseBody?.projectId).toBe(mockProject.id) expect(responseBody?.folderId).toBeNull() expect(responseBody?.status).toBe('DISABLED') expect(responseBody?.publishedVersionId).toBeNull() expect(responseBody?.metadata).toMatchObject({ foo: 'bar' }) expect(Object.keys(responseBody?.version)).toHaveLength(13) expect(responseBody?.version?.id).toHaveLength(21) expect(responseBody?.version?.created).toBeDefined() expect(responseBody?.version?.updated).toBeDefined() expect(responseBody?.version?.updatedBy).toBeNull() expect(responseBody?.version?.flowId).toBe(responseBody?.id) expect(responseBody?.version?.displayName).toBe('test flow') expect(Object.keys(responseBody?.version?.trigger)).toHaveLength(5) expect(responseBody?.version?.trigger.type).toBe('EMPTY') expect(responseBody?.version?.trigger.name).toBe('trigger') expect(responseBody?.version?.trigger.settings).toMatchObject({}) expect(responseBody?.version?.trigger.valid).toBe(false) expect(responseBody?.version?.trigger.displayName).toBe('Select Trigger') expect(responseBody?.version?.valid).toBe(false) expect(responseBody?.version?.state).toBe('DRAFT') }) }) describe('Update status endpoint', () => { it('Enables a disabled Flow', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockPieceMetadata1 = createMockPieceMetadata({ name: '@activepieces/piece-schedule', version: '0.1.5', triggers: { 'every_hour': { 'name': 'every_hour', 'displayName': 'Every Hour', 'description': 'Triggers the current flow every hour', 'requireAuth': false, 'props': { }, 'type': TriggerStrategy.POLLING, 'sampleData': { }, 'testStrategy': TriggerTestStrategy.TEST_FUNCTION, }, }, pieceType: PieceType.OFFICIAL, packageType: PackageType.REGISTRY, }) await databaseConnection() .getRepository('piece_metadata') .save([mockPieceMetadata1]) const mockFlow = createMockFlow({ projectId: mockProject.id, status: FlowStatus.DISABLED, }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockFlowVersion = createMockFlowVersion({ flowId: mockFlow.id, updatedBy: mockOwner.id, trigger: { type: FlowTriggerType.PIECE, settings: { pieceName: '@activepieces/piece-schedule', pieceVersion: '0.1.5', input: { run_on_weekends: false, }, triggerName: 'every_hour', propertySettings: { 'run_on_weekends': { type: PropertyExecutionType.MANUAL, }, }, }, valid: true, name: 'trigger', displayName: 'Schedule', }, }) await databaseConnection() .getRepository('flow_version') .save([mockFlowVersion]) await databaseConnection().getRepository('flow').update(mockFlow.id, { publishedVersionId: mockFlowVersion.id, }) const mockToken = await generateMockToken({ type: PrincipalType.USER, platform: { id: mockPlatform.id, }, projectId: mockProject.id, id: mockOwner.id, }) // act const response = await app?.inject({ method: 'POST', url: `/v1/flows/${mockFlow.id}`, headers: { authorization: `Bearer ${mockToken}`, }, body: { type: FlowOperationType.CHANGE_STATUS, request: { status: 'ENABLED', }, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody: PopulatedFlow | undefined = response?.json() expect(responseBody).toBeDefined() if (responseBody) { expect(Object.keys(responseBody)).toHaveLength(11) expect(responseBody.id).toBe(mockFlow.id) expect(responseBody.created).toBeDefined() expect(responseBody.updated).toBeDefined() expect(responseBody.projectId).toBe(mockProject.id) expect(responseBody.folderId).toBeNull() expect(responseBody.status).toBe('ENABLED') expect(responseBody.publishedVersionId).toBe(mockFlowVersion.id) expect(responseBody.metadata).toBeNull() expect(Object.keys(responseBody.version)).toHaveLength(13) expect(responseBody.version.id).toBe(mockFlowVersion.id) } }) it('Disables an enabled Flow', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockFlow = createMockFlow({ projectId: mockProject.id, status: FlowStatus.ENABLED, }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockFlowVersion = createMockFlowVersion({ flowId: mockFlow.id, updatedBy: mockOwner.id, }) await databaseConnection() .getRepository('flow_version') .save([mockFlowVersion]) await databaseConnection().getRepository('flow').update(mockFlow.id, { publishedVersionId: mockFlowVersion.id, }) const mockToken = await generateMockToken({ type: PrincipalType.USER, platform: { id: mockPlatform.id, }, projectId: mockProject.id, id: mockOwner.id, }) const mockUpdateFlowStatusRequest = { type: FlowOperationType.CHANGE_STATUS, request: { status: 'DISABLED', }, } // act const response = await app?.inject({ method: 'POST', url: `/v1/flows/${mockFlow.id}`, headers: { authorization: `Bearer ${mockToken}`, }, body: mockUpdateFlowStatusRequest, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody = response?.json() expect(Object.keys(responseBody)).toHaveLength(10) expect(responseBody?.id).toBe(mockFlow.id) expect(responseBody?.created).toBeDefined() expect(responseBody?.updated).toBeDefined() expect(responseBody?.projectId).toBe(mockProject.id) expect(responseBody?.folderId).toBeNull() expect(responseBody?.status).toBe('DISABLED') expect(responseBody?.publishedVersionId).toBe(mockFlowVersion.id) expect(responseBody?.metadata).toBeNull() expect(Object.keys(responseBody?.version)).toHaveLength(13) expect(responseBody?.version?.id).toBe(mockFlowVersion.id) }) }) describe('Update published version id endpoint', () => { it('Publishes latest draft version', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockPieceMetadata1 = createMockPieceMetadata({ name: '@activepieces/piece-schedule', version: '0.1.5', triggers: { 'every_hour': { 'name': 'every_hour', 'displayName': 'Every Hour', 'description': 'Triggers the current flow every hour', 'requireAuth': true, 'props': { }, 'type': TriggerStrategy.WEBHOOK, 'handshakeConfiguration': { 'strategy': WebhookHandshakeStrategy.NONE, }, 'renewConfiguration': { 'strategy': WebhookRenewStrategy.NONE, }, 'sampleData': { }, 'testStrategy': TriggerTestStrategy.TEST_FUNCTION, }, }, pieceType: PieceType.OFFICIAL, packageType: PackageType.REGISTRY, }) await databaseConnection() .getRepository('piece_metadata') .save([mockPieceMetadata1]) const mockFlow = createMockFlow({ projectId: mockProject.id, status: FlowStatus.DISABLED, }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockFlowVersion = createMockFlowVersion({ flowId: mockFlow.id, updatedBy: mockOwner.id, state: FlowVersionState.DRAFT, trigger: { type: FlowTriggerType.PIECE, settings: { pieceName: '@activepieces/piece-schedule', pieceVersion: '0.1.5', input: { run_on_weekends: false, }, triggerName: 'every_hour', propertySettings: { 'run_on_weekends': { type: PropertyExecutionType.MANUAL, }, }, }, valid: true, name: 'trigger', displayName: 'Schedule', }, }) await databaseConnection() .getRepository('flow_version') .save([mockFlowVersion]) const mockToken = await generateMockToken({ id: mockOwner.id, type: PrincipalType.USER, projectId: mockProject.id, platform: { id: mockPlatform.id, }, }) // act const response = await app?.inject({ method: 'POST', url: `/v1/flows/${mockFlow.id}`, body: { type: FlowOperationType.LOCK_AND_PUBLISH, request: {}, }, headers: { authorization: `Bearer ${mockToken}`, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody: PopulatedFlow | undefined = response?.json() expect(responseBody).toBeDefined() if (responseBody) { expect(Object.keys(responseBody)).toHaveLength(11) expect(responseBody.id).toBe(mockFlow.id) expect(responseBody.created).toBeDefined() expect(responseBody.updated).toBeDefined() expect(responseBody.projectId).toBe(mockProject.id) expect(responseBody.folderId).toBeNull() expect(responseBody.status).toBe('ENABLED') expect(responseBody.publishedVersionId).toBe(mockFlowVersion.id) expect(responseBody.metadata).toBeNull() expect(Object.keys(responseBody.version)).toHaveLength(13) expect(responseBody.version.id).toBe(mockFlowVersion.id) expect(responseBody.version.state).toBe('LOCKED') expect(responseBody.triggerSource?.schedule).toBeNull() } }) }) describe('List Flows endpoint', () => { it('Filters Flows by status', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockEnabledFlow = createMockFlow({ projectId: mockProject.id, status: FlowStatus.ENABLED, }) const mockDisabledFlow = createMockFlow({ projectId: mockProject.id, status: FlowStatus.DISABLED, }) await databaseConnection() .getRepository('flow') .save([mockEnabledFlow, mockDisabledFlow]) const mockEnabledFlowVersion = createMockFlowVersion({ flowId: mockEnabledFlow.id, }) const mockDisabledFlowVersion = createMockFlowVersion({ flowId: mockDisabledFlow.id, }) await databaseConnection() .getRepository('flow_version') .save([mockEnabledFlowVersion, mockDisabledFlowVersion]) const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id, id: mockOwner.id, platform: { id: mockPlatform.id, }, }) // act const response = await app?.inject({ method: 'GET', url: '/v1/flows', query: { projectId: mockProject.id, status: 'ENABLED', }, headers: { authorization: `Bearer ${mockToken}`, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody = response?.json() expect(responseBody.data).toHaveLength(1) expect(responseBody.data[0].id).toBe(mockEnabledFlow.id) }) it('Populates Flow version', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockFlow = createMockFlow({ projectId: mockProject.id }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockFlowVersion = createMockFlowVersion({ flowId: mockFlow.id }) await databaseConnection() .getRepository('flow_version') .save([mockFlowVersion]) const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id, id: mockOwner.id, platform: { id: mockPlatform.id, }, }) // act const response = await app?.inject({ method: 'GET', url: '/v1/flows', query: { projectId: mockProject.id, }, headers: { authorization: `Bearer ${mockToken}`, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody = response?.json() expect(responseBody?.data).toHaveLength(1) expect(responseBody?.data?.[0]?.id).toBe(mockFlow.id) expect(responseBody?.data?.[0]?.version?.id).toBe(mockFlowVersion.id) }) it('Fails if a flow with no version exists', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockFlow = createMockFlow({ projectId: mockProject.id }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id, id: mockOwner.id, platform: { id: mockPlatform.id, }, }) // act const response = await app?.inject({ method: 'GET', url: '/v1/flows', query: { projectId: mockProject.id, }, headers: { authorization: `Bearer ${mockToken}`, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.NOT_FOUND) const responseBody = response?.json() expect(responseBody?.code).toBe('ENTITY_NOT_FOUND') expect(responseBody?.params?.entityType).toBe('FlowVersion') expect(responseBody?.params?.message).toBe(`flowId=${mockFlow.id}`) }) }) describe('Update Metadata endpoint', () => { it('Updates flow metadata', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() // create a flow with no metadata const mockFlow = createMockFlow({ projectId: mockProject.id }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockFlowVersion = createMockFlowVersion({ flowId: mockFlow.id }) await databaseConnection() .getRepository('flow_version') .save([mockFlowVersion]) const mockToken = await generateMockToken({ type: PrincipalType.USER, projectId: mockProject.id, id: mockOwner.id, platform: { id: mockPlatform.id, }, }) const updatedMetadata = { foo: 'bar' } // act const response = await app?.inject({ method: 'POST', url: `/v1/flows/${mockFlow.id}`, headers: { authorization: `Bearer ${mockToken}`, }, body: { type: FlowOperationType.UPDATE_METADATA, request: { metadata: updatedMetadata, }, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody = response?.json() expect(responseBody.id).toBe(mockFlow.id) expect(responseBody.metadata).toEqual(updatedMetadata) // Verify metadata was actually persisted in the database const updatedFlow = await databaseConnection() .getRepository('flow') .findOneBy({ id: mockFlow.id }) expect(updatedFlow?.metadata).toEqual(updatedMetadata) }) }) describe('Export Flow Template endpoint', () => { it('Exports a flow template using an API key', async () => { // arrange const { mockProject, mockOwner, mockPlatform } = await mockAndSaveBasicSetup() const mockFlow = createMockFlow({ projectId: mockProject.id, status: FlowStatus.ENABLED, }) await databaseConnection().getRepository('flow').save([mockFlow]) const mockFlowVersion = createMockFlowVersion({ flowId: mockFlow.id, updatedBy: mockOwner.id, }) await databaseConnection() .getRepository('flow_version') .save([mockFlowVersion]) const mockApiKey = 'test_api_key' const mockToken = await generateMockToken({ type: PrincipalType.SERVICE, projectId: mockProject.id, id: mockApiKey, platform: { id: mockPlatform.id, }, }) // act const response = await app?.inject({ method: 'GET', url: `/v1/flows/${mockFlow.id}/template`, headers: { authorization: `Bearer ${mockToken}`, }, }) // assert expect(response?.statusCode).toBe(StatusCodes.OK) const responseBody = response?.json() expect(responseBody).toHaveProperty('name') expect(responseBody).toHaveProperty('description') expect(responseBody).toHaveProperty('template') expect(responseBody.template).toHaveProperty('trigger') }) }) })

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server