Coverage for tests/test_env_get.py: 100%

74 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-11-09 00:25 +0000

1import json 1abcdefg

2from unittest.mock import patch 1abcdefg

3 

4import pytest 1abcdefg

5import respx 1abcdefg

6from httpx import Response 1abcdefg

7from inline_snapshot import snapshot 1abcdefg

8 

9from fastapi_cloud_cli.cli import cloud_app as app 1abcdefg

10from tests.conftest import ConfiguredApp 1abcdefg

11from tests.utils import Keys, SnapshotCliRunner, changing_dir 1abcdefg

12 

13runner = SnapshotCliRunner() 1abcdefg

14 

15 

16def test_shows_a_message_if_not_logged_in(logged_out_cli: None) -> None: 1abcdefg

17 result = runner.invoke(app, ["env", "get", "LOG_LEVEL"]) 1#$%'()*

18 

19 assert result.exit_code == 1 1#$%'()*

20 assert "No credentials found." in result.output 1#$%'()*

21 

22 

23@pytest.mark.respx 1abcdefg

24def test_shows_message_if_no_environment_variables( 1abcdefg

25 logged_in_cli: None, respx_mock: respx.MockRouter, configured_app: ConfiguredApp 

26) -> None: 

27 respx_mock.get(f"/apps/{configured_app.app_id}/environment-variables/").mock( 1JKLMNOP

28 return_value=Response(200, json={"data": []}) 

29 ) 

30 

31 with changing_dir(configured_app.path): 1JKLMNOP

32 result = runner.invoke(app, ["env", "get"]) 1JKLMNOP

33 

34 assert result.exit_code == 0 1JKLMNOP

35 assert result.output == snapshot("""\ 1JKLMNOP

36environment variables 

37 

38No environment variables found.\ 

39""") 

40 

41 

42@pytest.mark.respx 1abcdefg

43def test_gets_environment_variable_in_human_output_with_environment_variables_tag( 1abcdefg

44 logged_in_cli: None, respx_mock: respx.MockRouter 

45) -> None: 

46 app_id = "00000000-0000-4000-8000-000000000002" 1QRSTUVW

47 respx_mock.get(f"/apps/{app_id}/environment-variables/").mock( 1QRSTUVW

48 return_value=Response( 

49 200, 

50 json={ 

51 "data": [ 

52 { 

53 "name": "LOG_LEVEL", 

54 "value": "info", 

55 "is_secret": False, 

56 } 

57 ] 

58 }, 

59 ) 

60 ) 

61 

62 result = runner.invoke(app, ["env", "get", "LOG_LEVEL", "--app-id", app_id]) 1QRSTUVW

63 

64 assert result.exit_code == 0 1QRSTUVW

65 assert result.output == snapshot("""\ 1QRSTUVW

66environment variables 

67 

68name: LOG_LEVEL 

69value: info\ 

70""") 

71 

72 

73@pytest.mark.respx 1abcdefg

74def test_gets_secret_environment_variable_in_human_output( 1abcdefg

75 logged_in_cli: None, respx_mock: respx.MockRouter 

76) -> None: 

77 app_id = "00000000-0000-4000-8000-000000000002" 1XYZ0123

78 respx_mock.get(f"/apps/{app_id}/environment-variables/").mock( 1XYZ0123

79 return_value=Response( 

80 200, 

81 json={ 

82 "data": [ 

83 { 

84 "name": "DATABASE_URL", 

85 "is_secret": True, 

86 } 

87 ] 

88 }, 

89 ) 

90 ) 

91 

92 result = runner.invoke(app, ["env", "get", "DATABASE_URL", "--app-id", app_id]) 1XYZ0123

93 

94 assert result.exit_code == 0 1XYZ0123

95 assert result.output == snapshot("""\ 1XYZ0123

96environment variables 

97 

98name: DATABASE_URL 

99value: [secret]\ 

100""") 

101 

102 

103@pytest.mark.respx 1abcdefg

104def test_get_prompts_for_environment_variable_name( 1abcdefg

105 logged_in_cli: None, respx_mock: respx.MockRouter 

106) -> None: 

107 app_id = "00000000-0000-4000-8000-000000000002" 1vwxyzAB

108 respx_mock.get(f"/apps/{app_id}/environment-variables/").mock( 1vwxyzAB

109 return_value=Response( 

110 200, 

111 json={ 

112 "data": [ 

113 { 

114 "name": "DEMO", 

115 "value": "VALUE", 

116 "is_secret": False, 

117 }, 

118 { 

119 "name": "OTHER", 

120 "value": "ignored", 

121 "is_secret": False, 

122 }, 

123 ] 

124 }, 

125 ) 

126 ) 

127 

128 with patch("rich_toolkit.container.getchar", side_effect=[Keys.ENTER]): 1vwxyzAB

