|
1 | 1 | import { it, expect, describe } from "vitest" |
2 | | -import { applyBaseUrl, isValidEndpointUrl } from "./query" |
3 | | - |
| 2 | +import { applyBaseUrl } from "@budibase/shared-core" |
| 3 | +import { |
| 4 | + isValidEndpointUrl, |
| 5 | + constructFullPath, |
| 6 | + convertPathVariables, |
| 7 | + validateQuery, |
| 8 | +} from "./query" |
| 9 | + |
| 10 | +// Just a smoke test in the builder as the base functionality |
| 11 | +// is already covered |
4 | 12 | describe("applyBaseUrl", () => { |
5 | | - describe("plain URLs", () => { |
6 | | - it("replaces the origin, keeping the path", () => { |
7 | | - expect( |
8 | | - applyBaseUrl( |
9 | | - "https://old.example.com/api/users", |
10 | | - "https://new.example.com" |
11 | | - ) |
12 | | - ).toBe("https://new.example.com/api/users") |
13 | | - }) |
14 | | - |
15 | | - it("replaces the origin, keeping the query string", () => { |
16 | | - expect( |
17 | | - applyBaseUrl( |
18 | | - "https://old.example.com/api/users?page=1", |
19 | | - "https://new.example.com" |
20 | | - ) |
21 | | - ).toBe("https://new.example.com/api/users?page=1") |
22 | | - }) |
23 | | - |
24 | | - it("replaces the origin, keeping path + query string + hash", () => { |
25 | | - expect( |
26 | | - applyBaseUrl( |
27 | | - "https://old.example.com/api/users?page=1#top", |
28 | | - "https://new.example.com" |
29 | | - ) |
30 | | - ).toBe("https://new.example.com/api/users?page=1#top") |
31 | | - }) |
32 | | - |
33 | | - it("drops the path when current URL is just an origin with no path", () => { |
34 | | - expect( |
35 | | - applyBaseUrl("https://old.example.com", "https://new.example.com") |
36 | | - ).toBe("https://new.example.com") |
37 | | - }) |
38 | | - |
39 | | - it("falls back to newBase when currentUrl is not a valid URL", () => { |
40 | | - expect(applyBaseUrl("not a url", "https://new.example.com")).toBe( |
41 | | - "https://new.example.com" |
42 | | - ) |
43 | | - }) |
44 | | - |
45 | | - it("falls back to newBase when currentUrl is empty", () => { |
46 | | - expect(applyBaseUrl("", "https://new.example.com")).toBe( |
| 13 | + it("replaces the origin keeping the path", () => { |
| 14 | + expect( |
| 15 | + applyBaseUrl( |
| 16 | + "https://old.example.com/api/users", |
47 | 17 | "https://new.example.com" |
48 | 18 | ) |
49 | | - }) |
50 | | - |
51 | | - it("preserves a relative path when currentUrl has no origin", () => { |
52 | | - expect(applyBaseUrl("/api/v1/users", "https://new.example.com")).toBe( |
53 | | - "https://new.example.com/api/v1/users" |
54 | | - ) |
55 | | - }) |
56 | | - |
57 | | - it("strips a trailing slash from newBase to avoid double slashes", () => { |
58 | | - expect( |
59 | | - applyBaseUrl( |
60 | | - "https://old.example.com/api/users", |
61 | | - "https://new.example.com/" |
62 | | - ) |
63 | | - ).toBe("https://new.example.com/api/users") |
64 | | - }) |
65 | | - |
66 | | - it("strips trailing slash from newBase when preserving a relative path", () => { |
67 | | - expect(applyBaseUrl("/api/v1/users", "https://new.example.com/")).toBe( |
68 | | - "https://new.example.com/api/v1/users" |
69 | | - ) |
70 | | - }) |
71 | | - }) |
72 | | - |
73 | | - describe("HBS template URLs", () => { |
74 | | - it("preserves HBS blocks in the path", () => { |
75 | | - expect( |
76 | | - applyBaseUrl( |
77 | | - "https://old.example.com/api/{{version}}/users", |
78 | | - "https://new.example.com" |
79 | | - ) |
80 | | - ).toBe("https://new.example.com/api/{{version}}/users") |
81 | | - }) |
82 | | - |
83 | | - it("preserves HBS blocks in the query string", () => { |
84 | | - expect( |
85 | | - applyBaseUrl( |
86 | | - "https://old.example.com/api/users?token={{auth.token}}", |
87 | | - "https://new.example.com" |
88 | | - ) |
89 | | - ).toBe("https://new.example.com/api/users?token={{auth.token}}") |
90 | | - }) |
91 | | - |
92 | | - it("preserves an HBS block in the port position", () => { |
93 | | - expect( |
94 | | - applyBaseUrl( |
95 | | - "http://{{host}}:{{port}}/api/users", |
96 | | - "https://new.example.com" |
97 | | - ) |
98 | | - ).toBe("https://new.example.com/api/users") |
99 | | - }) |
100 | | - |
101 | | - it("preserves HBS blocks in both port and path", () => { |
102 | | - expect( |
103 | | - applyBaseUrl( |
104 | | - "http://{{host}}:{{port}}/api/{{version}}/users", |
105 | | - "https://new.example.com" |
106 | | - ) |
107 | | - ).toBe("https://new.example.com/api/{{version}}/users") |
108 | | - }) |
109 | | - |
110 | | - it("preserves multiple HBS blocks in the path", () => { |
111 | | - expect( |
112 | | - applyBaseUrl( |
113 | | - "https://old.example.com/{{org}}/{{repo}}/issues", |
114 | | - "https://new.example.com" |
115 | | - ) |
116 | | - ).toBe("https://new.example.com/{{org}}/{{repo}}/issues") |
117 | | - }) |
| 19 | + ).toBe("https://new.example.com/api/users") |
118 | 20 | }) |
119 | 21 | }) |
120 | 22 |
|
@@ -189,3 +91,59 @@ describe("isValidEndpointUrl - HBS bindings", () => { |
189 | 91 | expect(isValidEndpointUrl("{{derp")).toBe(false) |
190 | 92 | }) |
191 | 93 | }) |
| 94 | + |
| 95 | +describe("convertPathVariables", () => { |
| 96 | + it("converts OpenAPI {var} to HBS {{var}}", () => { |
| 97 | + expect(convertPathVariables("/api/{version}/users/{id}")).toBe( |
| 98 | + "/api/{{version}}/users/{{id}}" |
| 99 | + ) |
| 100 | + }) |
| 101 | + |
| 102 | + it("returns value unchanged when no path variables", () => { |
| 103 | + expect(convertPathVariables("/api/v1/users")).toBe("/api/v1/users") |
| 104 | + }) |
| 105 | +}) |
| 106 | + |
| 107 | +describe("constructFullPath", () => { |
| 108 | + it("joins base URL and endpoint path", () => { |
| 109 | + expect(constructFullPath("https://example.com", "/api/v1/users")).toBe( |
| 110 | + "https://example.com/api/v1/users" |
| 111 | + ) |
| 112 | + }) |
| 113 | + |
| 114 | + it("strips trailing slash from base", () => { |
| 115 | + expect(constructFullPath("https://example.com/", "/api/v1/users")).toBe( |
| 116 | + "https://example.com/api/v1/users" |
| 117 | + ) |
| 118 | + }) |
| 119 | + |
| 120 | + it("returns base when path is empty", () => { |
| 121 | + expect(constructFullPath("https://example.com", "")).toBe( |
| 122 | + "https://example.com" |
| 123 | + ) |
| 124 | + }) |
| 125 | + |
| 126 | + it("returns just the path when base is undefined", () => { |
| 127 | + expect(constructFullPath(undefined, "api/v1/users")).toBe("api/v1/users") |
| 128 | + }) |
| 129 | +}) |
| 130 | + |
| 131 | +describe("validateQuery", () => { |
| 132 | + it("throws when url contains {{user}} binding", () => { |
| 133 | + expect(() => |
| 134 | + validateQuery("https://example.com/{{user}}", undefined, {}, {}) |
| 135 | + ).toThrow("'user' is a protected binding") |
| 136 | + }) |
| 137 | + |
| 138 | + it("throws when request body contains {{user.id}}", () => { |
| 139 | + expect(() => |
| 140 | + validateQuery("https://example.com/api", "{{user.id}}", {}, {}) |
| 141 | + ).toThrow("'user' is a protected binding") |
| 142 | + }) |
| 143 | + |
| 144 | + it("does not throw for safe bindings", () => { |
| 145 | + expect(() => |
| 146 | + validateQuery("https://example.com/{{version}}/users", undefined, {}, {}) |
| 147 | + ).not.toThrow() |
| 148 | + }) |
| 149 | +}) |
0 commit comments