Coverage for databases/sync_tests/test_find_many.py: 100%

118 statements  

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

1import pytest 

2 

3import prisma 

4from prisma import Prisma 

5 

6 

7def test_find_many(client: Prisma) -> None: 

8 """Filters and ordering work as suggested""" 

9 posts = [ 

10 client.post.create({'title': 'Test post 1', 'published': False}), 

11 client.post.create({'title': 'Test post 2', 'published': False}), 

12 ] 

13 found = client.post.find_many(where={'title': 'Test post 1'}) 

14 assert len(found) == 1 

15 assert found[0].id == posts[0].id 

16 

17 posts = client.post.find_many(where={'OR': [{'title': 'Test post 1'}, {'title': 'Test post 2'}]}) 

18 assert len(posts) == 2 

19 

20 posts = client.post.find_many(where={'title': {'contains': 'Test post'}}) 

21 assert len(posts) == 2 

22 

23 posts = client.post.find_many(where={'title': {'startswith': 'Test post'}}) 

24 assert len(posts) == 2 

25 

26 posts = client.post.find_many(where={'title': {'not_in': ['Test post 1']}}) 

27 assert len(posts) == 1 

28 assert posts[0].title == 'Test post 2' 

29 

30 posts = client.post.find_many(where={'title': {'equals': 'Test post 2'}}) 

31 assert len(posts) == 1 

32 assert posts[0].title == 'Test post 2' 

33 

34 posts = client.post.find_many(where={'title': 'Test post 2'}) 

35 assert len(posts) == 1 

36 assert posts[0].title == 'Test post 2' 

37 

38 posts = client.post.find_many(order={'title': 'desc'}) 

39 assert len(posts) == 2 

40 assert posts[0].title == 'Test post 2' 

41 assert posts[1].title == 'Test post 1' 

42 

43 posts = client.post.find_many(order={'title': 'asc'}) 

44 assert len(posts) == 2 

45 assert posts[0].title == 'Test post 1' 

46 assert posts[1].title == 'Test post 2' 

47 

48 

49def test_cursor(client: Prisma) -> None: 

50 """Cursor argument correctly paginates results""" 

51 posts = [ 

52 client.post.create({'title': 'Foo 1', 'published': False}), 

53 client.post.create({'title': 'Foo 2', 'published': False}), 

54 client.post.create({'title': 'Foo 3', 'published': False}), 

55 client.post.create({'title': 'Foo 4', 'published': False}), 

56 ] 

57 found = client.post.find_many( 

58 cursor={ 

59 'id': posts[1].id, 

60 }, 

61 order={ 

62 'title': 'asc', 

63 }, 

64 ) 

65 assert len(found) == 3 

66 assert found[0].title == 'Foo 2' 

67 assert found[1].title == 'Foo 3' 

68 assert found[2].title == 'Foo 4' 

69 

70 found = client.post.find_many( 

71 cursor={ 

72 'id': posts[3].id, 

73 }, 

74 order={ 

75 'title': 'asc', 

76 }, 

77 ) 

78 assert len(found) == 1 

79 assert found[0].title == 'Foo 4' 

80 

81 

82def test_filtering_one_to_one_relation(client: Prisma) -> None: 

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

84 with client.batch_() as batcher: 

85 batcher.user.create( 

86 { 

87 'name': 'Robert', 

88 'profile': { 

89 'create': { 

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

91 'country': 'Scotland', 

92 } 

93 }, 

94 }, 

95 ) 

96 batcher.user.create( 

97 { 

98 'name': 'Tegan', 

99 'profile': { 

100 'create': { 

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

102 'country': 'Scotland', 

103 }, 

104 }, 

105 }, 

106 ) 

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

108 

109 users = client.user.find_many( 

110 where={ 

111 'profile': { 

112 'is': { 

113 'description': { 

114 'contains': 'cool', 

115 } 

116 } 

117 } 

118 } 

119 ) 

120 assert len(users) == 1 

121 assert users[0].name == 'Robert' 

122 assert users[0].profile is None 

123 

124 users = client.user.find_many( 

125 where={ 

126 'profile': { 

127 'is': { 

128 'description': { 

129 'contains': 'bio', 

130 }, 

131 }, 

132 }, 

133 }, 

134 order={ 

135 'name': 'asc', 

136 }, 

137 ) 

138 assert len(users) == 2 

139 assert users[0].name == 'Robert' 

140 assert users[1].name == 'Tegan' 

141 

142 users = client.user.find_many( 

143 where={ 

144 'profile': { 

145 'is_not': { 

146 'description': { 

147 'contains': 'bio', 

148 } 

149 } 

150 } 

151 } 

152 ) 

153 assert len(users) == 1 

154 assert users[0].name == 'Callum' 

155 

156 

157def test_filtering_one_to_many_relation(client: Prisma) -> None: 

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

159 with client.batch_() as batcher: 

160 batcher.user.create( 

161 { 

162 'name': 'Robert', 

163 'posts': { 

164 'create': [ 

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

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

167 ] 

168 }, 

169 } 

170 ) 

171 batcher.user.create( 

172 { 

173 'name': 'Tegan', 

174 'posts': { 

175 'create': [ 

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

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

178 ] 

179 }, 

180 } 

181 ) 

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

