Coverage for databases/tests/test_find_first_or_raise.py: 100%

86 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-08-27 18:25 +0000

1import pytest 

2 

3from prisma import Prisma, errors 

4from prisma.types import UserWhereInput 

5 

6 

7@pytest.mark.asyncio 

8async def test_find_first_or_raise(client: Prisma) -> None: 

9 """Skips multiple non-matching records""" 

10 posts = [ 

11 await client.post.create( 

12 { 

13 'title': 'Test post 1', 

14 'published': False, 

15 'views': 100, 

16 } 

17 ), 

18 await client.post.create( 

19 { 

20 'title': 'Test post 2', 

21 'published': False, 

22 } 

23 ), 

24 await client.post.create( 

25 { 

26 'title': 'Test post 3', 

27 'published': False, 

28 } 

29 ), 

30 await client.post.create( 

31 { 

32 'title': 'Test post 4', 

33 'published': True, 

34 'views': 500, 

35 } 

36 ), 

37 await client.post.create( 

38 { 

39 'title': 'Test post 5', 

40 'published': False, 

41 } 

42 ), 

43 await client.post.create( 

44 { 

45 'title': 'Test post 6', 

46 'published': True, 

47 } 

48 ), 

49 ] 

50 

51 post = await client.post.find_first_or_raise( 

52 where={ 

53 'published': True, 

54 }, 

55 order={ 

56 'title': 'asc', 

57 }, 

58 ) 

59 assert post.id == posts[3].id 

60 assert post.title == 'Test post 4' 

61 assert post.published is True 

62 

63 with pytest.raises( 

64 errors.RecordNotFoundError, 

65 match=r'depends on one or more records that were required but not found', 

66 ): 

67 await client.post.find_first_or_raise( 

68 where={ 

69 'title': { 

70 'contains': 'not found', 

71 } 

72 } 

73 ) 

74 

75 post = await client.post.find_first_or_raise( 

76 where={ 

77 'published': True, 

78 }, 

79 order={ 

80 'title': 'asc', 

81 }, 

82 skip=1, 

83 ) 

84 assert post.id == posts[5].id 

85 assert post.title == 'Test post 6' 

86 assert post.published is True 

87 

88 post = await client.post.find_first_or_raise( 

89 where={ 

90 'NOT': [ 

91 { 

92 'published': True, 

93 }, 

94 ], 

95 }, 

96 order={ 

97 'created_at': 'asc', 

98 }, 

99 ) 

100 assert post.title == 'Test post 1' 

101 

102 post = await client.post.find_first_or_raise( 

103 where={ 

104 'NOT': [ 

105 { 

106 'title': { 

107 'contains': '1', 

108 }, 

109 }, 

110 { 

111 'title': { 

112 'contains': '2', 

113 }, 

114 }, 

115 ], 

116 }, 

117 order={ 

118 'created_at': 'asc', 

119 }, 

120 ) 

121 assert post.title == 'Test post 3' 

122 

123 post = await client.post.find_first_or_raise( 

124 where={ 

125 'title': { 

126 'contains': 'Test', 

127 }, 

128 'AND': [ 

129 { 

130 'published': True, 

131 }, 

132 ], 

133 }, 

134 order={ 

135 'created_at': 'asc', 

136 }, 

137 ) 

138 assert post.title == 'Test post 4' 

139 

140 post = await client.post.find_first_or_raise( 

141 where={ 

142 'AND': [ 

143 { 

144 'published': True, 

145 }, 

146 { 

147 'title': { 

148 'contains': 'Test', 

149 } 

150 }, 

151 ], 

152 }, 

153 order={ 

154 'created_at': 'asc', 

155 }, 

156 ) 

157 assert post.title == 'Test post 4' 

158 

159 with pytest.raises(errors.RecordNotFoundError): 

160 await client.post.find_first_or_raise( 

161 where={ 

162 'views': { 

163 'gt': 100, 

164 }, 

165 'OR': [ 

166 { 

167 'published': False, 

168 }, 

169 ], 

170 } 

171 ) 

172 

