package api import ( "fission-console/internal/runtime" "testing" ) func TestDecodeNodeJSWrapperSource(t *testing.T) { wrapper := []byte("const __mod = { exports: {} };\n(new Function('module', 'exports', \"module.exports = async function () { return { status: 200, body: \\\"ok\\\" }; }\"))(__mod, __mod.exports);\nconst _fn = __mod.exports;") src, ok := decodeNodeJSWrapperSource(wrapper) if !ok { t.Fatalf("decodeNodeJSWrapperSource() = false, want true") } want := "module.exports = async function () { return { status: 200, body: \"ok\" }; }" if src != want { t.Fatalf("decoded source = %q, want %q", src, want) } } func TestDecodeArchiveBytesToSourcePrefersNodeJSWrapperExtraction(t *testing.T) { wrapper := []byte("const __mod = { exports: {} };\n(new Function('module', 'exports', \"module.exports = async function () { return { status: 200, body: \\\"ok\\\" }; }\"))(__mod, __mod.exports);\nconst _fn = __mod.exports;\n\n\tasync function __invoke(ctx) {\n const fn = typeof _fn === 'function' ? _fn : (_fn.default || _fn.handler || _fn.main);\n if (!fn) throw new Error('no exported function found in user code');\n const result = await fn(ctx);\n if (!result) return { status: 200, body: '' };\n if (typeof result.status !== 'undefined') return result;\n return { status: 200, ...result };\n}\n\n\texport { __invoke as main, __invoke as handler };\n\texport default __invoke;\n") src, err := decodeArchiveBytesToSource(wrapper) if err != nil { t.Fatalf("decodeArchiveBytesToSource() error = %v", err) } want := "module.exports = async function () { return { status: 200, body: \"ok\" }; }" if src != want { t.Fatalf("decoded source = %q, want %q", src, want) } } func TestDecodeArchiveBytesToSourcePrefersNodeJSWrapperExtractionWithNewlines(t *testing.T) { wrapper := []byte("const __mod = { exports: {} };\n(new Function('module', 'exports', \"module.exports = async function (context) {\\n const value = await Promise.resolve(context?.value || 'ok');\\n return { status: 200, body: value };\\n}\"))(__mod, __mod.exports);\nconst _fn = __mod.exports;\n\n\tasync function __invoke(ctx) {\n const fn = typeof _fn === 'function' ? _fn : (_fn.default || _fn.handler || _fn.main);\n if (!fn) throw new Error('no exported function found in user code');\n const result = await fn(ctx);\n if (!result) return { status: 200, body: '' };\n if (typeof result.status !== 'undefined') return result;\n return { status: 200, ...result };\n}\n\n\texport { __invoke as main, __invoke as handler };\n\texport default __invoke;\n") src, err := decodeArchiveBytesToSource(wrapper) if err != nil { t.Fatalf("decodeArchiveBytesToSource() error = %v", err) } want := "module.exports = async function (context) {\n const value = await Promise.resolve(context?.value || 'ok');\n return { status: 200, body: value };\n}" if src != want { t.Fatalf("decoded source = %q, want %q", src, want) } } func TestDecodeArchiveBytesToSourceKeepsPythonMultilineSource(t *testing.T) { src := "def main(context):\n value = context.get('value', 'ok')\n return {'status': 200, 'body': value}\n" got, err := decodeArchiveBytesToSource([]byte(src)) if err != nil { t.Fatalf("decodeArchiveBytesToSource() error = %v", err) } if got != src { t.Fatalf("decoded source = %q, want %q", got, src) } } func TestDecodeArchiveBytesToSourceUnwrapsNodeJSZipPayload(t *testing.T) { zipBytes, err := runtime.BuildJSDeployZip(`module.exports = async function (context) { return { status: 200, body: context?.value || "ok" }; }`) if err != nil { t.Fatalf("runtime.BuildJSDeployZip() error = %v", err) } got, err := decodeArchiveBytesToSource(zipBytes) if err != nil { t.Fatalf("decodeArchiveBytesToSource() error = %v", err) } want := `module.exports = async function (context) { return { status: 200, body: context?.value || "ok" }; }` if got != want { t.Fatalf("decoded source = %q, want %q", got, want) } } func TestDecodeArchiveBytesToSourceKeepsRubyMultilineSource(t *testing.T) { src := "def handler(context)\n value = context[:value] || 'ok'\n { status: 200, body: value }\nend\n" got, err := decodeArchiveBytesToSource([]byte(src)) if err != nil { t.Fatalf("decodeArchiveBytesToSource() error = %v", err) } if got != src { t.Fatalf("decoded source = %q, want %q", got, src) } } func TestDecodeArchiveBytesToSourceKeepsPHPMultilineSource(t *testing.T) { src := " 200, 'body' => $value];\n}\n" got, err := decodeArchiveBytesToSource([]byte(src)) if err != nil { t.Fatalf("decodeArchiveBytesToSource() error = %v", err) } if got != src { t.Fatalf("decoded source = %q, want %q", got, src) } }