@@ -652,3 +652,145 @@ def test_does_not_duplicate_entry_in_git_ignore(
652652 _deploy_without_waiting (respx_mock , tmp_path )
653653
654654 assert git_ignore_path .read_text () == ".fastapicloud\n "
655+
656+
657+ @pytest .mark .respx (base_url = settings .base_api_url )
658+ def test_creates_environment_variables_during_app_setup (
659+ logged_in_cli : None , tmp_path : Path , respx_mock : respx .MockRouter
660+ ) -> None :
661+ steps = [
662+ Keys .ENTER , # Setup and deploy
663+ Keys .ENTER , # Select team
664+ Keys .ENTER , # Create new app
665+ * "demo" , # App name
666+ Keys .ENTER ,
667+ Keys .ENTER , # Setup environment variables (Yes)
668+ * "API_KEY" , # Environment variable name
669+ Keys .ENTER ,
670+ * "secret123" , # Environment variable value
671+ Keys .ENTER ,
672+ Keys .ENTER , # Empty key to finish
673+ Keys .CTRL_C , # Exit before deployment
674+ ]
675+
676+ team = _get_random_team ()
677+ app_data = _get_random_app (team_id = team ["id" ])
678+
679+ respx_mock .get ("/teams/" ).mock (return_value = Response (200 , json = {"data" : [team ]}))
680+
681+ respx_mock .post ("/apps/" , json = {"name" : "demo" , "team_id" : team ["id" ]}).mock (
682+ return_value = Response (201 , json = app_data )
683+ )
684+
685+ env_vars_request = respx_mock .patch (
686+ f"/apps/{ app_data ['id' ]} /environment-variables/" , json = {"API_KEY" : "secret123" }
687+ ).mock (return_value = Response (200 ))
688+
689+ with changing_dir (tmp_path ), patch ("click.getchar" ) as mock_getchar :
690+ mock_getchar .side_effect = steps
691+
692+ result = runner .invoke (app , ["deploy" ])
693+
694+ assert result .exit_code == 1
695+ assert env_vars_request .called
696+ assert "Environment variables set up successfully!" in result .output
697+
698+
699+ @pytest .mark .respx (base_url = settings .base_api_url )
700+ def test_rejects_invalid_environment_variable_names (
701+ logged_in_cli : None , tmp_path : Path , respx_mock : respx .MockRouter
702+ ) -> None :
703+ steps = [
704+ Keys .ENTER , # Setup and deploy
705+ Keys .ENTER , # Select team
706+ Keys .ENTER , # Create new app
707+ * "demo" , # App name
708+ Keys .ENTER ,
709+ Keys .ENTER , # Setup environment variables (Yes)
710+ * "123-invalid" , # Invalid environment variable name (starts with digit, contains hyphen)
711+ Keys .ENTER ,
712+ * "VALID_KEY" , # Valid environment variable name
713+ Keys .ENTER ,
714+ * "value123" , # Environment variable value
715+ Keys .ENTER ,
716+ Keys .ENTER , # Empty key to finish
717+ Keys .CTRL_C , # Exit before deployment
718+ ]
719+
720+ team = _get_random_team ()
721+ app_data = _get_random_app (team_id = team ["id" ])
722+
723+ respx_mock .get ("/teams/" ).mock (return_value = Response (200 , json = {"data" : [team ]}))
724+
725+ respx_mock .post ("/apps/" , json = {"name" : "demo" , "team_id" : team ["id" ]}).mock (
726+ return_value = Response (201 , json = app_data )
727+ )
728+
729+ env_vars_request = respx_mock .patch (
730+ f"/apps/{ app_data ['id' ]} /environment-variables/" , json = {"VALID_KEY" : "value123" }
731+ ).mock (return_value = Response (200 ))
732+
733+ with changing_dir (tmp_path ), patch ("click.getchar" ) as mock_getchar :
734+ mock_getchar .side_effect = steps
735+
736+ result = runner .invoke (app , ["deploy" ])
737+
738+ assert result .exit_code == 1
739+ assert env_vars_request .called
740+ assert "Invalid environment variable name." in result .output
741+ assert "Environment variables set up successfully!" in result .output
742+
743+
744+ @pytest .mark .respx (base_url = settings .base_api_url )
745+ def test_shows_error_for_invalid_waitlist_form_data (
746+ logged_out_cli : None , tmp_path : Path , respx_mock : respx .MockRouter
747+ ) -> None :
748+ steps = [
749+ * "test@example.com" ,
750+ Keys .ENTER ,
751+ Keys .ENTER , # Choose to provide more information
752+ Keys .CTRL_C , # Interrupt to avoid infinite loop
753+ ]
754+
755+ with changing_dir (tmp_path ), patch ("rich_toolkit.menu.click.getchar" ) as mock_getchar , patch (
756+ "rich_toolkit.form.Form.run"
757+ ) as mock_form_run :
758+ mock_getchar .side_effect = steps
759+ # Simulate form returning data with invalid email field to trigger ValidationError
760+ mock_form_run .return_value = {"email" : "invalid-email-format" , "name" : "John Doe" }
761+
762+ result = runner .invoke (app , ["deploy" ])
763+
764+ assert result .exit_code == 1
765+ assert "Invalid form data. Please try again." in result .output
766+
767+
768+ @pytest .mark .respx (base_url = settings .base_api_url )
769+ def test_shows_no_apps_found_message_when_team_has_no_apps (
770+ logged_in_cli : None , tmp_path : Path , respx_mock : respx .MockRouter
771+ ) -> None :
772+ steps = [
773+ Keys .ENTER , # Setup and deploy
774+ Keys .ENTER , # Select team
775+ Keys .RIGHT_ARROW , # Choose existing app (No)
776+ Keys .ENTER ,
777+ ]
778+
779+ team = _get_random_team ()
780+
781+ respx_mock .get ("/teams/" ).mock (
782+ return_value = Response (200 , json = {"data" : [team ]})
783+ )
784+
785+ # Mock empty apps list for the team
786+ respx_mock .get ("/apps/" , params = {"team_id" : team ["id" ]}).mock (
787+ return_value = Response (200 , json = {"data" : []})
788+ )
789+
790+ with changing_dir (tmp_path ), patch ("click.getchar" ) as mock_getchar :
791+ mock_getchar .side_effect = steps
792+
793+ result = runner .invoke (app , ["deploy" ])
794+
795+ assert result .exit_code == 1
796+ assert "No apps found in this team. You can create a new app instead." in result .output
0 commit comments