|
| 1 | +/** |
| 2 | + * The executor hands a tool `{ ...rawInputs, ...blockParams }`, so a subBlock value the |
| 3 | + * block mapper leaves unassigned reaches the tool raw. These cases keep stored values |
| 4 | + * from another operation, and empty table rows, out of requests. |
| 5 | + */ |
| 6 | +import { describe, expect, it } from 'vitest' |
| 7 | +import { awsCloudformationCreateChangeSetContract } from '@/lib/api/contracts/tools/aws/cloudformation-create-change-set' |
| 8 | +import { awsDynamodbScanContract } from '@/lib/api/contracts/tools/aws/dynamodb-scan' |
| 9 | +import { awsIamCreateUserContract } from '@/lib/api/contracts/tools/aws/iam-create-user' |
| 10 | +import { awsSesSendTemplatedEmailContract } from '@/lib/api/contracts/tools/aws/ses-send-templated-email' |
| 11 | +import { CloudFormationBlock } from '@/blocks/blocks/cloudformation' |
| 12 | +import { DynamoDBBlock } from '@/blocks/blocks/dynamodb' |
| 13 | +import { IAMBlock } from '@/blocks/blocks/iam' |
| 14 | +import { SESBlock } from '@/blocks/blocks/ses' |
| 15 | +import type { BlockConfig } from '@/blocks/types' |
| 16 | +import { createChangeSetTool } from '@/tools/cloudformation/create_change_set' |
| 17 | +import { scanTool } from '@/tools/dynamodb/scan' |
| 18 | +import { createUserTool } from '@/tools/iam/create_user' |
| 19 | +import { sendTemplatedEmailTool } from '@/tools/ses/send_templated_email' |
| 20 | + |
| 21 | +const AWS = { region: 'us-east-1', accessKeyId: 'AKIAEXAMPLE', secretAccessKey: 'secret' } |
| 22 | + |
| 23 | +function executorParams(block: BlockConfig, inputs: Record<string, unknown>) { |
| 24 | + const mapped = block.tools.config?.params?.(inputs) ?? {} |
| 25 | + return { ...inputs, ...mapped } as Record<string, unknown> |
| 26 | +} |
| 27 | + |
| 28 | +describe('AWS blocks keep stale subBlock values out of tool input', () => { |
| 29 | + it('scan ignores the get consistentRead and query indexName values', () => { |
| 30 | + const params = executorParams(DynamoDBBlock, { |
| 31 | + ...AWS, |
| 32 | + operation: 'scan', |
| 33 | + tableName: 'orders', |
| 34 | + consistentRead: 'false', |
| 35 | + indexName: 'by-customer', |
| 36 | + }) |
| 37 | + const body = scanTool.operation.input(params as never) as Record<string, unknown> |
| 38 | + expect(body.indexName).toBeUndefined() |
| 39 | + expect(awsDynamodbScanContract.body?.safeParse(body).success).toBe(true) |
| 40 | + }) |
| 41 | + |
| 42 | + it('templated send ignores the send_email Reply-To', () => { |
| 43 | + const params = executorParams(SESBlock, { |
| 44 | + ...AWS, |
| 45 | + operation: 'send_templated_email', |
| 46 | + fromAddress: 'from@example.com', |
| 47 | + toAddresses: 'to@example.com', |
| 48 | + templateName: 'welcome', |
| 49 | + templateData: '{}', |
| 50 | + replyToAddresses: 'stale@example.com', |
| 51 | + }) |
| 52 | + const body = sendTemplatedEmailTool.operation.input(params as never) as Record<string, unknown> |
| 53 | + expect(body.replyToAddresses).toBeUndefined() |
| 54 | + expect(awsSesSendTemplatedEmailContract.body?.safeParse(body).success).toBe(true) |
| 55 | + }) |
| 56 | + |
| 57 | + it('create change set ignores the stack tags', () => { |
| 58 | + const params = executorParams(CloudFormationBlock, { |
| 59 | + awsRegion: 'us-east-1', |
| 60 | + awsAccessKeyId: 'AKIAEXAMPLE', |
| 61 | + awsSecretAccessKey: 'secret', |
| 62 | + operation: 'create_change_set', |
| 63 | + stackName: 'app', |
| 64 | + changeSetName: 'cs-1', |
| 65 | + templateBody: '{}', |
| 66 | + tags: '[{"key":"team","value":"old"}]', |
| 67 | + }) |
| 68 | + const body = createChangeSetTool.operation.input(params as never) as Record<string, unknown> |
| 69 | + expect(body.tags).toBeUndefined() |
| 70 | + expect(awsCloudformationCreateChangeSetContract.body?.safeParse(body).success).toBe(true) |
| 71 | + }) |
| 72 | + |
| 73 | + it('create user accepts an untouched Tags table', () => { |
| 74 | + const params = executorParams(IAMBlock, { |
| 75 | + ...AWS, |
| 76 | + operation: 'create_user', |
| 77 | + userName: 'alice', |
| 78 | + tags: [{ id: 'row-1', cells: { key: '', value: '' } }], |
| 79 | + }) |
| 80 | + const body = createUserTool.operation.input(params as never) |
| 81 | + expect(awsIamCreateUserContract.body?.safeParse(body).success).toBe(true) |
| 82 | + }) |
| 83 | +}) |
0 commit comments