component extends="testbox.system.BaseSpec" { function beforeAll() { // Initialize application scope with minimal settings application._taffy = { settings: { serializer: "core.nativeJsonSerializer", noDataSends204NoContent: false }, factory: new core.factory(), compat: { queryToArray: "missing", queryToStruct: "missing" } }; // Create sample data fixture variables.sampleData = new tests.fixtures.SampleData(); } function run() { describe("Resource", function() { beforeEach(function() { variables.resource = new core.resource(); }); describe("rep() / representationOf()", function() { it("should return a serializer instance with data", function() { var result = resource.rep({ message: "test" }); expect(new tests.helpers.MetadataHelper().extendsClass(result, "baseSerializer")).toBeTrue(); expect(result.getData().message).toBe("test"); }); it("rep() should be alias for representationOf()", function() { var data = { id: 123 }; var rep1 = resource.rep(data); // Both should return serializer instances with same data expect(rep1.getData().id).toBe(123); }); it("should work with simple string data", function() { var result = resource.rep("Hello World"); expect(result.getData()).toBe("Hello World"); }); it("should work with array data", function() { var result = resource.rep([1, 2, 3]); expect(result.getData()).toBeArray(); expect(arrayLen(result.getData())).toBe(3); }); it("should work with nested struct data", function() { var data = { user: { name: "John", age: 30 }, roles: ["admin", "user"] }; var result = resource.rep(data); expect(result.getData().user.name).toBe("John"); expect(result.getData().roles).toBeArray(); }); }); describe("encode.string()", function() { it("should add control character prefix to force string serialization", function() { // forceString is public (no access modifier), encode.string is just a reference to it var result = resource.forceString("12345"); expect(left(result, 1)).toBe(chr(2)); }); it("should preserve the original value after prefix", function() { var result = resource.forceString("12345"); expect(right(result, 5)).toBe("12345"); }); it("should work with numeric-looking strings", function() { var result = resource.forceString("00123"); expect(len(result)).toBe(6); // chr(2) + "00123" }); }); describe("qToArray() - internal query to array conversion", function() { beforeEach(function() { makePublic(resource, "qToArray"); }); it("should convert query to array of structs", function() { var q = sampleData.getSampleQuery(); var result = resource.qToArray(q); expect(result).toBeArray(); expect(arrayLen(result)).toBe(3); }); it("should preserve column values in structs", function() { var q = sampleData.getSampleQuery(); var result = resource.qToArray(q); // Find the row with id=1 var found = false; for (var row in result) { if (row.id == 1) { expect(row.name).toBe("John Doe"); expect(row.email).toBe("john@example.com"); found = true; break; } } expect(found).toBeTrue(); }); it("should handle empty query", function() { var q = queryNew("id,name", "integer,varchar"); var result = resource.qToArray(q); expect(result).toBeArray(); expect(arrayLen(result)).toBe(0); }); it("should support callback function for row transformation", function() { var q = sampleData.getSingleRowQuery(); var result = resource.qToArray(q, function(row) { row.transformed = true; return row; }); expect(result[1].transformed).toBeTrue(); }); }); describe("qToStruct() - internal query to struct conversion", function() { beforeEach(function() { makePublic(resource, "qToStruct"); }); it("should convert single-row query to struct", function() { var q = sampleData.getSingleRowQuery(); var result = resource.qToStruct(q); expect(result).toBeStruct(); expect(result.id).toBe(1); expect(result.name).toBe("Test User"); }); it("should throw error for multi-row query", function() { var q = sampleData.getSampleQuery(); // Has 3 rows expect(function() { resource.qToStruct(q); }).toThrow(); }); it("should handle query with all column types", function() { var q = sampleData.getSingleRowQuery(); var result = resource.qToStruct(q); expect(structKeyExists(result, "id")).toBeTrue(); expect(structKeyExists(result, "name")).toBeTrue(); expect(structKeyExists(result, "email")).toBeTrue(); }); it("should support callback function for value transformation", function() { var q = sampleData.getSingleRowQuery(); var result = resource.qToStruct(q, function(colName, value) { if (colName == "name") { return uCase(value); } return value; }); expect(result.name).toBe("TEST USER"); }); }); describe("method chaining with rep()", function() { it("should support chaining with withStatus()", function() { var result = resource.rep({ created: true }).withStatus(201); expect(result.getStatus()).toBe(201); expect(result.getData().created).toBeTrue(); }); it("should support chaining with withHeaders()", function() { var result = resource.rep({ data: "test" }) .withHeaders({ "X-Custom": "value" }); expect(result.getHeaders()["X-Custom"]).toBe("value"); }); it("should support full fluent chain", function() { var result = resource.rep({ id: 123 }) .withStatus(201, "Created") .withHeaders({ "Location": "/items/123" }); expect(result.getData().id).toBe(123); expect(result.getStatus()).toBe(201); expect(result.getStatusText()).toBe("Created"); expect(result.getHeaders()["Location"]).toBe("/items/123"); }); }); }); } }