Coverage for tests/test_generation/test_validation.py: 100%

82 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-28 15:17 +0000

1import re 

2import subprocess 

3 

4import pytest 

5 

6from prisma.utils import temp_env_update 

7 

8from ..utils import Testdir 

9 

10 

11def _remove_known_warnings(output: str) -> str: 

12 # as we run generation under coverage we need to remove any warnings 

13 # for example, coverage.py will warn that the tests module was not imported 

14 output = re.sub(r'.*prisma:GeneratorProcess .* CoverageWarning:.*', '', output) 

15 output = re.sub(r'.*prisma:GeneratorProcess .* was never imported.*', '', output) 

16 

17 # unknown why this is logged but it doesn't seem to effect anything 

18 output = re.sub( 

19 r'.*prisma:GeneratorProcess child exited with code null.*', 

20 '', 

21 output, 

22 ) 

23 

24 return output 

25 

26 

27def assert_no_generator_output(output: str) -> None: 

28 assert 'prisma:GeneratorProcess' not in _remove_known_warnings(output) 

29 

30 

31def test_model_name_python_keyword(testdir: Testdir) -> None: 

32 """Model name shadowing a python keyword is not allowed""" 

33 schema = ( 

34 testdir.SCHEMA_HEADER 

35 + """ 

36 model from {{ 

37 id String @id 

38 name String 

39 }} 

40 """ 

41 ) 

42 with pytest.raises(subprocess.CalledProcessError) as exc: 

43 testdir.generate(schema=schema) 

44 

45 assert 'Model name "from" shadows a Python keyword; use a different model name with \'@@map("from")\'' in str( 

46 exc.value.output, 'utf-8' 

47 ) 

48 

49 

50def test_model_name_lowercase_python_keyword(testdir: Testdir) -> None: 

51 """Model name that when transformed to lowercase a python keyword is not allowed""" 

52 schema = ( 

53 testdir.SCHEMA_HEADER 

54 + """ 

55 model Class {{ 

56 id String @id 

57 name String 

58 }} 

59 """ 

60 ) 

61 with pytest.raises(subprocess.CalledProcessError) as exc: 

62 testdir.generate(schema=schema) 

63 

64 assert ( 

65 'Model name "Class" results in a client property that shadows a Python keyword; use a different model name with \'@@map("Class")\'' 

66 in str(exc.value.output, 'utf-8') 

67 ) 

68 

69 

70def test_field_name_basemodel_attribute(testdir: Testdir) -> None: 

71 """Field name shadowing a basemodel attribute is not allowed""" 

72 schema = ( 

73 testdir.SCHEMA_HEADER 

74 + """ 

75 model User {{ 

76 id String @id 

77 json String 

78 }} 

79 """ 

80 ) 

81 with pytest.raises(subprocess.CalledProcessError) as exc: 

82 testdir.generate(schema=schema) 

83 

84 assert ( 

85 'Field name "json" shadows a BaseModel attribute; ' 

86 'use a different field name with \'@map("json")\'' in str(exc.value.output, 'utf-8') 

87 ) 

88 

89 

90def test_field_name_python_keyword(testdir: Testdir) -> None: 

91 """Field name shadowing a python keyword is not allowed""" 

92 schema = ( 

93 testdir.SCHEMA_HEADER 

94 + """ 

95 model User {{ 

96 id String @id 

97 from String 

98 }} 

99 """ 

100 ) 

101 with pytest.raises(subprocess.CalledProcessError) as exc: 

102 testdir.generate(schema=schema) 

103 

104 assert 'Field name "from" shadows a Python keyword; use a different field name with \'@map("from")\'' in str( 

105 exc.value.output, 'utf-8' 

106 ) 

107 

108 

109def test_field_name_prisma_not_allowed(testdir: Testdir) -> None: 

110 """Field name "prisma" is not allowed as it overrides our own method""" 

111 schema = ( 

112 testdir.SCHEMA_HEADER 

113 + """ 

114 model User {{ 

115 id String @id 

116 prisma String 

117 }} 

118 """ 

119 ) 

120 with pytest.raises(subprocess.CalledProcessError) as exc: 

121 testdir.generate(schema=schema) 

122 

123 assert ( 

124 'Field name "prisma" shadows a Prisma Client Python method; ' 

125 'use a different field name with \'@map("prisma")\'' 

126 ) in str(exc.value.output, 'utf-8') 

127 

128 

129def test_field_name_matching_query_builder_alias_not_allowed( 

130 testdir: Testdir, 

131) -> None: 

