insforge 1.2.10 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +20 -20
- package/.dockerignore +60 -60
- package/.env.example +83 -77
- package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
- package/.github/ISSUE_TEMPLATE/config.yml +11 -11
- package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
- package/.github/copilot-instructions.md +146 -146
- package/.github/workflows/build-image.yml +65 -65
- package/.github/workflows/ci-premerge-check.yml +23 -23
- package/.github/workflows/e2e.yml +63 -63
- package/.github/workflows/lint-and-format.yml +32 -32
- package/.prettierignore +64 -64
- package/CHANGELOG.md +44 -44
- package/CLAUDE_PLUGIN.md +104 -104
- package/CODE_OF_CONDUCT.md +128 -128
- package/CONTRIBUTING.md +125 -125
- package/Dockerfile +30 -30
- package/GITHUB_OAUTH_SETUP.md +49 -49
- package/GOOGLE_OAUTH_SETUP.md +148 -148
- package/LICENSE +201 -201
- package/README.md +182 -182
- package/assets/Dark.svg +23 -23
- package/auth/package.json +28 -28
- package/auth/src/lib/broadcastService.ts +117 -115
- package/auth/src/pages/SignInPage.tsx +60 -57
- package/auth/src/pages/SignUpPage.tsx +60 -57
- package/auth/tsconfig.json +32 -32
- package/auth/tsconfig.node.json +11 -11
- package/backend/package.json +78 -75
- package/backend/src/api/routes/ai/index.routes.ts +3 -3
- package/backend/src/api/routes/auth/index.routes.ts +667 -570
- package/backend/src/api/routes/auth/oauth.routes.ts +473 -448
- package/backend/src/api/routes/database/advance.routes.ts +37 -16
- package/backend/src/api/routes/database/index.routes.ts +78 -1
- package/backend/src/api/routes/database/records.routes.ts +10 -10
- package/backend/src/api/routes/database/tables.routes.ts +0 -14
- package/backend/src/api/routes/docs/index.routes.ts +75 -76
- package/backend/src/api/routes/email/index.routes.ts +35 -0
- package/backend/src/api/routes/functions/index.routes.ts +18 -12
- package/backend/src/api/routes/metadata/index.routes.ts +12 -0
- package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
- package/backend/src/api/routes/realtime/index.routes.ts +12 -0
- package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
- package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
- package/backend/src/api/routes/storage/index.routes.ts +18 -12
- package/backend/src/api/routes/usage/index.routes.ts +6 -4
- package/backend/src/infra/database/database.manager.ts +14 -1
- package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
- package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
- package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
- package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
- package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
- package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
- package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
- package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
- package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
- package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
- package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
- package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
- package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
- package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
- package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
- package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
- package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
- package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
- package/backend/src/infra/realtime/realtime.manager.ts +246 -0
- package/backend/src/infra/realtime/webhook-sender.ts +82 -0
- package/backend/src/infra/security/token.manager.ts +219 -125
- package/backend/src/infra/socket/socket.manager.ts +198 -64
- package/backend/src/providers/ai/openrouter.provider.ts +12 -9
- package/backend/src/providers/email/base.provider.ts +4 -7
- package/backend/src/providers/email/cloud.provider.ts +84 -0
- package/backend/src/providers/oauth/apple.provider.ts +266 -0
- package/backend/src/providers/oauth/index.ts +1 -0
- package/backend/src/server.ts +317 -284
- package/backend/src/services/ai/ai-model.service.ts +5 -5
- package/backend/src/services/ai/chat-completion.service.ts +4 -4
- package/backend/src/services/ai/image-generation.service.ts +3 -3
- package/backend/src/services/auth/auth.service.ts +14 -0
- package/backend/src/services/database/database-table.service.ts +0 -9
- package/backend/src/services/database/database.service.ts +127 -0
- package/backend/src/services/email/email.service.ts +5 -7
- package/backend/src/services/realtime/index.ts +3 -0
- package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
- package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
- package/backend/src/services/realtime/realtime-message.service.ts +260 -0
- package/backend/src/types/auth.ts +11 -0
- package/backend/src/types/realtime.ts +18 -0
- package/backend/src/types/socket.ts +7 -31
- package/backend/src/utils/cookies.ts +35 -0
- package/backend/src/utils/s3-config-loader.ts +64 -0
- package/backend/src/utils/seed.ts +301 -298
- package/backend/src/utils/sql-parser.ts +90 -0
- package/backend/tests/README.md +133 -133
- package/backend/tests/cleanup-all-test-data.sh +230 -230
- package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
- package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
- package/backend/tests/local/test-ai-config.sh +129 -129
- package/backend/tests/local/test-ai-usage.sh +80 -80
- package/backend/tests/local/test-auth-router.sh +143 -143
- package/backend/tests/local/test-database-router.sh +222 -222
- package/backend/tests/local/test-e2e.sh +240 -240
- package/backend/tests/local/test-fk-errors.sh +96 -96
- package/backend/tests/local/test-functions.sh +123 -123
- package/backend/tests/local/test-id-field.sh +200 -200
- package/backend/tests/local/test-logs.sh +132 -132
- package/backend/tests/local/test-public-bucket.sh +264 -264
- package/backend/tests/local/test-secrets.sh +249 -249
- package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
- package/backend/tests/local/test-traditional-rest.sh +208 -208
- package/backend/tests/manual/README.md +50 -50
- package/backend/tests/manual/create-large-table-simple.sql +10 -10
- package/backend/tests/manual/seed-large-table.sql +100 -100
- package/backend/tests/manual/setup-large-table-extras.sql +33 -33
- package/backend/tests/manual/test-bulk-upsert.sh +409 -409
- package/backend/tests/manual/test-database-advance.sh +296 -296
- package/backend/tests/manual/test-postgrest-stability.sh +191 -191
- package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
- package/backend/tests/manual/test-rawsql-modes.sh +244 -244
- package/backend/tests/manual/test-universal-storage.sh +263 -263
- package/backend/tests/manual/test-users.sql +17 -17
- package/backend/tests/run-all-tests.sh +139 -139
- package/backend/tests/setup.ts +0 -0
- package/backend/tests/test-config.sh +338 -338
- package/backend/tests/unit/analyze-query.test.ts +697 -0
- package/backend/tsconfig.json +22 -22
- package/claude-plugin/.claude-plugin/plugin.json +24 -24
- package/claude-plugin/README.md +133 -133
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -270
- package/docker-compose.prod.yml +204 -200
- package/docker-compose.yml +232 -228
- package/docker-init/db/db-init.sql +97 -97
- package/docker-init/db/jwt.sql +5 -5
- package/docker-init/db/postgresql.conf +16 -16
- package/docker-init/logs/vector.yml +236 -236
- package/docs/README.md +44 -44
- package/docs/agent-docs/real-time.md +269 -0
- package/docs/changelog.mdx +119 -67
- package/docs/core-concepts/ai/architecture.mdx +372 -372
- package/docs/core-concepts/ai/sdk.mdx +213 -213
- package/docs/core-concepts/authentication/architecture.mdx +278 -278
- package/docs/core-concepts/authentication/sdk.mdx +414 -414
- package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -529
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -221
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -184
- package/docs/core-concepts/authentication/ui-components/react.mdx +129 -129
- package/docs/core-concepts/database/architecture.mdx +255 -255
- package/docs/core-concepts/database/sdk.mdx +382 -382
- package/docs/core-concepts/email/architecture.mdx +101 -0
- package/docs/core-concepts/email/sdk.mdx +53 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -105
- package/docs/core-concepts/functions/sdk.mdx +184 -184
- package/docs/core-concepts/realtime/architecture.mdx +446 -0
- package/docs/core-concepts/realtime/sdk.mdx +409 -0
- package/docs/core-concepts/storage/architecture.mdx +243 -243
- package/docs/core-concepts/storage/sdk.mdx +253 -253
- package/docs/deployment/README.md +94 -94
- package/docs/deployment/deploy-to-aws-ec2.md +564 -564
- package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
- package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
- package/docs/deployment/deploy-to-render.md +441 -441
- package/docs/deprecated/insforge-auth-api.md +214 -214
- package/docs/deprecated/insforge-auth-sdk.md +99 -99
- package/docs/deprecated/insforge-db-api.md +358 -358
- package/docs/deprecated/insforge-db-sdk.md +139 -139
- package/docs/deprecated/insforge-debug-sdk.md +156 -156
- package/docs/deprecated/insforge-debug.md +64 -64
- package/docs/deprecated/insforge-instructions.md +123 -123
- package/docs/deprecated/insforge-project.md +117 -117
- package/docs/deprecated/insforge-storage-api.md +278 -278
- package/docs/deprecated/insforge-storage-sdk.md +158 -158
- package/docs/docs.json +232 -210
- package/docs/examples/framework-guides/nextjs.mdx +131 -131
- package/docs/examples/framework-guides/nuxt.mdx +165 -165
- package/docs/examples/framework-guides/react.mdx +165 -165
- package/docs/examples/framework-guides/svelte.mdx +153 -153
- package/docs/examples/framework-guides/vue.mdx +159 -159
- package/docs/examples/overview.mdx +67 -67
- package/docs/favicon.svg +19 -19
- package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
- package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
- package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
- package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
- package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
- package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
- package/docs/images/icons/ai.svg +4 -4
- package/docs/images/logos/nextjs.svg +4 -4
- package/docs/images/logos/nuxt.svg +4 -4
- package/docs/images/logos/react.svg +5 -5
- package/docs/images/logos/svelte.svg +4 -4
- package/docs/images/logos/vue.svg +5 -5
- package/docs/insforge-instructions-sdk.md +89 -88
- package/docs/introduction.mdx +45 -45
- package/docs/logo/dark.svg +22 -22
- package/docs/logo/light.svg +20 -20
- package/docs/partnership.mdx +651 -646
- package/docs/quickstart.mdx +82 -82
- package/docs/showcase.mdx +52 -52
- package/docs/snippets/sdk-installation.mdx +21 -21
- package/docs/snippets/service-icons.mdx +27 -27
- package/examples/oauth/frontend-oauth-example.html +250 -250
- package/examples/response-examples.md +443 -443
- package/frontend/components.json +17 -17
- package/frontend/package.json +69 -69
- package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
- package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
- package/frontend/src/assets/icons/checked.svg +3 -3
- package/frontend/src/assets/icons/connected.svg +3 -3
- package/frontend/src/assets/icons/error.svg +3 -3
- package/frontend/src/assets/icons/loader.svg +9 -9
- package/frontend/src/assets/icons/pencil.svg +4 -4
- package/frontend/src/assets/icons/refresh.svg +4 -4
- package/frontend/src/assets/icons/step_active.svg +3 -3
- package/frontend/src/assets/icons/step_inactive.svg +11 -11
- package/frontend/src/assets/icons/warning.svg +3 -3
- package/frontend/src/assets/logos/apple.svg +3 -3
- package/frontend/src/assets/logos/claude_code.svg +3 -3
- package/frontend/src/assets/logos/cline.svg +6 -6
- package/frontend/src/assets/logos/cursor.svg +20 -20
- package/frontend/src/assets/logos/discord.svg +8 -8
- package/frontend/src/assets/logos/facebook.svg +3 -3
- package/frontend/src/assets/logos/gemini.svg +19 -19
- package/frontend/src/assets/logos/github.svg +5 -5
- package/frontend/src/assets/logos/google.svg +13 -13
- package/frontend/src/assets/logos/grok.svg +10 -10
- package/frontend/src/assets/logos/insforge_dark.svg +15 -15
- package/frontend/src/assets/logos/insforge_light.svg +15 -15
- package/frontend/src/assets/logos/instagram.svg +1 -1
- package/frontend/src/assets/logos/linkedin.svg +3 -3
- package/frontend/src/assets/logos/openai.svg +10 -10
- package/frontend/src/assets/logos/roo_code.svg +9 -9
- package/frontend/src/assets/logos/spotify.svg +16 -16
- package/frontend/src/assets/logos/tiktok.svg +5 -5
- package/frontend/src/assets/logos/trae.svg +3 -3
- package/frontend/src/assets/logos/windsurf.svg +10 -10
- package/frontend/src/assets/logos/x.svg +3 -3
- package/frontend/src/components/layout/AppHeader.tsx +9 -10
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +6 -0
- package/frontend/src/features/auth/helpers.tsx +8 -0
- package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
- package/frontend/src/features/database/components/SQLModal.tsx +75 -0
- package/frontend/src/features/database/components/TableForm.tsx +0 -4
- package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
- package/frontend/src/features/database/hooks/useTables.ts +32 -28
- package/frontend/src/features/database/index.ts +1 -0
- package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -37
- package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +35 -47
- package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +43 -54
- package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
- package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +35 -47
- package/frontend/src/features/database/services/advance.service.ts +0 -26
- package/frontend/src/features/database/services/database.service.ts +55 -0
- package/frontend/src/features/database/services/table.service.ts +0 -6
- package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
- package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +11 -9
- package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
- package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
- package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
- package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
- package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
- package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
- package/frontend/src/features/realtime/index.ts +11 -0
- package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
- package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
- package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
- package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
- package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +3 -3
- package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +1 -35
- package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
- package/frontend/src/lib/routing/AppRoutes.tsx +35 -20
- package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
- package/frontend/src/lib/utils/menuItems.ts +24 -0
- package/frontend/src/lib/utils/utils.ts +14 -1
- package/frontend/tsconfig.json +25 -25
- package/frontend/tsconfig.node.json +9 -9
- package/functions/deno.json +24 -24
- package/functions/server.ts +315 -315
- package/i18n/README.ar.md +130 -130
- package/i18n/README.de.md +130 -130
- package/i18n/README.es.md +154 -154
- package/i18n/README.fr.md +134 -134
- package/i18n/README.hi.md +129 -129
- package/i18n/README.ja.md +174 -174
- package/i18n/README.ko.md +136 -136
- package/i18n/README.pt-BR.md +131 -131
- package/i18n/README.ru.md +129 -129
- package/i18n/README.zh-CN.md +133 -133
- package/openapi/ai.yaml +715 -715
- package/openapi/auth.yaml +1244 -1244
- package/openapi/email.yaml +158 -0
- package/openapi/functions.yaml +475 -475
- package/openapi/health.yaml +29 -29
- package/openapi/logs.yaml +223 -223
- package/openapi/metadata.yaml +177 -177
- package/openapi/realtime.yaml +699 -0
- package/openapi/records.yaml +381 -381
- package/openapi/secrets.yaml +370 -370
- package/openapi/storage.yaml +875 -875
- package/openapi/tables.yaml +463 -463
- package/package.json +97 -97
- package/shared-schemas/package.json +31 -31
- package/shared-schemas/src/ai.schema.ts +63 -59
- package/shared-schemas/src/auth-api.schema.ts +352 -339
- package/shared-schemas/src/auth.schema.ts +1 -1
- package/shared-schemas/src/database-api.schema.ts +32 -1
- package/shared-schemas/src/database.schema.ts +39 -0
- package/shared-schemas/src/docs.schema.ts +26 -0
- package/shared-schemas/src/email-api.schema.ts +30 -0
- package/shared-schemas/src/index.ts +4 -0
- package/shared-schemas/src/metadata.schema.ts +9 -0
- package/shared-schemas/src/realtime-api.schema.ts +111 -0
- package/shared-schemas/src/realtime.schema.ts +143 -0
- package/shared-schemas/tsconfig.json +21 -21
- package/tsconfig.json +7 -7
- package/zeabur/README.md +13 -13
- package/zeabur/template.yml +1032 -1032
- package/.cursor/rules/cursor-rules.mdc +0 -94
- package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
- package/test-gemini.sh +0 -35
- package/test-usage-admin.sh +0 -57
- package/test-usage.sh +0 -50
- /package/frontend/src/features/ai/{page → pages}/AIPage.tsx +0 -0
- /package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +0 -0
- /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
- /package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +0 -0
- /package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +0 -0
- /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
- /package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +0 -0
- /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
- /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
- /package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +0 -0
- /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
|
@@ -1,325 +1,325 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Fixed Test Script for InsForge Serverless Functions
|
|
4
|
-
|
|
5
|
-
# Get the directory where this script is located
|
|
6
|
-
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
7
|
-
|
|
8
|
-
# Source the test configuration
|
|
9
|
-
source "$SCRIPT_DIR/../test-config.sh"
|
|
10
|
-
|
|
11
|
-
echo "🧪 InsForge Serverless Functions Test Suite"
|
|
12
|
-
echo "========================================"
|
|
13
|
-
echo ""
|
|
14
|
-
|
|
15
|
-
# Use configuration from test-config.sh
|
|
16
|
-
API_BASE="$TEST_API_BASE"
|
|
17
|
-
# Base URL without /api prefix for function execution
|
|
18
|
-
BASE_URL="${TEST_API_BASE%/api}"
|
|
19
|
-
|
|
20
|
-
# Helper function for section headers
|
|
21
|
-
function section() {
|
|
22
|
-
echo -e "\n${BLUE}▶ $1${NC}"
|
|
23
|
-
echo "----------------------------------------"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
# Start tests
|
|
27
|
-
section "1. Authentication"
|
|
28
|
-
|
|
29
|
-
TOKEN=$(get_admin_token)
|
|
30
|
-
|
|
31
|
-
if [ -n "$TOKEN" ]; then
|
|
32
|
-
print_success "Admin login"
|
|
33
|
-
else
|
|
34
|
-
print_fail "Admin login - Could not obtain admin token"
|
|
35
|
-
exit 1
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
section "2. Function CRUD Operations"
|
|
39
|
-
|
|
40
|
-
# Use unique names with timestamp
|
|
41
|
-
TIMESTAMP=$(date +%s)
|
|
42
|
-
FUNC_NAME="test-func-$TIMESTAMP"
|
|
43
|
-
FUNC_SLUG="test-func-$TIMESTAMP" # slug matches name
|
|
44
|
-
|
|
45
|
-
# Create function
|
|
46
|
-
CREATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
47
|
-
-H "Content-Type: application/json" \
|
|
48
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
49
|
-
-d "{
|
|
50
|
-
\"name\": \"$FUNC_NAME\",
|
|
51
|
-
\"slug\": \"$FUNC_SLUG\",
|
|
52
|
-
\"code\": \"module.exports = async function(req) { return new Response('Hello World'); }\",
|
|
53
|
-
\"status\": \"active\"
|
|
54
|
-
}")
|
|
55
|
-
|
|
56
|
-
HTTP_CODE=$(echo "$CREATE_RESPONSE" | tail -n1)
|
|
57
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
58
|
-
print_success "Create function"
|
|
59
|
-
else
|
|
60
|
-
print_fail "Create function - Status: $HTTP_CODE"
|
|
61
|
-
BODY=$(echo "$CREATE_RESPONSE" | sed '$d')
|
|
62
|
-
echo " Response: $BODY"
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
# Get function
|
|
66
|
-
GET_RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions/$FUNC_SLUG" \
|
|
67
|
-
-H "Authorization: Bearer $TOKEN")
|
|
68
|
-
|
|
69
|
-
HTTP_CODE=$(echo "$GET_RESPONSE" | tail -n1)
|
|
70
|
-
BODY=$(echo "$GET_RESPONSE" | sed '$d')
|
|
71
|
-
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q '"code"'; then
|
|
72
|
-
print_success "Get function"
|
|
73
|
-
else
|
|
74
|
-
print_fail "Get function - Status: $HTTP_CODE"
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
# Update function
|
|
78
|
-
UPDATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT "$API_BASE/functions/$FUNC_SLUG" \
|
|
79
|
-
-H "Content-Type: application/json" \
|
|
80
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
81
|
-
-d '{"code": "module.exports = async function(req) { return new Response(\"Updated!\"); }"}')
|
|
82
|
-
|
|
83
|
-
HTTP_CODE=$(echo "$UPDATE_RESPONSE" | tail -n1)
|
|
84
|
-
if [ "$HTTP_CODE" = "200" ]; then
|
|
85
|
-
print_success "Update function"
|
|
86
|
-
else
|
|
87
|
-
print_fail "Update function - Status: $HTTP_CODE"
|
|
88
|
-
fi
|
|
89
|
-
|
|
90
|
-
# List functions
|
|
91
|
-
LIST_RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions" \
|
|
92
|
-
-H "Authorization: Bearer $TOKEN")
|
|
93
|
-
|
|
94
|
-
HTTP_CODE=$(echo "$LIST_RESPONSE" | tail -n1)
|
|
95
|
-
BODY=$(echo "$LIST_RESPONSE" | sed '$d')
|
|
96
|
-
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "$FUNC_SLUG"; then
|
|
97
|
-
print_success "List functions"
|
|
98
|
-
else
|
|
99
|
-
print_fail "List functions - Status: $HTTP_CODE or missing function"
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
section "3. Function Execution"
|
|
103
|
-
|
|
104
|
-
# Execute updated function
|
|
105
|
-
EXEC_RESPONSE=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FUNC_SLUG")
|
|
106
|
-
HTTP_CODE=$(echo "$EXEC_RESPONSE" | tail -n1)
|
|
107
|
-
BODY=$(echo "$EXEC_RESPONSE" | sed '$d')
|
|
108
|
-
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "Updated!"; then
|
|
109
|
-
print_success "Execute function"
|
|
110
|
-
else
|
|
111
|
-
print_fail "Execute function - Status: $HTTP_CODE, Body: $BODY"
|
|
112
|
-
fi
|
|
113
|
-
|
|
114
|
-
# Create POST function
|
|
115
|
-
POST_FUNC="post-func-$TIMESTAMP"
|
|
116
|
-
POST_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
117
|
-
-H "Content-Type: application/json" \
|
|
118
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
119
|
-
-d "{
|
|
120
|
-
\"name\": \"$POST_FUNC\",
|
|
121
|
-
\"slug\": \"$POST_FUNC\",
|
|
122
|
-
\"code\": \"module.exports = async function(req) { if (req.method !== 'POST') return new Response('Method Not Allowed', { status: 405 }); const data = await req.json(); return new Response(JSON.stringify({ result: data.value * 2 }), { headers: { 'Content-Type': 'application/json' } }); }\",
|
|
123
|
-
\"status\": \"active\"
|
|
124
|
-
}")
|
|
125
|
-
|
|
126
|
-
HTTP_CODE=$(echo "$POST_CREATE" | tail -n1)
|
|
127
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
128
|
-
print_success "Create POST function"
|
|
129
|
-
else
|
|
130
|
-
print_fail "Create POST function - Status: $HTTP_CODE"
|
|
131
|
-
fi
|
|
132
|
-
|
|
133
|
-
# Test POST execution
|
|
134
|
-
POST_EXEC=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/functions/$POST_FUNC" \
|
|
135
|
-
-H "Content-Type: application/json" \
|
|
136
|
-
-d '{"value": 21}')
|
|
137
|
-
|
|
138
|
-
HTTP_CODE=$(echo "$POST_EXEC" | tail -n1)
|
|
139
|
-
BODY=$(echo "$POST_EXEC" | sed '$d')
|
|
140
|
-
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q '"result":42'; then
|
|
141
|
-
print_success "POST execution"
|
|
142
|
-
else
|
|
143
|
-
print_fail "POST execution - Status: $HTTP_CODE, Body: $BODY"
|
|
144
|
-
fi
|
|
145
|
-
|
|
146
|
-
section "4. Error Status Code Preservation"
|
|
147
|
-
|
|
148
|
-
# Create function that returns 403 Forbidden
|
|
149
|
-
FORBIDDEN_FUNC="forbidden-func-$TIMESTAMP"
|
|
150
|
-
FORBIDDEN_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
151
|
-
-H "Content-Type: application/json" \
|
|
152
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
153
|
-
-d "{
|
|
154
|
-
\"name\": \"$FORBIDDEN_FUNC\",
|
|
155
|
-
\"slug\": \"$FORBIDDEN_FUNC\",
|
|
156
|
-
\"code\": \"module.exports = async function(req) { return new Response(JSON.stringify({ error: 'Access Forbidden' }), { status: 403, headers: { 'Content-Type': 'application/json' } }); }\",
|
|
157
|
-
\"status\": \"active\"
|
|
158
|
-
}")
|
|
159
|
-
|
|
160
|
-
HTTP_CODE=$(echo "$FORBIDDEN_CREATE" | tail -n1)
|
|
161
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
162
|
-
# Test execution returns 403
|
|
163
|
-
EXEC_403=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FORBIDDEN_FUNC")
|
|
164
|
-
HTTP_CODE=$(echo "$EXEC_403" | tail -n1)
|
|
165
|
-
BODY=$(echo "$EXEC_403" | sed '$d')
|
|
166
|
-
if [ "$HTTP_CODE" = "403" ] && echo "$BODY" | grep -q "Access Forbidden"; then
|
|
167
|
-
print_success "403 status preserved"
|
|
168
|
-
else
|
|
169
|
-
print_fail "403 status preserved - Expected 403, got $HTTP_CODE"
|
|
170
|
-
fi
|
|
171
|
-
else
|
|
172
|
-
print_fail "Create 403 function - Status: $HTTP_CODE"
|
|
173
|
-
fi
|
|
174
|
-
|
|
175
|
-
# Create function that throws 401 Unauthorized
|
|
176
|
-
UNAUTH_FUNC="unauth-func-$TIMESTAMP"
|
|
177
|
-
UNAUTH_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
178
|
-
-H "Content-Type: application/json" \
|
|
179
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
180
|
-
-d "{
|
|
181
|
-
\"name\": \"$UNAUTH_FUNC\",
|
|
182
|
-
\"slug\": \"$UNAUTH_FUNC\",
|
|
183
|
-
\"code\": \"module.exports = async function(req) { throw new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401, headers: { 'Content-Type': 'application/json' } }); }\",
|
|
184
|
-
\"status\": \"active\"
|
|
185
|
-
}")
|
|
186
|
-
|
|
187
|
-
HTTP_CODE=$(echo "$UNAUTH_CREATE" | tail -n1)
|
|
188
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
189
|
-
# Test execution returns 401
|
|
190
|
-
EXEC_401=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$UNAUTH_FUNC")
|
|
191
|
-
HTTP_CODE=$(echo "$EXEC_401" | tail -n1)
|
|
192
|
-
BODY=$(echo "$EXEC_401" | sed '$d')
|
|
193
|
-
if [ "$HTTP_CODE" = "401" ] && echo "$BODY" | grep -q "Unauthorized"; then
|
|
194
|
-
print_success "401 status preserved (thrown)"
|
|
195
|
-
else
|
|
196
|
-
print_fail "401 status preserved (thrown) - Expected 401, got $HTTP_CODE"
|
|
197
|
-
fi
|
|
198
|
-
else
|
|
199
|
-
print_fail "Create 401 function - Status: $HTTP_CODE"
|
|
200
|
-
fi
|
|
201
|
-
|
|
202
|
-
# Create validation function that returns 400 Bad Request
|
|
203
|
-
VALIDATION_FUNC="validation-func-$TIMESTAMP"
|
|
204
|
-
VALIDATION_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
205
|
-
-H "Content-Type: application/json" \
|
|
206
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
207
|
-
-d "{
|
|
208
|
-
\"name\": \"$VALIDATION_FUNC\",
|
|
209
|
-
\"slug\": \"$VALIDATION_FUNC\",
|
|
210
|
-
\"code\": \"module.exports = async function(req) { const url = new URL(req.url); const name = url.searchParams.get('name'); if (!name) { return new Response(JSON.stringify({ error: 'Name parameter required' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } return new Response(JSON.stringify({ message: 'Hello ' + name }), { headers: { 'Content-Type': 'application/json' } }); }\",
|
|
211
|
-
\"status\": \"active\"
|
|
212
|
-
}")
|
|
213
|
-
|
|
214
|
-
HTTP_CODE=$(echo "$VALIDATION_CREATE" | tail -n1)
|
|
215
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
216
|
-
# Test execution without param returns 400
|
|
217
|
-
EXEC_400=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$VALIDATION_FUNC")
|
|
218
|
-
HTTP_CODE=$(echo "$EXEC_400" | tail -n1)
|
|
219
|
-
BODY=$(echo "$EXEC_400" | sed '$d')
|
|
220
|
-
if [ "$HTTP_CODE" = "400" ] && echo "$BODY" | grep -q "Name parameter required"; then
|
|
221
|
-
print_success "400 status preserved"
|
|
222
|
-
else
|
|
223
|
-
print_fail "400 status preserved - Expected 400, got $HTTP_CODE"
|
|
224
|
-
fi
|
|
225
|
-
|
|
226
|
-
# Test with valid param returns 200
|
|
227
|
-
EXEC_200=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$VALIDATION_FUNC?name=World")
|
|
228
|
-
HTTP_CODE=$(echo "$EXEC_200" | tail -n1)
|
|
229
|
-
BODY=$(echo "$EXEC_200" | sed '$d')
|
|
230
|
-
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "Hello World"; then
|
|
231
|
-
print_success "Validation success (200)"
|
|
232
|
-
else
|
|
233
|
-
print_fail "Validation success - Expected 200, got $HTTP_CODE"
|
|
234
|
-
fi
|
|
235
|
-
else
|
|
236
|
-
print_fail "Create validation function - Status: $HTTP_CODE"
|
|
237
|
-
fi
|
|
238
|
-
|
|
239
|
-
# Create function with real JavaScript error (should be 500)
|
|
240
|
-
ERROR_FUNC="error-func-$TIMESTAMP"
|
|
241
|
-
ERROR_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
242
|
-
-H "Content-Type: application/json" \
|
|
243
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
244
|
-
-d "{
|
|
245
|
-
\"name\": \"$ERROR_FUNC\",
|
|
246
|
-
\"slug\": \"$ERROR_FUNC\",
|
|
247
|
-
\"code\": \"module.exports = async function(req) { throw new Error('Something went wrong'); }\",
|
|
248
|
-
\"status\": \"active\"
|
|
249
|
-
}")
|
|
250
|
-
|
|
251
|
-
HTTP_CODE=$(echo "$ERROR_CREATE" | tail -n1)
|
|
252
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
253
|
-
# Test execution returns 500
|
|
254
|
-
EXEC_500=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$ERROR_FUNC")
|
|
255
|
-
HTTP_CODE=$(echo "$EXEC_500" | tail -n1)
|
|
256
|
-
BODY=$(echo "$EXEC_500" | sed '$d')
|
|
257
|
-
if [ "$HTTP_CODE" = "500" ] && echo "$BODY" | grep -q "Something went wrong"; then
|
|
258
|
-
print_success "500 for real errors"
|
|
259
|
-
else
|
|
260
|
-
print_fail "500 for real errors - Expected 500, got $HTTP_CODE"
|
|
261
|
-
fi
|
|
262
|
-
else
|
|
263
|
-
print_fail "Create error function - Status: $HTTP_CODE"
|
|
264
|
-
fi
|
|
265
|
-
|
|
266
|
-
section "5. Error Handling"
|
|
267
|
-
|
|
268
|
-
# Duplicate function
|
|
269
|
-
DUP_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
270
|
-
-H "Content-Type: application/json" \
|
|
271
|
-
-H "Authorization: Bearer $TOKEN" \
|
|
272
|
-
-d "{
|
|
273
|
-
\"name\": \"$FUNC_NAME\",
|
|
274
|
-
\"slug\": \"$FUNC_SLUG\",
|
|
275
|
-
\"code\": \"module.exports = async function(req) { return new Response('Dup'); }\"
|
|
276
|
-
}")
|
|
277
|
-
|
|
278
|
-
HTTP_CODE=$(echo "$DUP_RESPONSE" | tail -n1)
|
|
279
|
-
if [ "$HTTP_CODE" = "409" ]; then
|
|
280
|
-
print_success "Duplicate rejection"
|
|
281
|
-
else
|
|
282
|
-
print_fail "Duplicate rejection - Expected 409, got $HTTP_CODE"
|
|
283
|
-
fi
|
|
284
|
-
|
|
285
|
-
# No auth
|
|
286
|
-
NO_AUTH=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions")
|
|
287
|
-
HTTP_CODE=$(echo "$NO_AUTH" | tail -n1)
|
|
288
|
-
if [ "$HTTP_CODE" = "401" ]; then
|
|
289
|
-
print_success "Auth required"
|
|
290
|
-
else
|
|
291
|
-
print_fail "Auth required - Expected 401, got $HTTP_CODE"
|
|
292
|
-
fi
|
|
293
|
-
|
|
294
|
-
# Non-existent function
|
|
295
|
-
NOT_FOUND=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/does-not-exist-$TIMESTAMP")
|
|
296
|
-
HTTP_CODE=$(echo "$NOT_FOUND" | tail -n1)
|
|
297
|
-
if [ "$HTTP_CODE" = "404" ]; then
|
|
298
|
-
print_success "Function not found"
|
|
299
|
-
else
|
|
300
|
-
print_fail "Function not found - Expected 404, got $HTTP_CODE"
|
|
301
|
-
fi
|
|
302
|
-
|
|
303
|
-
section "6. Cleanup"
|
|
304
|
-
|
|
305
|
-
# Delete all test functions
|
|
306
|
-
for slug in "$FUNC_SLUG" "$POST_FUNC" "$FORBIDDEN_FUNC" "$UNAUTH_FUNC" "$VALIDATION_FUNC" "$ERROR_FUNC"; do
|
|
307
|
-
DELETE_RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE "$API_BASE/functions/$slug" \
|
|
308
|
-
-H "Authorization: Bearer $TOKEN")
|
|
309
|
-
|
|
310
|
-
HTTP_CODE=$(echo "$DELETE_RESPONSE" | tail -n1)
|
|
311
|
-
if [ "$HTTP_CODE" = "200" ]; then
|
|
312
|
-
echo " Deleted: $slug"
|
|
313
|
-
fi
|
|
314
|
-
done
|
|
315
|
-
|
|
316
|
-
# Verify cleanup
|
|
317
|
-
VERIFY=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FUNC_SLUG")
|
|
318
|
-
HTTP_CODE=$(echo "$VERIFY" | tail -n1)
|
|
319
|
-
if [ "$HTTP_CODE" = "404" ]; then
|
|
320
|
-
print_success "Cleanup verified"
|
|
321
|
-
else
|
|
322
|
-
print_fail "Cleanup verification - Expected 404, got $HTTP_CODE"
|
|
323
|
-
fi
|
|
324
|
-
|
|
325
|
-
# Test summary is handled by test-config.sh cleanup function
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Fixed Test Script for InsForge Serverless Functions
|
|
4
|
+
|
|
5
|
+
# Get the directory where this script is located
|
|
6
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
7
|
+
|
|
8
|
+
# Source the test configuration
|
|
9
|
+
source "$SCRIPT_DIR/../test-config.sh"
|
|
10
|
+
|
|
11
|
+
echo "🧪 InsForge Serverless Functions Test Suite"
|
|
12
|
+
echo "========================================"
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
# Use configuration from test-config.sh
|
|
16
|
+
API_BASE="$TEST_API_BASE"
|
|
17
|
+
# Base URL without /api prefix for function execution
|
|
18
|
+
BASE_URL="${TEST_API_BASE%/api}"
|
|
19
|
+
|
|
20
|
+
# Helper function for section headers
|
|
21
|
+
function section() {
|
|
22
|
+
echo -e "\n${BLUE}▶ $1${NC}"
|
|
23
|
+
echo "----------------------------------------"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Start tests
|
|
27
|
+
section "1. Authentication"
|
|
28
|
+
|
|
29
|
+
TOKEN=$(get_admin_token)
|
|
30
|
+
|
|
31
|
+
if [ -n "$TOKEN" ]; then
|
|
32
|
+
print_success "Admin login"
|
|
33
|
+
else
|
|
34
|
+
print_fail "Admin login - Could not obtain admin token"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
section "2. Function CRUD Operations"
|
|
39
|
+
|
|
40
|
+
# Use unique names with timestamp
|
|
41
|
+
TIMESTAMP=$(date +%s)
|
|
42
|
+
FUNC_NAME="test-func-$TIMESTAMP"
|
|
43
|
+
FUNC_SLUG="test-func-$TIMESTAMP" # slug matches name
|
|
44
|
+
|
|
45
|
+
# Create function
|
|
46
|
+
CREATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
47
|
+
-H "Content-Type: application/json" \
|
|
48
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
49
|
+
-d "{
|
|
50
|
+
\"name\": \"$FUNC_NAME\",
|
|
51
|
+
\"slug\": \"$FUNC_SLUG\",
|
|
52
|
+
\"code\": \"module.exports = async function(req) { return new Response('Hello World'); }\",
|
|
53
|
+
\"status\": \"active\"
|
|
54
|
+
}")
|
|
55
|
+
|
|
56
|
+
HTTP_CODE=$(echo "$CREATE_RESPONSE" | tail -n1)
|
|
57
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
58
|
+
print_success "Create function"
|
|
59
|
+
else
|
|
60
|
+
print_fail "Create function - Status: $HTTP_CODE"
|
|
61
|
+
BODY=$(echo "$CREATE_RESPONSE" | sed '$d')
|
|
62
|
+
echo " Response: $BODY"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Get function
|
|
66
|
+
GET_RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions/$FUNC_SLUG" \
|
|
67
|
+
-H "Authorization: Bearer $TOKEN")
|
|
68
|
+
|
|
69
|
+
HTTP_CODE=$(echo "$GET_RESPONSE" | tail -n1)
|
|
70
|
+
BODY=$(echo "$GET_RESPONSE" | sed '$d')
|
|
71
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q '"code"'; then
|
|
72
|
+
print_success "Get function"
|
|
73
|
+
else
|
|
74
|
+
print_fail "Get function - Status: $HTTP_CODE"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Update function
|
|
78
|
+
UPDATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT "$API_BASE/functions/$FUNC_SLUG" \
|
|
79
|
+
-H "Content-Type: application/json" \
|
|
80
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
81
|
+
-d '{"code": "module.exports = async function(req) { return new Response(\"Updated!\"); }"}')
|
|
82
|
+
|
|
83
|
+
HTTP_CODE=$(echo "$UPDATE_RESPONSE" | tail -n1)
|
|
84
|
+
if [ "$HTTP_CODE" = "200" ]; then
|
|
85
|
+
print_success "Update function"
|
|
86
|
+
else
|
|
87
|
+
print_fail "Update function - Status: $HTTP_CODE"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# List functions
|
|
91
|
+
LIST_RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions" \
|
|
92
|
+
-H "Authorization: Bearer $TOKEN")
|
|
93
|
+
|
|
94
|
+
HTTP_CODE=$(echo "$LIST_RESPONSE" | tail -n1)
|
|
95
|
+
BODY=$(echo "$LIST_RESPONSE" | sed '$d')
|
|
96
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "$FUNC_SLUG"; then
|
|
97
|
+
print_success "List functions"
|
|
98
|
+
else
|
|
99
|
+
print_fail "List functions - Status: $HTTP_CODE or missing function"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
section "3. Function Execution"
|
|
103
|
+
|
|
104
|
+
# Execute updated function
|
|
105
|
+
EXEC_RESPONSE=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FUNC_SLUG")
|
|
106
|
+
HTTP_CODE=$(echo "$EXEC_RESPONSE" | tail -n1)
|
|
107
|
+
BODY=$(echo "$EXEC_RESPONSE" | sed '$d')
|
|
108
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "Updated!"; then
|
|
109
|
+
print_success "Execute function"
|
|
110
|
+
else
|
|
111
|
+
print_fail "Execute function - Status: $HTTP_CODE, Body: $BODY"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Create POST function
|
|
115
|
+
POST_FUNC="post-func-$TIMESTAMP"
|
|
116
|
+
POST_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
117
|
+
-H "Content-Type: application/json" \
|
|
118
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
119
|
+
-d "{
|
|
120
|
+
\"name\": \"$POST_FUNC\",
|
|
121
|
+
\"slug\": \"$POST_FUNC\",
|
|
122
|
+
\"code\": \"module.exports = async function(req) { if (req.method !== 'POST') return new Response('Method Not Allowed', { status: 405 }); const data = await req.json(); return new Response(JSON.stringify({ result: data.value * 2 }), { headers: { 'Content-Type': 'application/json' } }); }\",
|
|
123
|
+
\"status\": \"active\"
|
|
124
|
+
}")
|
|
125
|
+
|
|
126
|
+
HTTP_CODE=$(echo "$POST_CREATE" | tail -n1)
|
|
127
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
128
|
+
print_success "Create POST function"
|
|
129
|
+
else
|
|
130
|
+
print_fail "Create POST function - Status: $HTTP_CODE"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Test POST execution
|
|
134
|
+
POST_EXEC=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/functions/$POST_FUNC" \
|
|
135
|
+
-H "Content-Type: application/json" \
|
|
136
|
+
-d '{"value": 21}')
|
|
137
|
+
|
|
138
|
+
HTTP_CODE=$(echo "$POST_EXEC" | tail -n1)
|
|
139
|
+
BODY=$(echo "$POST_EXEC" | sed '$d')
|
|
140
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q '"result":42'; then
|
|
141
|
+
print_success "POST execution"
|
|
142
|
+
else
|
|
143
|
+
print_fail "POST execution - Status: $HTTP_CODE, Body: $BODY"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
section "4. Error Status Code Preservation"
|
|
147
|
+
|
|
148
|
+
# Create function that returns 403 Forbidden
|
|
149
|
+
FORBIDDEN_FUNC="forbidden-func-$TIMESTAMP"
|
|
150
|
+
FORBIDDEN_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
151
|
+
-H "Content-Type: application/json" \
|
|
152
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
153
|
+
-d "{
|
|
154
|
+
\"name\": \"$FORBIDDEN_FUNC\",
|
|
155
|
+
\"slug\": \"$FORBIDDEN_FUNC\",
|
|
156
|
+
\"code\": \"module.exports = async function(req) { return new Response(JSON.stringify({ error: 'Access Forbidden' }), { status: 403, headers: { 'Content-Type': 'application/json' } }); }\",
|
|
157
|
+
\"status\": \"active\"
|
|
158
|
+
}")
|
|
159
|
+
|
|
160
|
+
HTTP_CODE=$(echo "$FORBIDDEN_CREATE" | tail -n1)
|
|
161
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
162
|
+
# Test execution returns 403
|
|
163
|
+
EXEC_403=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FORBIDDEN_FUNC")
|
|
164
|
+
HTTP_CODE=$(echo "$EXEC_403" | tail -n1)
|
|
165
|
+
BODY=$(echo "$EXEC_403" | sed '$d')
|
|
166
|
+
if [ "$HTTP_CODE" = "403" ] && echo "$BODY" | grep -q "Access Forbidden"; then
|
|
167
|
+
print_success "403 status preserved"
|
|
168
|
+
else
|
|
169
|
+
print_fail "403 status preserved - Expected 403, got $HTTP_CODE"
|
|
170
|
+
fi
|
|
171
|
+
else
|
|
172
|
+
print_fail "Create 403 function - Status: $HTTP_CODE"
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Create function that throws 401 Unauthorized
|
|
176
|
+
UNAUTH_FUNC="unauth-func-$TIMESTAMP"
|
|
177
|
+
UNAUTH_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
178
|
+
-H "Content-Type: application/json" \
|
|
179
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
180
|
+
-d "{
|
|
181
|
+
\"name\": \"$UNAUTH_FUNC\",
|
|
182
|
+
\"slug\": \"$UNAUTH_FUNC\",
|
|
183
|
+
\"code\": \"module.exports = async function(req) { throw new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401, headers: { 'Content-Type': 'application/json' } }); }\",
|
|
184
|
+
\"status\": \"active\"
|
|
185
|
+
}")
|
|
186
|
+
|
|
187
|
+
HTTP_CODE=$(echo "$UNAUTH_CREATE" | tail -n1)
|
|
188
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
189
|
+
# Test execution returns 401
|
|
190
|
+
EXEC_401=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$UNAUTH_FUNC")
|
|
191
|
+
HTTP_CODE=$(echo "$EXEC_401" | tail -n1)
|
|
192
|
+
BODY=$(echo "$EXEC_401" | sed '$d')
|
|
193
|
+
if [ "$HTTP_CODE" = "401" ] && echo "$BODY" | grep -q "Unauthorized"; then
|
|
194
|
+
print_success "401 status preserved (thrown)"
|
|
195
|
+
else
|
|
196
|
+
print_fail "401 status preserved (thrown) - Expected 401, got $HTTP_CODE"
|
|
197
|
+
fi
|
|
198
|
+
else
|
|
199
|
+
print_fail "Create 401 function - Status: $HTTP_CODE"
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
# Create validation function that returns 400 Bad Request
|
|
203
|
+
VALIDATION_FUNC="validation-func-$TIMESTAMP"
|
|
204
|
+
VALIDATION_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
205
|
+
-H "Content-Type: application/json" \
|
|
206
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
207
|
+
-d "{
|
|
208
|
+
\"name\": \"$VALIDATION_FUNC\",
|
|
209
|
+
\"slug\": \"$VALIDATION_FUNC\",
|
|
210
|
+
\"code\": \"module.exports = async function(req) { const url = new URL(req.url); const name = url.searchParams.get('name'); if (!name) { return new Response(JSON.stringify({ error: 'Name parameter required' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } return new Response(JSON.stringify({ message: 'Hello ' + name }), { headers: { 'Content-Type': 'application/json' } }); }\",
|
|
211
|
+
\"status\": \"active\"
|
|
212
|
+
}")
|
|
213
|
+
|
|
214
|
+
HTTP_CODE=$(echo "$VALIDATION_CREATE" | tail -n1)
|
|
215
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
216
|
+
# Test execution without param returns 400
|
|
217
|
+
EXEC_400=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$VALIDATION_FUNC")
|
|
218
|
+
HTTP_CODE=$(echo "$EXEC_400" | tail -n1)
|
|
219
|
+
BODY=$(echo "$EXEC_400" | sed '$d')
|
|
220
|
+
if [ "$HTTP_CODE" = "400" ] && echo "$BODY" | grep -q "Name parameter required"; then
|
|
221
|
+
print_success "400 status preserved"
|
|
222
|
+
else
|
|
223
|
+
print_fail "400 status preserved - Expected 400, got $HTTP_CODE"
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
# Test with valid param returns 200
|
|
227
|
+
EXEC_200=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$VALIDATION_FUNC?name=World")
|
|
228
|
+
HTTP_CODE=$(echo "$EXEC_200" | tail -n1)
|
|
229
|
+
BODY=$(echo "$EXEC_200" | sed '$d')
|
|
230
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "Hello World"; then
|
|
231
|
+
print_success "Validation success (200)"
|
|
232
|
+
else
|
|
233
|
+
print_fail "Validation success - Expected 200, got $HTTP_CODE"
|
|
234
|
+
fi
|
|
235
|
+
else
|
|
236
|
+
print_fail "Create validation function - Status: $HTTP_CODE"
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
# Create function with real JavaScript error (should be 500)
|
|
240
|
+
ERROR_FUNC="error-func-$TIMESTAMP"
|
|
241
|
+
ERROR_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
242
|
+
-H "Content-Type: application/json" \
|
|
243
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
244
|
+
-d "{
|
|
245
|
+
\"name\": \"$ERROR_FUNC\",
|
|
246
|
+
\"slug\": \"$ERROR_FUNC\",
|
|
247
|
+
\"code\": \"module.exports = async function(req) { throw new Error('Something went wrong'); }\",
|
|
248
|
+
\"status\": \"active\"
|
|
249
|
+
}")
|
|
250
|
+
|
|
251
|
+
HTTP_CODE=$(echo "$ERROR_CREATE" | tail -n1)
|
|
252
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
253
|
+
# Test execution returns 500
|
|
254
|
+
EXEC_500=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$ERROR_FUNC")
|
|
255
|
+
HTTP_CODE=$(echo "$EXEC_500" | tail -n1)
|
|
256
|
+
BODY=$(echo "$EXEC_500" | sed '$d')
|
|
257
|
+
if [ "$HTTP_CODE" = "500" ] && echo "$BODY" | grep -q "Something went wrong"; then
|
|
258
|
+
print_success "500 for real errors"
|
|
259
|
+
else
|
|
260
|
+
print_fail "500 for real errors - Expected 500, got $HTTP_CODE"
|
|
261
|
+
fi
|
|
262
|
+
else
|
|
263
|
+
print_fail "Create error function - Status: $HTTP_CODE"
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
section "5. Error Handling"
|
|
267
|
+
|
|
268
|
+
# Duplicate function
|
|
269
|
+
DUP_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
270
|
+
-H "Content-Type: application/json" \
|
|
271
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
272
|
+
-d "{
|
|
273
|
+
\"name\": \"$FUNC_NAME\",
|
|
274
|
+
\"slug\": \"$FUNC_SLUG\",
|
|
275
|
+
\"code\": \"module.exports = async function(req) { return new Response('Dup'); }\"
|
|
276
|
+
}")
|
|
277
|
+
|
|
278
|
+
HTTP_CODE=$(echo "$DUP_RESPONSE" | tail -n1)
|
|
279
|
+
if [ "$HTTP_CODE" = "409" ]; then
|
|
280
|
+
print_success "Duplicate rejection"
|
|
281
|
+
else
|
|
282
|
+
print_fail "Duplicate rejection - Expected 409, got $HTTP_CODE"
|
|
283
|
+
fi
|
|
284
|
+
|
|
285
|
+
# No auth
|
|
286
|
+
NO_AUTH=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions")
|
|
287
|
+
HTTP_CODE=$(echo "$NO_AUTH" | tail -n1)
|
|
288
|
+
if [ "$HTTP_CODE" = "401" ]; then
|
|
289
|
+
print_success "Auth required"
|
|
290
|
+
else
|
|
291
|
+
print_fail "Auth required - Expected 401, got $HTTP_CODE"
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# Non-existent function
|
|
295
|
+
NOT_FOUND=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/does-not-exist-$TIMESTAMP")
|
|
296
|
+
HTTP_CODE=$(echo "$NOT_FOUND" | tail -n1)
|
|
297
|
+
if [ "$HTTP_CODE" = "404" ]; then
|
|
298
|
+
print_success "Function not found"
|
|
299
|
+
else
|
|
300
|
+
print_fail "Function not found - Expected 404, got $HTTP_CODE"
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
section "6. Cleanup"
|
|
304
|
+
|
|
305
|
+
# Delete all test functions
|
|
306
|
+
for slug in "$FUNC_SLUG" "$POST_FUNC" "$FORBIDDEN_FUNC" "$UNAUTH_FUNC" "$VALIDATION_FUNC" "$ERROR_FUNC"; do
|
|
307
|
+
DELETE_RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE "$API_BASE/functions/$slug" \
|
|
308
|
+
-H "Authorization: Bearer $TOKEN")
|
|
309
|
+
|
|
310
|
+
HTTP_CODE=$(echo "$DELETE_RESPONSE" | tail -n1)
|
|
311
|
+
if [ "$HTTP_CODE" = "200" ]; then
|
|
312
|
+
echo " Deleted: $slug"
|
|
313
|
+
fi
|
|
314
|
+
done
|
|
315
|
+
|
|
316
|
+
# Verify cleanup
|
|
317
|
+
VERIFY=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FUNC_SLUG")
|
|
318
|
+
HTTP_CODE=$(echo "$VERIFY" | tail -n1)
|
|
319
|
+
if [ "$HTTP_CODE" = "404" ]; then
|
|
320
|
+
print_success "Cleanup verified"
|
|
321
|
+
else
|
|
322
|
+
print_fail "Cleanup verification - Expected 404, got $HTTP_CODE"
|
|
323
|
+
fi
|
|
324
|
+
|
|
325
|
+
# Test summary is handled by test-config.sh cleanup function
|