Skip to content

Commit f1a8cef

Browse files
authored
chore: migrate some v2 regression cases (#287)
* chore: migrate some v2 regression cases * update * update
1 parent cc848f2 commit f1a8cef

File tree

9 files changed

+292
-0
lines changed

9 files changed

+292
-0
lines changed

packages/testtools/src/schema.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
import { invariant } from '@zenstackhq/common-helpers';
12
import { loadDocument } from '@zenstackhq/language';
23
import { TsSchemaGenerator } from '@zenstackhq/sdk';
34
import type { SchemaDef } from '@zenstackhq/sdk/schema';
45
import { execSync } from 'node:child_process';
6+
import crypto from 'node:crypto';
57
import fs from 'node:fs';
8+
import os from 'node:os';
69
import path from 'node:path';
710
import { match } from 'ts-pattern';
11+
import { expect } from 'vitest';
812
import { createTestProject } from './project';
913

1014
function makePrelude(provider: 'sqlite' | 'postgresql', dbUrl?: string) {
@@ -86,3 +90,44 @@ export async function generateTsSchemaInPlace(schemaPath: string) {
8690
await generator.generate(result.model, workDir);
8791
return compileAndLoad(workDir);
8892
}
93+
94+
export async function loadSchema(schema: string) {
95+
if (!schema.includes('datasource ')) {
96+
schema = `${makePrelude('sqlite')}\n\n${schema}`;
97+
}
98+
99+
// create a temp file
100+
const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);
101+
fs.writeFileSync(tempFile, schema);
102+
const r = await loadDocument(tempFile);
103+
expect(r).toSatisfy(
104+
(r) => r.success,
105+
`Failed to load schema: ${(r as any).errors?.map((e: any) => e.toString()).join(', ')}`,
106+
);
107+
invariant(r.success);
108+
return r.model;
109+
}
110+
111+
export async function loadSchemaWithError(schema: string, error: string | RegExp) {
112+
if (!schema.includes('datasource ')) {
113+
schema = `${makePrelude('sqlite')}\n\n${schema}`;
114+
}
115+
116+
// create a temp file
117+
const tempFile = path.join(os.tmpdir(), `zenstack-schema-${crypto.randomUUID()}.zmodel`);
118+
fs.writeFileSync(tempFile, schema);
119+
const r = await loadDocument(tempFile);
120+
expect(r.success).toBe(false);
121+
invariant(!r.success);
122+
if (typeof error === 'string') {
123+
expect(r).toSatisfy(
124+
(r) => r.errors.some((e: any) => e.toString().toLowerCase().includes(error.toLowerCase())),
125+
`Expected error message to include "${error}" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,
126+
);
127+
} else {
128+
expect(r).toSatisfy(
129+
(r) => r.errors.some((e: any) => error.test(e)),
130+
`Expected error message to match "${error}" but got: ${r.errors.map((e: any) => e.toString()).join(', ')}`,
131+
);
132+
}
133+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { loadSchemaWithError } from '@zenstackhq/testtools';
2+
import { it } from 'vitest';
3+
4+
it('verifies issue 177', async () => {
5+
await loadSchemaWithError(
6+
`
7+
model Foo {
8+
id String @id @default(cuid())
9+
10+
bar Bar @relation(fields: [barId1, barId2], references: [id1, id2])
11+
barId1 String?
12+
barId2 String
13+
}
14+
15+
model Bar {
16+
id1 String @default(cuid())
17+
id2 String @default(cuid())
18+
foos Foo[]
19+
20+
@@id([id1, id2])
21+
}
22+
`,
23+
'relation "bar" is not optional, but field "barId1" is optional',
24+
);
25+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { expect, it } from 'vitest';
2+
import { createPolicyTestClient } from '@zenstackhq/testtools';
3+
4+
it('verifies issue 389', async () => {
5+
const db = await createPolicyTestClient(`
6+
model model {
7+
id String @id @default(uuid())
8+
value Int
9+
@@allow('read', true)
10+
@@allow('create', value > 0)
11+
}
12+
`);
13+
await expect(db.model.create({ data: { value: 0 } })).toBeRejectedByPolicy();
14+
await expect(db.model.create({ data: { value: 1 } })).toResolveTruthy();
15+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { loadDocument } from '@zenstackhq/language';
2+
import { it } from 'vitest';
3+
4+
it('verifies issue 392', async () => {
5+
await loadDocument(
6+
`
7+
model M1 {
8+
m2_id String @id
9+
m2 M2 @relation(fields: [m2_id], references: [id])
10+
}
11+
12+
model M2 {
13+
id String @id
14+
m1 M1?
15+
}
16+
`,
17+
);
18+
19+
await loadDocument(
20+
`
21+
model M1 {
22+
id String @id
23+
m2_id String @unique
24+
m2 M2 @relation(fields: [m2_id], references: [id])
25+
}
26+
27+
model M2 {
28+
id String @id
29+
m1 M1?
30+
}
31+
`,
32+
);
33+
34+
await loadDocument(
35+
`
36+
model M1 {
37+
m2_id String
38+
m2 M2 @relation(fields: [m2_id], references: [id])
39+
@@id([m2_id])
40+
}
41+
42+
model M2 {
43+
id String @id
44+
m1 M1?
45+
}
46+
`,
47+
);
48+
49+
await loadDocument(
50+
`
51+
model M1 {
52+
m2_id String
53+
m2 M2 @relation(fields: [m2_id], references: [id])
54+
@@unique([m2_id])
55+
}
56+
57+
model M2 {
58+
id String @id
59+
m1 M1?
60+
}
61+
`,
62+
);
63+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
import { it } from 'vitest';
3+
4+
it('verifies issue 416', async () => {
5+
await loadSchema(
6+
`
7+
datasource db {
8+
provider = "postgresql"
9+
url = env("DATABASE_URL")
10+
}
11+
12+
model Example {
13+
id Int @id
14+
doubleQuote String @default("s\\"1")
15+
singleQuote String @default('s\\'1')
16+
json Json @default("{\\"theme\\": \\"light\\", \\"consoleDrawer\\": false}")
17+
}
18+
`,
19+
);
20+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { loadDocument } from '@zenstackhq/language';
2+
import { it } from 'vitest';
3+
4+
it('verifies issue 509', async () => {
5+
await loadDocument(
6+
`
7+
model User {
8+
id Int @id @default(autoincrement())
9+
email String @unique
10+
name String?
11+
posts Post[]
12+
}
13+
14+
model Post {
15+
id Int @id @default(autoincrement())
16+
title String
17+
content String?
18+
published Boolean @default(false)
19+
author User? @relation(fields: [authorId], references: [id])
20+
authorId Int?
21+
22+
deleted Boolean @default(false) @omit
23+
24+
@@allow('all', true)
25+
@@deny('read', deleted)
26+
}
27+
`,
28+
);
29+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { createPolicyTestClient } from '@zenstackhq/testtools';
2+
import { expect, it } from 'vitest';
3+
4+
it('verifies issue 609', async () => {
5+
const db = await createPolicyTestClient(
6+
`
7+
model User {
8+
id String @id @default(cuid())
9+
comments Comment[]
10+
}
11+
12+
model Comment {
13+
id String @id @default(cuid())
14+
parentCommentId String?
15+
replies Comment[] @relation("CommentToComment")
16+
parent Comment? @relation("CommentToComment", fields: [parentCommentId], references: [id])
17+
comment String
18+
author User @relation(fields: [authorId], references: [id])
19+
authorId String
20+
21+
@@allow('read,create', true)
22+
@@allow('update,delete', auth() == author)
23+
}
24+
`,
25+
{ usePrismaPush: true },
26+
);
27+
28+
const rawDb = db.$unuseAll();
29+
30+
await rawDb.user.create({
31+
data: {
32+
id: '1',
33+
comments: {
34+
create: {
35+
id: '1',
36+
comment: 'Comment 1',
37+
},
38+
},
39+
},
40+
});
41+
42+
await rawDb.user.create({
43+
data: {
44+
id: '2',
45+
},
46+
});
47+
48+
// connecting a child comment from a different user to a parent comment should succeed
49+
const dbAuth = db.$setAuth({ id: '2' });
50+
await expect(
51+
dbAuth.comment.create({
52+
data: {
53+
comment: 'Comment 2',
54+
author: { connect: { id: '2' } },
55+
parent: { connect: { id: '1' } },
56+
},
57+
}),
58+
).toResolveTruthy();
59+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { createTestClient } from '@zenstackhq/testtools';
2+
import { it } from 'vitest';
3+
4+
it('verifies issue 632', async () => {
5+
await createTestClient(
6+
`
7+
enum InventoryUnit {
8+
DIGITAL
9+
FL_OZ
10+
GRAMS
11+
MILLILITERS
12+
OUNCES
13+
UNIT
14+
UNLIMITED
15+
}
16+
17+
model TwoEnumsOneModelTest {
18+
id String @id @default(cuid())
19+
inventoryUnit InventoryUnit @default(UNIT)
20+
inputUnit InventoryUnit @default(UNIT)
21+
}
22+
`,
23+
{ provider: 'postgresql', usePrismaPush: true },
24+
);
25+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
import { it } from 'vitest';
3+
4+
it('verifies issue 646', async () => {
5+
await loadSchema(`
6+
model Example {
7+
id Int @id
8+
epsilon Decimal @default(0.00000001)
9+
}
10+
`);
11+
});

0 commit comments

Comments
 (0)