@kenniy/godeye-data-contracts
Version:
Enterprise-grade base repository architecture for GOD-EYE microservices with zero overhead and maximum code reuse
309 lines (308 loc) • 13.9 kB
JavaScript
;
/**
* Complete Integration Test
* Tests the entire package working together as described in usage guides
*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("../index");
const class_validator_1 = require("class-validator");
const class_transformer_1 = require("class-transformer");
const auth_constants_1 = require("../constants/auth.constants");
// Test DTO matching usage guide examples
class UserResponseDto {
}
__decorate([
(0, index_1.IsValidId)(),
__metadata("design:type", String)
], UserResponseDto.prototype, "id", void 0);
__decorate([
(0, index_1.IsRequiredEmail)(),
(0, index_1.ToLowerCase)(),
(0, index_1.Trim)(),
__metadata("design:type", String)
], UserResponseDto.prototype, "email", void 0);
describe("Complete Integration Test", () => {
describe("Usage Guide Compliance - ResponseFactory", () => {
it("should match simple-response-usage.md examples", () => {
// Test simple success response
const userData = {
id: "123",
name: "John Doe",
email: "john@example.com",
};
const response = index_1.ResponseFactory.success(userData, "User found");
expect(response).toMatchObject({
success: true,
data: userData,
message: "User found",
status_code: 200,
});
expect(response.timestamp).toBeDefined();
expect(response.trace_id).toBeDefined();
expect(response.time_ms).toBeDefined();
});
it("should auto-detect paginated responses", () => {
const paginatedUsers = {
items: [
{ id: "1", name: "User 1" },
{ id: "2", name: "User 2" },
],
total: 50,
page: 2,
limit: 20,
};
const response = index_1.ResponseFactory.success(paginatedUsers);
expect(response.success).toBe(true);
expect(response.data.items).toEqual(paginatedUsers.items);
expect(response.data).toMatchObject({
items: paginatedUsers.items,
total: 50,
page: 2,
limit: 20,
totalPages: 3,
hasNext: true,
hasPrev: true,
});
});
it("should handle different pagination formats", () => {
// Test 'data' format
const dataFormat = {
data: [{ id: "1" }],
total: 5,
page: 1,
limit: 10,
};
const dataResponse = index_1.ResponseFactory.success(dataFormat);
expect(dataResponse.data.items).toEqual([{ id: "1" }]);
expect(dataResponse.data.total).toBe(5);
// Test 'results' format
const resultsFormat = {
results: [{ id: "2" }],
count: 3,
};
const resultsResponse = index_1.ResponseFactory.success(resultsFormat);
expect(resultsResponse.data.items).toEqual([{ id: "2" }]);
expect(resultsResponse.data.total).toBe(3);
});
});
describe("Usage Guide Compliance - Validation System", () => {
it("should match validation-pipeline-usage.md examples", async () => {
class TestDto {
}
__decorate([
(0, index_1.IsValidId)(),
__metadata("design:type", String)
], TestDto.prototype, "userId", void 0);
__decorate([
(0, index_1.IsRequiredEmail)(),
(0, index_1.ToLowerCase)(),
(0, index_1.Trim)(),
__metadata("design:type", String)
], TestDto.prototype, "email", void 0);
// Test valid data
const validInput = {
userId: "550e8400-e29b-41d4-a716-446655440000", // UUID
email: " TEST@EXAMPLE.COM ",
};
const dto = (0, class_transformer_1.plainToClass)(TestDto, validInput);
expect(dto.email).toBe("test@example.com"); // Transformed
const errors = await (0, class_validator_1.validate)(dto);
expect(errors).toHaveLength(0);
// Test MongoDB ObjectId
const mongoInput = {
userId: "507f1f77bcf86cd799439011",
email: "mongo@example.com",
};
const mongoDto = (0, class_transformer_1.plainToClass)(TestDto, mongoInput);
const mongoErrors = await (0, class_validator_1.validate)(mongoDto);
expect(mongoErrors).toHaveLength(0);
});
it("should validate with ValidationUtils", () => {
// UUID validation
expect(index_1.ValidationUtils.isValidId("550e8400-e29b-41d4-a716-446655440000")).toBe(true);
// MongoDB ObjectId validation
expect(index_1.ValidationUtils.isValidId("507f1f77bcf86cd799439011")).toBe(true);
// Numeric ID validation
expect(index_1.ValidationUtils.isValidId("12345")).toBe(true);
// Invalid ID validation
expect(index_1.ValidationUtils.isValidId("invalid-id")).toBe(false);
// Email validation
expect(index_1.ValidationUtils.isValidEmail("test@example.com")).toBe(true);
expect(index_1.ValidationUtils.isValidEmail("invalid-email")).toBe(false);
});
});
describe("Usage Guide Compliance - Kong Authentication", () => {
it("should match kong-usage.md examples", () => {
const headers = {
[auth_constants_1.KONG_HEADERS.USER_ID]: "123",
[auth_constants_1.KONG_HEADERS.USER_EMAIL]: "user@example.com",
[auth_constants_1.KONG_HEADERS.USER_TYPE]: "patient,admin",
[auth_constants_1.KONG_HEADERS.PROFILE_ID]: "profile-456",
};
const userContext = (0, index_1.extractKongUserContext)(headers);
expect(userContext).toMatchObject({
id: "123",
email: "user@example.com",
type: ["patient", "admin"],
profile_id: "profile-456",
});
});
it("should normalize headers correctly", () => {
const rawHeaders = {
"x-user-id": "123",
"x-user-type": ["admin", "user"],
"content-type": "application/json",
};
const normalized = (0, index_1.normalizeHeaders)(rawHeaders);
expect(normalized).toEqual({
"x-user-id": "123",
"x-user-type": "admin,user",
"content-type": "application/json",
});
});
});
describe("Usage Guide Compliance - Bootstrap System", () => {
it("should match bootstrap-usage.md configuration structure", () => {
const basicConfig = {
serviceName: "my-service",
port: 3003,
enableSwagger: true,
};
const advancedConfig = {
serviceName: "my-service",
port: 3003,
swagger: {
enabled: true,
title: "My Service API",
description: "API documentation with ResponseFactory patterns",
version: "1.0.0",
path: "docs",
},
cors: {
enabled: true,
origins: ["http://localhost:3000"],
credentials: true,
},
validation: {
whitelist: true,
transform: true,
},
};
// Test that configurations match expected structure
expect(basicConfig.serviceName).toBe("my-service");
expect(basicConfig.enableSwagger).toBe(true);
expect(advancedConfig.swagger?.title).toBe("My Service API");
expect(advancedConfig.cors?.origins).toContain("http://localhost:3000");
expect(advancedConfig.validation?.whitelist).toBe(true);
});
});
describe("End-to-End Workflow Test", () => {
it("should support complete microservice setup workflow", async () => {
// 1. Validation - Transform and validate user input
class CreateUserDto {
}
__decorate([
(0, index_1.IsRequiredEmail)(),
(0, index_1.ToLowerCase)(),
(0, index_1.Trim)(),
__metadata("design:type", String)
], CreateUserDto.prototype, "email", void 0);
__decorate([
(0, index_1.IsValidId)(),
__metadata("design:type", String)
], CreateUserDto.prototype, "profileId", void 0);
const rawInput = {
email: " JOHN@EXAMPLE.COM ",
profileId: "550e8400-e29b-41d4-a716-446655440000",
};
const dto = (0, class_transformer_1.plainToClass)(CreateUserDto, rawInput);
expect(dto.email).toBe("john@example.com"); // Transformed
const validationErrors = await (0, class_validator_1.validate)(dto);
expect(validationErrors).toHaveLength(0);
// 2. Kong Auth - Extract user context from headers
const kongHeaders = {
[auth_constants_1.KONG_HEADERS.USER_ID]: "456",
[auth_constants_1.KONG_HEADERS.USER_EMAIL]: "admin@example.com",
[auth_constants_1.KONG_HEADERS.USER_TYPE]: "admin",
};
const userContext = (0, index_1.extractKongUserContext)(kongHeaders);
expect(userContext.id).toBe("456");
expect(userContext.type).toContain("admin");
// 3. Response Factory - Create standardized responses
const createdUser = {
id: dto.profileId,
email: dto.email,
createdBy: userContext.id,
createdAt: new Date().toISOString(),
};
const successResponse = index_1.ResponseFactory.success(createdUser, "User created successfully");
expect(successResponse).toMatchObject({
success: true,
data: createdUser,
message: "User created successfully",
status_code: 200,
});
// 4. Error handling
const errorResponse = index_1.ResponseFactory.validationError("Validation failed", ["Email is required", "Invalid ID format"]);
expect(errorResponse).toMatchObject({
success: false,
error: "Validation Error",
status_code: 422,
});
expect(errorResponse.metadata?.validation_errors).toEqual([
"Email is required",
"Invalid ID format",
]);
// 5. Pagination response
const usersList = {
items: [createdUser],
total: 1,
page: 1,
limit: 20,
};
const paginatedResponse = index_1.ResponseFactory.success(usersList);
expect(paginatedResponse.data.items).toBeDefined();
expect(paginatedResponse.data.total).toBe(1);
});
});
describe("Package Consistency", () => {
it("should maintain consistent response format across all methods", () => {
const baseFields = [
"success",
"status_code",
"timestamp",
"trace_id",
"time_ms",
];
const successResponse = index_1.ResponseFactory.success({ test: true });
const errorResponse = index_1.ResponseFactory.error("Test Error", "Test message", 400);
const notFoundResponse = index_1.ResponseFactory.notFound("Not found");
baseFields.forEach((field) => {
expect(successResponse).toHaveProperty(field);
expect(errorResponse).toHaveProperty(field);
expect(notFoundResponse).toHaveProperty(field);
});
});
it("should maintain consistent trace_id format", () => {
const response1 = index_1.ResponseFactory.success({ test: 1 });
const response2 = index_1.ResponseFactory.error("Error", "Test error");
expect(response1.trace_id).toMatch(/^trace_\d+_[a-zA-Z0-9]+$/);
expect(response2.trace_id).toMatch(/^trace_\d+_[a-zA-Z0-9]+$/);
});
it("should provide consistent timing information", () => {
const response = index_1.ResponseFactory.success({ test: true });
expect(typeof response.time_ms).toBe("number");
expect(response.time_ms).toBeGreaterThanOrEqual(0);
expect(response.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
});
});
});