129 result = runner.invoke(app, ["env", "get", "--app-id", app_id]) 1vwxyzAB

130 

131 assert result.exit_code == 0 1vwxyzAB

132 assert result.output == snapshot("""\ 1vwxyzAB

133environment variables 

134 

135Select the environment variable to get: 

136● DEMO 

137○ OTHER 

138 

139Select the environment variable to get: DEMO 

140 

141name: DEMO 

142value: VALUE\ 

143""") 

144 

145 

146def test_get_json_returns_missing_required_input_without_name( 1abcdefg

147 logged_in_cli: None, 

148) -> None: 

149 result = runner.invoke( 1456789!

150 app, 

151 [ 

152 "env", 

153 "get", 

154 "--app-id", 

155 "00000000-0000-4000-8000-000000000002", 

156 "--json", 

157 ], 

158 ) 

159 

160 assert result.exit_code == 1 1456789!

161 assert json.loads(result.stdout) == { 1456789!

162 "error": { 

163 "code": "missing_required_input", 

164 "message": "Environment variable name is required.", 

165 "hint": "Pass NAME to choose an environment variable.", 

166 } 

167 } 

168 assert result.stderr == "" 1456789!

169 

170 

171@pytest.mark.respx 1abcdefg

172def test_gets_secret_environment_variable_as_json( 1abcdefg

173 logged_in_cli: None, respx_mock: respx.MockRouter 

174) -> None: 

175 app_id = "00000000-0000-4000-8000-000000000002" 1hijklmn

176 variable = { 1hijklmn

177 "name": "DATABASE_URL", 

178 "is_secret": True, 

179 "updated_at": "2026-05-22T10:00:00Z", 

180 } 

181 respx_mock.get(f"/apps/{app_id}/environment-variables/").mock( 1hijklmn

182 return_value=Response(200, json={"data": [variable]}) 

183 ) 

184 

185 result = runner.invoke( 1hijklmn

186 app, ["env", "get", "DATABASE_URL", "--app-id", app_id, "--json"] 

187 ) 

188 

189 assert result.exit_code == 0 1hijklmn

190 assert json.loads(result.stdout) == { 1hijklmn

191 "data": { 

192 "app_id": app_id, 

193 "variable": { 

194 "name": "DATABASE_URL", 

195 "value": None, 

196 "is_secret": True, 

197 "updated_at": "2026-05-22T10:00:00Z", 

198 }, 

199 } 

200 } 

201 assert result.stderr == "" 1hijklmn

202 

203 

204@pytest.mark.respx 1abcdefg

205def test_gets_non_secret_environment_variable_as_json( 1abcdefg

206 logged_in_cli: None, respx_mock: respx.MockRouter 

207) -> None: 

208 app_id = "00000000-0000-4000-8000-000000000002" 1opqrstu

209 variable = { 1opqrstu

210 "name": "LOG_LEVEL", 

211 "value": "info", 

212 "is_secret": False, 

213 "updated_at": "2026-05-22T10:00:00Z", 

214 } 

215 respx_mock.get(f"/apps/{app_id}/environment-variables/").mock( 1opqrstu

216 return_value=Response(200, json={"data": [variable]}) 

217 ) 

218 

219 result = runner.invoke( 1opqrstu

220 app, ["env", "get", "LOG_LEVEL", "--app-id", app_id, "--json"] 

221 ) 

222 

223 assert result.exit_code == 0 1opqrstu

224 assert json.loads(result.stdout) == { 1opqrstu

225 "data": { 

226 "app_id": app_id, 

227 "variable": variable, 

228 } 

229 } 

230 assert result.stderr == "" 1opqrstu

231 

232 

233@pytest.mark.respx 1abcdefg

234def test_get_environment_variable_json_returns_not_found( 1abcdefg

235 logged_in_cli: None, respx_mock: respx.MockRouter 

236) -> None: 

237 app_id = "00000000-0000-4000-8000-000000000002" 1CDEFGHI

238 respx_mock.get(f"/apps/{app_id}/environment-variables/").mock( 1CDEFGHI

239 return_value=Response( 

240 200, 

241 json={ 

242 "data": [ 

243 { 

244 "name": "LOG_LEVEL", 

245 "value": "info", 

246 "is_secret": False, 

247 } 

248 ] 

249 }, 

250 ) 

251 ) 

252 

253 result = runner.invoke( 1CDEFGHI

254 app, ["env", "get", "DATABASE_URL", "--app-id", app_id, "--json"] 

255 ) 

256 

257 assert result.exit_code == 1 1CDEFGHI

258 assert json.loads(result.stdout) == { 1CDEFGHI

259 "error": { 

260 "code": "not_found", 

261 "message": "Environment variable DATABASE_URL not found.", 

262 "hint": "Run `fastapi cloud env list` to see available variables.", 

263 } 

264 } 

265 assert result.stderr == "" 1CDEFGHI