Skip to content

Commit ef7c270

Browse files
committed
Port MongoDB filter regressions as ORM integration tests
Ports two MongoDB-only upstream behaviours against Mongo: a string value containing a literal `$` is treated as data (filter + update), and an OR[NOT eq, eq] filter evaluates to the expected result set. Signed-off-by: Serhii Tatarintsev <tatarintsev@prisma.io>
1 parent 41b017c commit ef7c270

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { MongoContractSerializer } from '@prisma-next/family-mongo/ir';
2+
import { mongoOrm } from '@prisma-next/mongo-orm';
3+
import { MongoFieldFilter, MongoOrExpr } from '@prisma-next/mongo-query-ast/execution';
4+
import { expect, it } from 'vitest';
5+
import type { Contract } from './fixtures/generated/contract';
6+
import ormContractJson from './fixtures/generated/contract.json';
7+
import { describeWithMongoDB } from './setup';
8+
9+
const contract = new MongoContractSerializer().deserializeContract(ormContractJson) as Contract;
10+
11+
// Ported from upstream MongoDB-only regressions:
12+
// #103 prisma/prisma#13089 — a `$`-prefixed string value is data, not a Mongo operator.
13+
// #104 prisma-engines prisma_22007 — `OR: [{ NOT: { f: "b" } }, { f: "c" } ]` evaluates to {a, c}.
14+
describeWithMongoDB('ported MongoDB regressions', (ctx) => {
15+
it('#103 filters by a string value containing a literal `$`', async () => {
16+
const db = ctx.client.db(ctx.dbName);
17+
await db.collection('users').insertMany([
18+
{ name: 'foo', email: 'foo@example.com', addresses: [] },
19+
{ name: '$foo', email: 'dollar-foo@example.com', addresses: [] },
20+
]);
21+
22+
const orm = mongoOrm({ contract, executor: ctx.runtime });
23+
const results = await orm.users.where(MongoFieldFilter.eq('name', '$foo')).all();
24+
25+
expect(results).toHaveLength(1);
26+
expect(results[0]).toMatchObject({ name: '$foo', email: 'dollar-foo@example.com' });
27+
});
28+
29+
it('#103 updates a record matched by a string value containing a literal `$`', async () => {
30+
const db = ctx.client.db(ctx.dbName);
31+
await db.collection('users').insertMany([
32+
{ name: 'foo', email: 'foo@example.com', addresses: [] },
33+
{ name: '$foo', email: 'dollar-foo@example.com', addresses: [] },
34+
]);
35+
36+
const orm = mongoOrm({ contract, executor: ctx.runtime });
37+
const updated = await orm.users
38+
.where(MongoFieldFilter.eq('name', '$foo'))
39+
.update({ name: '$$foo' });
40+
41+
expect(updated).toMatchObject({ name: '$$foo', email: 'dollar-foo@example.com' });
42+
43+
const afterUpdate = await orm.users.where(MongoFieldFilter.eq('name', '$$foo')).all();
44+
expect(afterUpdate).toHaveLength(1);
45+
expect(afterUpdate[0]).toMatchObject({ name: '$$foo' });
46+
47+
const originalGone = await orm.users.where(MongoFieldFilter.eq('name', '$foo')).all();
48+
expect(originalGone).toHaveLength(0);
49+
});
50+
51+
it('#104 renders `OR: [{ NOT: b }, c ]` to the {a, c} result set', async () => {
52+
const db = ctx.client.db(ctx.dbName);
53+
await db.collection('users').insertMany([
54+
{ name: 'a', email: 'a@example.com', addresses: [] },
55+
{ name: 'b', email: 'b@example.com', addresses: [] },
56+
{ name: 'c', email: 'c@example.com', addresses: [] },
57+
]);
58+
59+
const orm = mongoOrm({ contract, executor: ctx.runtime });
60+
const filter = MongoOrExpr.of([
61+
MongoFieldFilter.eq('name', 'b').not(),
62+
MongoFieldFilter.eq('name', 'c'),
63+
]);
64+
const results = await orm.users.where(filter).orderBy({ name: 1 }).all();
65+
66+
expect(results).toHaveLength(2);
67+
expect(results.map((r) => r.name)).toEqual(['a', 'c']);
68+
});
69+
});

0 commit comments

Comments
 (0)