183 

184 # I guess it makes sense that a record with no relations also matches this 

185 # TODO: this needs to be documented 

186 users = client.user.find_many( 

187 where={ 

188 'posts': { 

189 'every': { 

190 'title': { 

191 'contains': 'post', 

192 } 

193 } 

194 } 

195 }, 

196 ) 

197 assert len(users) == 2 

198 assert users[0].name == 'Robert' 

199 assert users[1].name == 'Callum' 

200 

201 users = client.user.find_many( 

202 where={ 

203 'posts': { 

204 'some': { 

205 'title': { 

206 'contains': 'post', 

207 } 

208 } 

209 } 

210 }, 

211 order={ 

212 'name': 'asc', 

213 }, 

214 ) 

215 assert len(users) == 2 

216 assert users[0].name == 'Robert' 

217 assert users[1].name == 'Tegan' 

218 

219 users = client.user.find_many( 

220 where={ 

221 'posts': { 

222 'none': { 

223 'title': { 

224 'contains': 'post', 

225 } 

226 } 

227 } 

228 } 

229 ) 

230 assert len(users) == 1 

231 assert users[0].name == 'Callum' 

232 

233 users = client.user.find_many( 

234 where={ 

235 'posts': { 

236 'some': { 

237 'title': 'foo', 

238 } 

239 } 

240 } 

241 ) 

242 assert len(users) == 0 

243 

244 

245def test_ordering(client: Prisma) -> None: 

246 """Ordering by `asc` and `desc` correctly changes the order of the returned records""" 

247 with client.batch_() as batcher: 

248 batcher.post.create({'title': 'Test post 1', 'published': False}) 

249 batcher.post.create({'title': 'Test post 2', 'published': False}) 

250 batcher.post.create({'title': 'Test post 3', 'published': True}) 

251 

252 found = client.post.find_many( 

253 where={'title': {'contains': 'Test'}}, 

254 order={'published': 'asc'}, 

255 ) 

256 assert len(found) == 3 

257 assert found[0].published is False 

258 assert found[1].published is False 

259 assert found[2].published is True 

260 

261 found = client.post.find_many( 

262 where={'title': {'contains': 'Test'}}, 

263 order={'published': 'desc'}, 

264 ) 

265 assert len(found) == 3 

266 assert found[0].published is True 

267 assert found[1].published is False 

268 assert found[2].published is False 

269 

270 # multiple fields in the same `order` dictionary are not supported 

271 with pytest.raises(prisma.errors.DataError): 

272 client.post.find_many( 

273 where={ 

274 'title': { 

275 'contains': 'Test', 

276 }, 

277 }, 

278 order={ # type: ignore 

279 'published': 'desc', 

280 'title': 'desc', 

281 }, 

282 ) 

283 

284 

285def test_order_field_not_nullable(client: Prisma) -> None: 

286 """Order by fields, if present, cannot be None""" 

287 with pytest.raises(prisma.errors.FieldNotFoundError) as exc: 

288 client.post.find_many(order={'desc': None}) # type: ignore 

289 

290 assert exc.match(r'desc') 

291 

292 

293def test_distinct(client: Prisma) -> None: 

294 """Filtering by distinct combinations of fields""" 

295 users = [ 

296 client.user.create( 

297 data={ 

298 'name': 'Robert', 

299 }, 

300 ), 

301 client.user.create( 

302 data={ 

303 'name': 'Tegan', 

304 }, 

305 ), 

306 client.user.create( 

307 data={ 

308 'name': 'Patrick', 

309 }, 

310 ), 

311 ] 

312 with client.batch_() as batcher: 

313 batcher.profile.create( 

314 { 

315 'city': 'Paris', 

316 'country': 'France', 

317 'description': 'Foo', 

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

319 } 

320 ) 

321 batcher.profile.create( 

322 { 

323 'city': 'Lyon', 

324 'country': 'France', 

325 'description': 'Foo', 

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

327 } 

328 ) 

329 batcher.profile.create( 

330 { 

331 'city': 'Paris', 

332 'country': 'Denmark', 

333 'description': 'Foo', 

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

335 } 

336 ) 

337 

338 results = client.profile.find_many( 

339 distinct=['country'], 

340 order={ 

341 'country': 'asc', 

342 }, 

343 ) 

344 assert len(results) == 2 

345 assert results[0].country == 'Denmark' 

346 assert results[1].country == 'France' 

347 

348 results = client.profile.find_many( 

349 distinct=['city'], 

350 order={ 

351 'city': 'asc', 

352 }, 

353 ) 

354 assert len(results) == 2 

355 assert results[0].city == 'Lyon' 

356 assert results[1].city == 'Paris' 

357 

358 results = client.profile.find_many( 

359 distinct=['city', 'country'], 

360 order=[ 

361 { 

362 'city': 'asc', 

363 }, 

364 { 

365 'country': 'asc', 

366 }, 

367 ], 

368 ) 

369 assert len(results) == 3 

370 assert results[0].city == 'Lyon' 

371 assert results[0].country == 'France' 

372 assert results[1].city == 'Paris' 

373 assert results[1].country == 'Denmark' 

374 assert results[2].city == 'Paris' 

375 assert results[2].country == 'France'