Skip to content

Commit bdf5e65

Browse files
committedSep 23, 2021
test: improve coverage of model methods
1 parent ab9b643 commit bdf5e65

File tree

3 files changed

+123
-13
lines changed

3 files changed

+123
-13
lines changed
 

‎src/Model/Model.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,10 @@ export class BaseModel {
519519
this: ModelType,
520520
filter: Filter<ModelAttributes<InstanceType<ModelType>>> = {},
521521
options?: ModelAdapterOptions<
522-
FindOptions<ModelAttributes<InstanceType<ModelType>>>
522+
Omit<
523+
FindOptions<ModelAttributes<InstanceType<ModelType>>>,
524+
ForbiddenQueryOptions
525+
>
523526
>,
524527
): Query<ModelType> {
525528
return new Query(filter, options, this);

‎src/Model/__tests__/Model.query.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ describe('query.sort', () => {
127127
)._id,
128128
).toBe(3);
129129
});
130+
131+
it('should sort by custom field ascending by default', async () => {
132+
expect(
133+
(await TestModel.query().sortBy('numberField').firstOrFail())._id,
134+
).toBe(1);
135+
});
130136
});
131137

132138
describe('query.skip', () => {
@@ -205,8 +211,22 @@ test('query.explain', async () => {
205211
expect(result.queryPlanner.winningPlan.inputStage.stage).toBe('IXSCAN');
206212
});
207213

214+
test('query should pass additional driver options', async () => {
215+
const query = TestModel.query(
216+
{ _id: 1 },
217+
{
218+
driverOptions: {
219+
showRecordId: true,
220+
},
221+
},
222+
);
223+
const result = await query.firstOrFail();
224+
expect(result.$attributes.$recordId).toBe(1);
225+
});
226+
208227
test('query should throw if forbidden options are passed', () => {
209228
expect(() =>
229+
// @ts-expect-error
210230
TestModel.query({}, { driverOptions: { sort: 'test' } }),
211231
).toThrow(/sort is not allowed in query's driverOptions/);
212232
});

‎src/Model/__tests__/Model.test.ts

+99-12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class Post extends BaseAutoIncrementModel {
2525

2626
@field()
2727
public content: string;
28+
29+
public notAField?: string;
2830
}
2931

3032
class Empty extends BaseAutoIncrementModel {}
@@ -46,6 +48,28 @@ function nextTitle() {
4648
return `post title ${++postTitleCounter}`;
4749
}
4850

51+
describe('$hasField', () => {
52+
it('should return true if field exists', () => {
53+
expect(Post.$hasField('title')).toBe(true);
54+
});
55+
56+
it('should return false if field does not exist', () => {
57+
expect(Post.$hasField('notAField')).toBe(false);
58+
});
59+
});
60+
61+
describe('$getField', () => {
62+
it('should return the field if it exists', () => {
63+
const field = Post.$getField('title');
64+
expect(field).toStrictEqual({});
65+
});
66+
67+
it('should return undefined if the field does not exist', () => {
68+
const field = Post.$getField('notAField');
69+
expect(field).toBeUndefined();
70+
});
71+
});
72+
4973
test('can create', async () => {
5074
const newUser = await User.create({
5175
username: nextUsername(),
@@ -59,11 +83,6 @@ test('get collection by model class', async () => {
5983
expect(collection).toBeDefined();
6084
});
6185

62-
test('find one by property', async () => {
63-
const user = User.findBy('username', 'root');
64-
expect(user).toBeDefined();
65-
});
66-
6786
test('count all', async () => {
6887
const count = await User.count({});
6988
expect(count).toBe(1);
@@ -78,13 +97,6 @@ test('find by id should work', async () => {
7897
expect(secondUser).not.toBeNull();
7998
});
8099

81-
test("find by id should throw when doesn't exists", async () => {
82-
const t = async () => {
83-
await User.findOrFail(new ObjectId());
84-
};
85-
await expect(t).rejects.toThrow(/E_DOCUMENT_NOT_FOUND/);
86-
});
87-
88100
test('find all', async () => {
89101
const users = await User.all();
90102
expect(users).toHaveLength(2);
@@ -440,3 +452,78 @@ test('custom inspect function', async () => {
440452
const inspected = inspect(post);
441453
expect(inspected).toMatchSnapshot();
442454
});
455+
456+
describe('findMany', () => {
457+
it('should accept an empty list', async () => {
458+
expect(await Post.findMany([])).toStrictEqual([]);
459+
});
460+
461+
it('should find all results', async () => {
462+
const results = await Post.findMany([2, 1, 3]);
463+
expect(results).toHaveLength(3);
464+
expect(results[0]).toBeInstanceOf(Post);
465+
expect(results.map((value) => value.id)).toStrictEqual([1, 2, 3]);
466+
});
467+
468+
it('should not duplicate results', async () => {
469+
const results = await Post.findMany([1, 1, 1]);
470+
expect(results).toHaveLength(1);
471+
expect(results[0].id).toBe(1);
472+
});
473+
});
474+
475+
describe('findOrFail', () => {
476+
it('should return instance if found', async () => {
477+
const post = await Post.findOrFail(1);
478+
expect(post).toBeInstanceOf(Post);
479+
expect(post.id).toBe(1);
480+
});
481+
482+
it('should throw if not found', async () => {
483+
await expect(Post.findOrFail(-1)).rejects.toThrow(/E_DOCUMENT_NOT_FOUND/);
484+
});
485+
});
486+
487+
describe('findBy', () => {
488+
it('should return instance if found', async () => {
489+
const user = await User.findBy('username', 'root1');
490+
expect(user).toBeInstanceOf(User);
491+
// @ts-expect-error
492+
expect(user.username).toBe('root1');
493+
});
494+
495+
it('should return null if not found', async () => {
496+
const user = await User.findBy('username', 'bad');
497+
expect(user).toBeNull();
498+
});
499+
});
500+
501+
describe('findByOrFail', () => {
502+
it('should return instance if found', async () => {
503+
const user = await User.findByOrFail('username', 'root1');
504+
expect(user).toBeInstanceOf(User);
505+
expect(user.username).toBe('root1');
506+
});
507+
508+
it('should throw if not found', async () => {
509+
await expect(User.findByOrFail('username', 'bad')).rejects.toThrow(
510+
/E_DOCUMENT_NOT_FOUND/,
511+
);
512+
});
513+
});
514+
515+
describe('save', () => {
516+
it('should return true if something was saved', async () => {
517+
const post = await Post.findOrFail(1);
518+
post.title = 'new title';
519+
expect(await post.save()).toBe(true);
520+
});
521+
522+
it('should return false if nothing was saved', async () => {
523+
const post = await Post.findOrFail(1);
524+
const title = post.title;
525+
// no-op
526+
post.title = title;
527+
expect(await post.save()).toBe(false);
528+
});
529+
});

0 commit comments

Comments
 (0)
Please sign in to comment.