170 lines
6.0 KiB
Plaintext
170 lines
6.0 KiB
Plaintext
component extends="testbox.system.BaseSpec" {
|
|
|
|
function beforeAll() {
|
|
// Initialize application scope with minimal settings required by resource.cfc
|
|
application._taffy = {
|
|
settings: {
|
|
serializer: "core.nativeJsonSerializer",
|
|
noDataSends204NoContent: false
|
|
},
|
|
factory: new core.factory(),
|
|
compat: {
|
|
queryToArray: "missing",
|
|
queryToStruct: "missing"
|
|
}
|
|
};
|
|
// Create a mock API instance for testing URI methods
|
|
variables.api = new core.api();
|
|
}
|
|
|
|
function run() {
|
|
|
|
describe("URI Matching", function() {
|
|
|
|
describe("convertURItoRegex()", function() {
|
|
|
|
it("should convert simple static URI to regex", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/users");
|
|
expect(result).toBeStruct();
|
|
expect(result).toHaveKey("uriRegex");
|
|
expect(result).toHaveKey("tokens");
|
|
expect(result.tokens).toBeArray();
|
|
expect(arrayLen(result.tokens)).toBe(0);
|
|
});
|
|
|
|
it("should extract single token from URI", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/users/{id}");
|
|
expect(arrayLen(result.tokens)).toBe(1);
|
|
expect(result.tokens[1]).toBe("id");
|
|
});
|
|
|
|
it("should extract multiple tokens from URI", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/users/{userId}/orders/{orderId}");
|
|
expect(arrayLen(result.tokens)).toBe(2);
|
|
expect(result.tokens[1]).toBe("userId");
|
|
expect(result.tokens[2]).toBe("orderId");
|
|
});
|
|
|
|
it("should handle mixed static and token segments", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/api/v1/users/{id}/profile");
|
|
expect(arrayLen(result.tokens)).toBe(1);
|
|
expect(result.tokens[1]).toBe("id");
|
|
});
|
|
|
|
it("should generate regex that matches expected URIs", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/items/{id}");
|
|
var regex = result.uriRegex;
|
|
|
|
// Should match /items/123
|
|
expect(reFindNoCase(regex, "/items/123")).toBeGT(0);
|
|
// Should match /items/abc
|
|
expect(reFindNoCase(regex, "/items/abc")).toBeGT(0);
|
|
// Should match with format extension
|
|
expect(reFindNoCase(regex, "/items/123.json")).toBeGT(0);
|
|
});
|
|
|
|
it("should support custom regex patterns in tokens", function() {
|
|
// Taffy supports {tokenName:regex} syntax
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/users/{id:[0-9]+}");
|
|
expect(result.tokens[1]).toBe("id");
|
|
// The regex should only match numeric IDs
|
|
var regex = result.uriRegex;
|
|
expect(reFindNoCase(regex, "/users/123")).toBeGT(0);
|
|
});
|
|
|
|
});
|
|
|
|
describe("URI regex matching", function() {
|
|
|
|
it("should match exact static path", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/simple");
|
|
expect(reFindNoCase(result.uriRegex, "/simple")).toBeGT(0);
|
|
});
|
|
|
|
it("should match path with trailing slash", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/simple");
|
|
expect(reFindNoCase(result.uriRegex, "/simple/")).toBeGT(0);
|
|
});
|
|
|
|
it("should match path with format extension", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/items/{id}");
|
|
expect(reFindNoCase(result.uriRegex, "/items/123.json")).toBeGT(0);
|
|
expect(reFindNoCase(result.uriRegex, "/items/abc.xml")).toBeGT(0);
|
|
});
|
|
|
|
it("should not match unrelated paths", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/users/{id}");
|
|
expect(reFindNoCase(result.uriRegex, "/items/123")).toBe(0);
|
|
});
|
|
|
|
it("should handle deeply nested URIs", function() {
|
|
var result = makePublic(api, "convertURItoRegex").convertURItoRegex("/api/v1/users/{userId}/orders/{orderId}/items/{itemId}");
|
|
expect(arrayLen(result.tokens)).toBe(3);
|
|
expect(reFindNoCase(result.uriRegex, "/api/v1/users/1/orders/2/items/3")).toBeGT(0);
|
|
});
|
|
|
|
});
|
|
|
|
describe("Token value extraction", function() {
|
|
|
|
it("should extract token values from matched URI", function() {
|
|
var uriConfig = makePublic(api, "convertURItoRegex").convertURItoRegex("/users/{id}");
|
|
var matchResult = reFindNoSuck(uriConfig.uriRegex, "/users/123");
|
|
expect(matchResult).toBeArray();
|
|
expect(arrayLen(matchResult)).toBeGTE(1);
|
|
expect(matchResult[1]).toBe("123");
|
|
});
|
|
|
|
it("should extract multiple token values", function() {
|
|
var uriConfig = makePublic(api, "convertURItoRegex").convertURItoRegex("/users/{userId}/orders/{orderId}");
|
|
var matchResult = reFindNoSuck(uriConfig.uriRegex, "/users/42/orders/99");
|
|
expect(arrayLen(matchResult)).toBeGTE(2);
|
|
expect(matchResult[1]).toBe("42");
|
|
expect(matchResult[2]).toBe("99");
|
|
});
|
|
|
|
});
|
|
|
|
describe("sortURIMatchOrder()", function() {
|
|
|
|
it("should sort URIs for proper matching order", function() {
|
|
var endpoints = {
|
|
"^/users/([^\/]+)": { srcUri: "/users/{id}" },
|
|
"^/users": { srcUri: "/users" },
|
|
"^/users/([^\/]+)/profile": { srcUri: "/users/{id}/profile" }
|
|
};
|
|
var result = makePublic(api, "sortURIMatchOrder").sortURIMatchOrder(endpoints);
|
|
expect(result).toBeArray();
|
|
// More specific patterns should be sorted appropriately
|
|
expect(arrayLen(result)).toBe(3);
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
/**
|
|
* Reimplementation of reFindNoSuck for testing
|
|
*/
|
|
private function reFindNoSuck(required string pattern, required string data, numeric startPos = 1) {
|
|
var local = {};
|
|
local.awesome = [];
|
|
local.sucky = reFindNoCase(arguments.pattern, arguments.data, arguments.startPos, true);
|
|
if (!isArray(local.sucky.len) || arrayLen(local.sucky.len) == 0) {
|
|
return [];
|
|
}
|
|
for (local.i = 1; local.i <= arrayLen(local.sucky.len); local.i++) {
|
|
if (local.sucky.len[local.i] > 0 && local.sucky.pos[local.i] > 0) {
|
|
local.matchBody = mid(arguments.data, local.sucky.pos[local.i], local.sucky.len[local.i]);
|
|
if (local.matchBody != arguments.data) {
|
|
arrayAppend(local.awesome, local.matchBody);
|
|
}
|
|
}
|
|
}
|
|
return local.awesome;
|
|
}
|
|
|
|
}
|