Skip to content

Commit 56836b5

Browse files
committed
FEAT: Add base model with validation, defaults, and hooks
- Implemented a new `Base` class that provides a foundation for creating data models. - Added functionality for schema definition, including type checking, min/max length, optional fields, default values, enums, and nested schemas. - Integrated `beforeChecks` and `afterChecks` hooks to allow pre- and post-validation data manipulation. - Enabled immutable class behavior to prevent accidental modification of model instances. - Introduced support for custom base model inheritance, allowing for shared functionality across different models. - Added comprehensive unit tests to verify the functionality of validation, defaults, hooks, immutability, and inheritance.
1 parent d4dd652 commit 56836b5

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

test/base.test.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import test from "node:test";
2+
import assert from "node:assert/strict";
3+
import Base from "../base.js";
4+
5+
test("validates fields, applies defaults, and runs hooks", () => {
6+
class User extends Base {
7+
static version = 1;
8+
static schema = {
9+
name: {
10+
type: String,
11+
minLength: 2,
12+
optional: true,
13+
beforeChecks: (value) => typeof value === "string" ? value.trim() : value,
14+
afterChecks: (value) => value.replace(/\s+/g, " ")
15+
},
16+
status: {
17+
type: String,
18+
enum: ["active", "inactive"],
19+
default: "active",
20+
beforeChecks: (value) => typeof value === "string" ? value.toLowerCase() : value
21+
},
22+
confirmed: { type: Boolean, optional: true, default: false },
23+
profile: {
24+
type: Object,
25+
keys: {
26+
role: { type: String, enum: ["admin", "editor"], default: "editor" }
27+
}
28+
},
29+
tags: {
30+
type: Array,
31+
default: [],
32+
values: {
33+
type: String,
34+
beforeChecks: (value) => typeof value === "string" ? value.trim() : value
35+
}
36+
}
37+
};
38+
}
39+
40+
const user = new User({
41+
name: " John Doe ",
42+
status: "active",
43+
profile: {}
44+
});
45+
46+
assert.equal(user.name, "John Doe");
47+
assert.equal(user.status, "active");
48+
assert.equal(user.confirmed, false);
49+
assert.deepEqual(user.profile, { role: "editor" });
50+
assert.deepEqual(user.tags, []);
51+
assert.equal(user.toObject().version, 1);
52+
assert.deepEqual(user.toObject(), {
53+
name: "John Doe",
54+
status: "active",
55+
confirmed: false,
56+
profile: { role: "editor" },
57+
tags: [],
58+
version: 1
59+
});
60+
});
61+
62+
test("update merges existing values and revalidates", () => {
63+
class User extends Base {
64+
static schema = {
65+
name: { type: String },
66+
role: { type: String, enum: ["admin", "editor"], default: "editor" },
67+
confirmed: { type: Boolean, optional: true, default: false }
68+
};
69+
}
70+
71+
const user = new User({ name: "John" });
72+
user.update({ role: "admin" });
73+
74+
assert.equal(user.name, "John");
75+
assert.equal(user.role, "admin");
76+
assert.equal(user.confirmed, false);
77+
});
78+
79+
test("immutable classes reject updates", () => {
80+
class User extends Base {
81+
static immutable = true;
82+
static schema = {
83+
name: { type: String }
84+
};
85+
}
86+
87+
const user = new User({ name: "John" });
88+
89+
assert.throws(() => {
90+
user.update({ name: "Jane" });
91+
}, /Cannot update immutable object of type User/);
92+
});
93+
94+
test("supports custom base model inheritance", () => {
95+
class BaseModel extends Base {
96+
save() {
97+
return "saved";
98+
}
99+
}
100+
101+
class User extends BaseModel {
102+
static collection = "users";
103+
static schema = {
104+
name: { type: String }
105+
};
106+
}
107+
108+
const user = new User({ name: "John" });
109+
110+
assert.equal(user.save(), "saved");
111+
assert.equal(user.name, "John");
112+
assert.equal(User.collection, "users");
113+
});

0 commit comments

Comments
 (0)