132 """A field name that is the same as an alias used by our internal query builder 

133 is not allowed as it will lead to confusing error messages 

134 

135 https://github.com/RobertCraigie/prisma-client-py/issues/124 

136 """ 

137 schema = ( 

138 testdir.SCHEMA_HEADER 

139 + """ 

140 model User {{ 

141 id String @id 

142 order_by String 

143 }} 

144 """ 

145 ) 

146 with pytest.raises(subprocess.CalledProcessError) as exc: 

147 testdir.generate(schema=schema) 

148 

149 assert ( 

150 'Field name "order_by" shadows an internal keyword; ' 'use a different field name with \'@map("order_by")\'' 

151 ) in str(exc.value.output, 'utf-8') 

152 

153 

154def test_custom_model_instance_name_not_valid_identifier( 

155 testdir: Testdir, 

156) -> None: 

157 schema = ( 

158 testdir.SCHEMA_HEADER 

159 + """ 

160 /// @Python(instance_name: "1") 

161 model User {{ 

162 id String @id 

163 }} 

164 """ 

165 ) 

166 with pytest.raises(subprocess.CalledProcessError) as exc: 

167 testdir.generate(schema=schema) 

168 

169 assert 'Custom Model instance_name "1" is not a valid Python identifier' in str(exc.value.output, 'utf-8') 

170 

171 

172def test_native_binary_target_no_warning(testdir: Testdir) -> None: 

173 """binaryTargets only being native does not raise warning""" 

174 with temp_env_update({'PRISMA_PY_DEBUG': '0'}): 

175 result = testdir.generate(options='binaryTargets = ["native"]') 

176 

177 stdout = _remove_known_warnings(result.stdout.decode('utf-8')) 

178 assert 'Warning' not in stdout 

179 assert 'binaryTargets option' not in stdout 

180 assert_no_generator_output(stdout) 

181 

182 

183def test_binary_targets_warning(testdir: Testdir) -> None: 

184 """Binary targets option being present raises a warning""" 

185 with temp_env_update({'PRISMA_PY_DEBUG': '0'}): 

186 result = testdir.generate(options='binaryTargets = ["native", "rhel-openssl-1.1.x"]') 

187 

188 stdout = result.stdout.decode('utf-8') 

189 assert_no_generator_output(stdout) 

190 assert 'Warning: The binaryTargets option ' 'is not officially supported by Prisma Client Python' in stdout 

191 

192 

193@pytest.mark.parametrize( 

194 'http,new', 

195 [ 

196 ('aiohttp', 'asyncio'), 

197 ('requests', 'sync'), 

198 ], 

199) 

200def test_old_http_option(testdir: Testdir, http: str, new: str) -> None: 

201 """A helpful error is raised if the old http config option is used""" 

202 with pytest.raises(subprocess.CalledProcessError) as exc: 

203 testdir.generate(options=f'http = "{http}"') 

204 

205 stdout = exc.value.stdout.decode('utf-8') 

206 assert 'The http option has been removed ' 'in favour of the interface option.' in stdout 

207 assert 'Please remove the http option from ' 'your Prisma schema and replace it with:' in stdout 

208 assert f'interface = "{new}"' in stdout 

209 

210 

211def test_decimal_type_experimental(testdir: Testdir) -> None: 

212 """The Decimal type requires a config flag to be set""" 

213 schema = ( 

214 testdir.SCHEMA_HEADER 

215 + """ 

216 model User {{ 

217 id String @id @default(cuid()) 

218 points Decimal 

219 }} 

220 """ 

221 ) 

222 with pytest.raises(subprocess.CalledProcessError) as exc: 

223 testdir.generate(schema=schema) 

224 

225 output = str(exc.value.output, 'utf-8') 

226 assert 'Support for the Decimal type is experimental' in output 

227 assert 'set the `enable_experimental_decimal` config flag to true' in output 

228 

229 

230def test_composite_type_not_supported(testdir: Testdir) -> None: 

231 """Composite types are not supported yet""" 

232 schema = ( 

233 testdir.default_generator 

234 + """ 

235 datasource db {{ 

236 provider = "mongodb" 

237 url = env("foo") 

238 }} 

239 

240 model User {{ 

241 id String @id @map("_id") 

242 // settings UserSettings 

243 }} 

244 

245 type UserSettings {{ 

246 points Decimal 

247 }} 

248 """ 

249 ) 

250 with pytest.raises(subprocess.CalledProcessError) as exc: 

251 testdir.generate(schema=schema) 

252 

253 output = str(exc.value.output, 'utf-8') 

254 assert 'Composite types are not supported yet.' in output 

255 assert 'https://github.com/RobertCraigie/prisma-client-py/issues/314' in output