173 post = await client.post.find_first_or_raise( 

174 where={ 

175 'OR': [ 

176 { 

177 'views': { 

178 'gt': 100, 

179 }, 

180 }, 

181 { 

182 'published': False, 

183 }, 

184 ] 

185 }, 

186 order={ 

187 'created_at': 'asc', 

188 }, 

189 ) 

190 assert post.title == 'Test post 1' 

191 

192 post = await client.post.find_first_or_raise( 

193 where={ 

194 'OR': [ 

195 { 

196 'views': { 

197 'gt': 100, 

198 }, 

199 }, 

200 ] 

201 } 

202 ) 

203 assert post.title == 'Test post 4' 

204 

205 

206@pytest.mark.asyncio 

207async def test_filtering_one_to_one_relation(client: Prisma) -> None: 

208 """Filtering by a 1-1 relational field and negating the filter""" 

209 async with client.batch_() as batcher: 

210 batcher.user.create( 

211 { 

212 'name': 'Robert', 

213 'profile': { 

214 'create': { 

215 'description': 'My very cool bio.', 

216 'country': 'Scotland', 

217 }, 

218 }, 

219 }, 

220 ) 

221 batcher.user.create( 

222 { 

223 'name': 'Tegan', 

224 'profile': { 

225 'create': { 

226 'description': 'Hello world, this is my bio.', 

227 'country': 'Scotland', 

228 }, 

229 }, 

230 }, 

231 ) 

232 batcher.user.create({'name': 'Callum'}) 

233 

234 user = await client.user.find_first_or_raise( 

235 where={ 

236 'profile': { 

237 'is': { 

238 'description': { 

239 'contains': 'cool', 

240 } 

241 } 

242 } 

243 } 

244 ) 

245 assert user.name == 'Robert' 

246 assert user.profile is None 

247 

248 user = await client.user.find_first_or_raise( 

249 where={ 

250 'profile': { 

251 'is_not': { 

252 'description': { 

253 'contains': 'bio', 

254 } 

255 } 

256 } 

257 } 

258 ) 

259 assert user.name == 'Callum' 

260 assert user.profile is None 

261 

262 

263@pytest.mark.asyncio 

264async def test_filtering_and_ordering_one_to_many_relation( 

265 client: Prisma, 

266) -> None: 

267 """Filtering with every, some, none and ordering by a 1-M relational field""" 

268 async with client.batch_() as batcher: 

269 batcher.user.create( 

270 { 

271 'name': 'Robert', 

272 'posts': { 

273 'create': [ 

274 {'title': 'My first post', 'published': True}, 

275 {'title': 'My second post', 'published': False}, 

276 ] 

277 }, 

278 } 

279 ) 

280 batcher.user.create( 

281 { 

282 'name': 'Tegan', 

283 'posts': { 

284 'create': [ 

285 {'title': 'Hello, world!', 'published': True}, 

286 {'title': 'My test post', 'published': False}, 

287 ] 

288 }, 

289 } 

290 ) 

291 batcher.user.create({'name': 'Callum'}) 

292 

293 user = await client.user.find_first_or_raise( 

294 where={ 

295 'posts': { 

296 'every': { 

297 'title': { 

298 'contains': 'post', 

299 } 

300 } 

301 } 

302 }, 

303 ) 

304 assert user.name == 'Robert' 

305 

306 user = await client.user.find_first_or_raise( 

307 where={ 

308 'posts': { 

309 'none': { 

310 'title': { 

311 'contains': 'Post', 

312 } 

313 } 

314 } 

315 }, 

316 order={ 

317 'name': 'asc', 

318 }, 

319 ) 

320 assert user.name == 'Callum' 

321 

322 with pytest.raises(errors.RecordNotFoundError): 

323 await client.user.find_first_or_raise( 

324 where={ 

325 'posts': { 

326 'some': { 

327 'title': 'foo', 

328 } 

329 } 

330 } 

331 ) 

332 

333 # ordering 

334 

