Files
svc-api-x/v1/taffy/tests/specs/integration/URIMatchingSpec.cfc

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;
}
}