|  | 
| 1 | 1 | import { describe, expect, it } from "vitest"; | 
| 2 |  | -import { joinPath, removeBasePath } from "./path"; | 
|  | 2 | +import { joinPath, removeBasePath, shiftBase } from "./path"; | 
| 3 | 3 | 
 | 
| 4 | 4 | describe("joinPath", () => { | 
| 5 | 5 | 	it("should join base and path with single slash", () => { | 
| @@ -119,3 +119,154 @@ describe("removeBasePath", () => { | 
| 119 | 119 | 		expect(removeBasePath("", "/foo/bar")).toBe("/foo/bar"); | 
| 120 | 120 | 	}); | 
| 121 | 121 | }); | 
|  | 122 | + | 
|  | 123 | +describe("shiftBase", () => { | 
|  | 124 | +	describe("normal usages", () => { | 
|  | 125 | +		it("should handle non-root oldBasePath and full newBaseUrl", () => { | 
|  | 126 | +			for (const oldBasePath of ["/base", "/base/"]) { | 
|  | 127 | +				for (const newBaseUrl of [ | 
|  | 128 | +					"https://typst.app/docs", | 
|  | 129 | +					"https://typst.app/docs/", | 
|  | 130 | +				]) { | 
|  | 131 | +					expect(shiftBase("/base/foo/bar/", oldBasePath, newBaseUrl)).toBe( | 
|  | 132 | +						"https://typst.app/docs/foo/bar/", | 
|  | 133 | +					); | 
|  | 134 | +					expect(shiftBase("/base/", oldBasePath, newBaseUrl)).toBe( | 
|  | 135 | +						"https://typst.app/docs/", | 
|  | 136 | +					); | 
|  | 137 | +				} | 
|  | 138 | +			} | 
|  | 139 | +		}); | 
|  | 140 | + | 
|  | 141 | +		it("should handle root oldBasePath and full newBaseUrl", () => { | 
|  | 142 | +			for (const oldBasePath of ["/", ""]) { | 
|  | 143 | +				for (const newBaseUrl of [ | 
|  | 144 | +					"https://typst.app/docs", | 
|  | 145 | +					"https://typst.app/docs/", | 
|  | 146 | +				]) { | 
|  | 147 | +					expect(shiftBase("/foo/bar/", oldBasePath, newBaseUrl)).toBe( | 
|  | 148 | +						"https://typst.app/docs/foo/bar/", | 
|  | 149 | +					); | 
|  | 150 | +					expect(shiftBase("/", oldBasePath, newBaseUrl)).toBe( | 
|  | 151 | +						"https://typst.app/docs/", | 
|  | 152 | +					); | 
|  | 153 | +				} | 
|  | 154 | +			} | 
|  | 155 | +		}); | 
|  | 156 | + | 
|  | 157 | +		it("should handle non-root oldBasePath and newBaseUrl without origin", () => { | 
|  | 158 | +			for (const oldBasePath of ["/ja-JP/docs", "/ja-JP/docs/"]) { | 
|  | 159 | +				for (const newBaseUrl of ["/en-US/docs", "/en-US/docs/"]) { | 
|  | 160 | +					expect( | 
|  | 161 | +						shiftBase("/ja-JP/docs/foo/bar/", oldBasePath, newBaseUrl), | 
|  | 162 | +					).toBe("/en-US/docs/foo/bar/"); | 
|  | 163 | +					expect(shiftBase("/ja-JP/docs/", oldBasePath, newBaseUrl)).toBe( | 
|  | 164 | +						"/en-US/docs/", | 
|  | 165 | +					); | 
|  | 166 | +				} | 
|  | 167 | +			} | 
|  | 168 | +		}); | 
|  | 169 | +	}); | 
|  | 170 | + | 
|  | 171 | +	// The following tests are generated by AI automatically. They describe the behaviors in edge cases. | 
|  | 172 | +	// However, these behaviors are not actually used, and their result and may not meet actual needs. | 
|  | 173 | +	// Therefore, the following usages should be avoided in practice. | 
|  | 174 | +	describe("generated usages", () => { | 
|  | 175 | +		it("should handle edge cases with empty oldBasePath and newBaseUrl", () => { | 
|  | 176 | +			expect(shiftBase("/foo/bar", "", "")).toBe("/foo/bar"); | 
|  | 177 | +			expect(shiftBase("/", "", "")).toBe("/"); | 
|  | 178 | +			expect(shiftBase("", "", "")).toBe(""); | 
|  | 179 | +		}); | 
|  | 180 | + | 
|  | 181 | +		it("should handle edge cases with empty route", () => { | 
|  | 182 | +			expect(shiftBase("", "/base", "/new")).toBe("/new/"); | 
|  | 183 | +			expect(shiftBase("", "/", "/new")).toBe("/new/"); | 
|  | 184 | +			expect(shiftBase("", "", "/new")).toBe("/new/"); | 
|  | 185 | +		}); | 
|  | 186 | + | 
|  | 187 | +		it("should handle edge cases with only slashes", () => { | 
|  | 188 | +			expect(shiftBase("/", "/", "/new")).toBe("/new/"); | 
|  | 189 | +			expect(shiftBase("/", "/base", "/new")).toBe("/new/"); | 
|  | 190 | +			expect(shiftBase("/base", "/base", "/new")).toBe("/new/"); | 
|  | 191 | +		}); | 
|  | 192 | + | 
|  | 193 | +		it("should handle routes with duplicate slashes", () => { | 
|  | 194 | +			expect(shiftBase("/base//foo//bar", "/base", "/new")).toBe( | 
|  | 195 | +				"/new/foo/bar", | 
|  | 196 | +			); | 
|  | 197 | +			expect(shiftBase("//base//foo//", "/base", "/new")).toBe( | 
|  | 198 | +				"/new/base/foo/", | 
|  | 199 | +			); | 
|  | 200 | +			expect(shiftBase("//base//", "/base", "/new")).toBe("/new/base/"); | 
|  | 201 | +		}); | 
|  | 202 | + | 
|  | 203 | +		it("should handle routes with special characters", () => { | 
|  | 204 | +			expect(shiftBase("/base/@/foo", "/base", "/new")).toBe("/new/@/foo"); | 
|  | 205 | +			expect(shiftBase("/base/#/foo", "/base", "/new")).toBe("/new/#/foo"); | 
|  | 206 | +			expect(shiftBase("/base/!$/foo", "/base", "/new")).toBe("/new/!$/foo"); | 
|  | 207 | +		}); | 
|  | 208 | + | 
|  | 209 | +		it("should handle routes with trailing slashes in newBaseUrl", () => { | 
|  | 210 | +			expect(shiftBase("/base/foo", "/base", "/new/")).toBe("/new/foo"); | 
|  | 211 | +			expect(shiftBase("/base/foo/", "/base", "/new/")).toBe("/new/foo/"); | 
|  | 212 | +			expect(shiftBase("/base/", "/base", "/new/")).toBe("/new/"); | 
|  | 213 | +		}); | 
|  | 214 | + | 
|  | 215 | +		it("should handle routes with trailing slashes in oldBasePath", () => { | 
|  | 216 | +			expect(shiftBase("/base/foo", "/base/", "/new")).toBe("/new/foo"); | 
|  | 217 | +			expect(shiftBase("/base/foo/", "/base/", "/new")).toBe("/new/foo/"); | 
|  | 218 | +			expect(shiftBase("/base/", "/base/", "/new")).toBe("/new/"); | 
|  | 219 | +		}); | 
|  | 220 | + | 
|  | 221 | +		it("should handle routes with mixed slashes and empty parts", () => { | 
|  | 222 | +			expect(shiftBase("/base//foo", "/base", "/new")).toBe("/new/foo"); | 
|  | 223 | +			expect(shiftBase("/base/foo//", "/base", "/new")).toBe("/new/foo/"); | 
|  | 224 | +			expect(shiftBase("/base//", "/base", "/new")).toBe("/new/"); | 
|  | 225 | +		}); | 
|  | 226 | + | 
|  | 227 | +		it("should handle newBaseUrl with https://", () => { | 
|  | 228 | +			expect(shiftBase("/base/foo", "/base", "https://example.com/new")).toBe( | 
|  | 229 | +				"https://example.com/new/foo", | 
|  | 230 | +			); | 
|  | 231 | +			expect(shiftBase("/base/foo/", "/base", "https://example.com/new")).toBe( | 
|  | 232 | +				"https://example.com/new/foo/", | 
|  | 233 | +			); | 
|  | 234 | +			expect(shiftBase("/base/", "/base", "https://example.com/new")).toBe( | 
|  | 235 | +				"https://example.com/new/", | 
|  | 236 | +			); | 
|  | 237 | +			expect(shiftBase("/base", "/base", "https://example.com/new")).toBe( | 
|  | 238 | +				"https://example.com/new/", | 
|  | 239 | +			); | 
|  | 240 | +		}); | 
|  | 241 | + | 
|  | 242 | +		it("should handle newBaseUrl with //example.com", () => { | 
|  | 243 | +			expect(shiftBase("/base/foo", "/base", "//example.com/new")).toBe( | 
|  | 244 | +				"//example.com/new/foo", | 
|  | 245 | +			); | 
|  | 246 | +			expect(shiftBase("/base/foo/", "/base", "//example.com/new")).toBe( | 
|  | 247 | +				"//example.com/new/foo/", | 
|  | 248 | +			); | 
|  | 249 | +			expect(shiftBase("/base/", "/base", "//example.com/new")).toBe( | 
|  | 250 | +				"//example.com/new/", | 
|  | 251 | +			); | 
|  | 252 | +			expect(shiftBase("/base", "/base", "//example.com/new")).toBe( | 
|  | 253 | +				"//example.com/new/", | 
|  | 254 | +			); | 
|  | 255 | +		}); | 
|  | 256 | + | 
|  | 257 | +		it("should handle newBaseUrl with only origin and no path", () => { | 
|  | 258 | +			expect(shiftBase("/base/foo", "/base", "https://example.com")).toBe( | 
|  | 259 | +				"https://example.com/foo", | 
|  | 260 | +			); | 
|  | 261 | +			expect(shiftBase("/base/foo/", "/base", "https://example.com")).toBe( | 
|  | 262 | +				"https://example.com/foo/", | 
|  | 263 | +			); | 
|  | 264 | +			expect(shiftBase("/base/", "/base", "https://example.com")).toBe( | 
|  | 265 | +				"https://example.com/", | 
|  | 266 | +			); | 
|  | 267 | +			expect(shiftBase("/base", "/base", "https://example.com")).toBe( | 
|  | 268 | +				"https://example.com/", | 
|  | 269 | +			); | 
|  | 270 | +		}); | 
|  | 271 | +	}); | 
|  | 272 | +}); | 
0 commit comments