335 user = await client.user.find_first_or_raise( 

336 where={ 

337 'posts': { 

338 'some': { 

339 'title': { 

340 'contains': 'post', 

341 } 

342 } 

343 } 

344 }, 

345 order={'name': 'asc'}, 

346 ) 

347 assert user.name == 'Robert' 

348 

349 user = await client.user.find_first_or_raise( 

350 where={ 

351 'posts': { 

352 'some': { 

353 'title': { 

354 'contains': 'post', 

355 } 

356 } 

357 } 

358 }, 

359 order={'name': 'desc'}, 

360 ) 

361 assert user.name == 'Tegan' 

362 

363 

364@pytest.mark.asyncio 

365async def test_list_wrapper_query_transformation(client: Prisma) -> None: 

366 """Queries wrapped within a list transform global aliases""" 

367 query: UserWhereInput = { 

368 'OR': [ 

369 {'name': {'startswith': '40'}}, 

370 {'name': {'contains': ', 40'}}, 

371 {'name': {'contains': 'house'}}, 

372 ] 

373 } 

374 

375 await client.user.create({'name': 'Robert house'}) 

376 found = await client.user.find_first_or_raise(where=query, order={'created_at': 'asc'}) 

377 assert found.name == 'Robert house' 

378 

379 await client.user.create({'name': '40 robert'}) 

380 found = await client.user.find_first_or_raise(skip=1, where=query, order={'created_at': 'asc'}) 

381 assert found.name == '40 robert' 

382 

383 

384@pytest.mark.asyncio 

385async def test_distinct(client: Prisma) -> None: 

386 """Filtering by distinct combinations of fields""" 

387 users = [ 

388 await client.user.create( 

389 data={ 

390 'name': 'Robert', 

391 }, 

392 ), 

393 await client.user.create( 

394 data={ 

395 'name': 'Tegan', 

396 }, 

397 ), 

398 await client.user.create( 

399 data={ 

400 'name': 'Patrick', 

401 }, 

402 ), 

403 ] 

404 async with client.batch_() as batcher: 

405 batcher.profile.create( 

406 { 

407 'city': 'Dundee', 

408 'country': 'Scotland', 

409 'description': 'Foo', 

410 'user_id': users[0].id, 

411 } 

412 ) 

413 batcher.profile.create( 

414 { 

415 'city': 'Edinburgh', 

416 'country': 'Scotland', 

417 'description': 'Foo', 

418 'user_id': users[1].id, 

419 } 

420 ) 

421 batcher.profile.create( 

422 { 

423 'city': 'London', 

424 'country': 'England', 

425 'description': 'Foo', 

426 'user_id': users[2].id, 

427 } 

428 ) 

429 

430 found = await client.profile.find_first_or_raise( 

431 where={'country': 'Scotland'}, 

432 distinct=['city'], 

433 order={'city': 'asc'}, 

434 ) 

435 assert found.city == 'Dundee' 

436 

437 found = await client.profile.find_first_or_raise( 

438 where={'country': 'Scotland'}, 

439 distinct=['city'], 

440 order={'city': 'desc'}, 

441 ) 

442 assert found.city == 'Edinburgh' 

443 

444 

445@pytest.mark.asyncio 

446async def test_distinct_relations(client: Prisma) -> None: 

447 """Using `distinct` across relations""" 

448 user = await client.user.create( 

449 { 

450 'name': 'Robert', 

451 'posts': { 

452 'create': [ 

453 { 

454 'title': 'Post 1', 

455 'published': True, 

456 }, 

457 { 

458 'title': 'Post 2', 

459 'published': False, 

460 }, 

461 { 

462 'title': 'Post 3', 

463 'published': True, 

464 }, 

465 ] 

466 }, 

467 } 

468 ) 

469 

470 found = await client.user.find_first_or_raise( 

471 where={ 

472 'id': user.id, 

473 }, 

474 include={ 

475 'posts': { 

476 'order_by': {'title': 'asc'}, 

477 'distinct': ['published'], 

478 } 

479 }, 

480 ) 

481 assert found.posts is not None 

482 assert len(found.posts) == 2 

483 assert found.posts[0].published is True 

484 assert found.posts[1].published is False