rea/tests/objcSwiftMetadata.test.ts

131 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
countMethodsByType,
isDbSaveComplete,
isGetterSelector,
isSetterSelector,
objcSwiftMetadataSchema,
propertyNameFromSelector,
swiftDeclsByKind,
type ObjcClass,
type ObjcMethod,
type ObjcProperty,
type DbOperation,
type ObjcSwiftMetadata,
type ObjcProtocol,
type ObjcPropertyAttribute,
type SwiftDecl,
type SwiftAccessLevel,
type DbSaveResult,
} from "../src/domain/objcSwiftMetadata.js";
describe("ObjC/Swift metadata", () => {
it("identifies getter selectors", () => {
expect(isGetterSelector("name")).toBe(true);
expect(isGetterSelector("setName:")).toBe(false);
expect(isGetterSelector("set")).toBe(true);
});
it("identifies setter selectors", () => {
expect(isSetterSelector("setName:")).toBe(true);
expect(isSetterSelector("name")).toBe(false);
});
it("extracts property name from selector", () => {
expect(propertyNameFromSelector("name")).toBe("name");
expect(propertyNameFromSelector("setName:")).toBe("name");
expect(propertyNameFromSelector("set")).toBe("set");
});
it("counts methods by type", () => {
const methods: ObjcMethod[] = [
{
selector: "init",
method_type: "instance",
address: 0x1000,
is_required: false,
is_optional: false,
},
{
selector: "alloc",
method_type: "class",
address: 0x2000,
is_required: false,
is_optional: false,
},
];
const counts = countMethodsByType(methods);
expect(counts.instance).toBe(1);
expect(counts.class).toBe(1);
expect(counts.ivar_getter).toBe(0);
expect(counts.ivar_setter).toBe(0);
});
it("filters Swift declarations by kind", () => {
const decls: SwiftDecl[] = [
{
kind: "class",
name: "Foo",
module: null,
access_level: "public",
super_class: null,
protocols: [],
is_final: false,
is_required: false,
is_convenience_init: false,
is_override: false,
},
];
const classes = swiftDeclsByKind(decls, "class");
expect(classes).toHaveLength(1);
expect(classes[0]!.name).toBe("Foo");
});
it("checks database save completeness", () => {
const result: DbSaveResult = {
operation: "save",
succeeded: true,
preserved_names: 10,
preserved_comments: 5,
preserved_bookmarks: 3,
database_path: "/tmp/db.hop",
error: null,
};
expect(isDbSaveComplete(result, 10, 5, 3)).toBe(true);
expect(isDbSaveComplete(result, 11, 5, 3)).toBe(false);
});
it("validates a well-formed metadata result", () => {
const meta = {
objc_classes: [] as ObjcClass[],
objc_protocols: [] as ObjcProtocol[],
swift_decls: [] as SwiftDecl[],
db_save_result: null,
};
const result = objcSwiftMetadataSchema.safeParse(meta);
expect(result.success).toBe(true);
});
it("uses all exported types", () => {
const prop: ObjcProperty = {
name: "title",
type_encoding: 'T@"NSString"&,N,V_title',
attributes: [] as ObjcPropertyAttribute[],
is_readonly: false,
getter: "title",
setter: "setTitle:",
};
expect(prop.name).toBe("title");
const op: DbOperation = "save";
expect(op).toBe("save");
const meta: ObjcSwiftMetadata = {
objc_classes: [],
objc_protocols: [],
swift_decls: [],
db_save_result: null,
};
expect(meta.objc_classes).toHaveLength(0);
});
});