@@ -652,3 +652,149 @@ 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+ 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 (
756+ "rich_toolkit.menu.click.getchar"
757+ ) as mock_getchar , patch ("rich_toolkit.form.Form.run" ) 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 = {
761+ "email" : "invalid-email-format" ,
762+ "name" : "John Doe" ,
763+ }
764+
765+ result = runner .invoke (app , ["deploy" ])
766+
767+ assert result .exit_code == 1
768+ assert "Invalid form data. Please try again." in result .output
769+
770+
771+ @pytest .mark .respx (base_url = settings .base_api_url )
772+ def test_shows_no_apps_found_message_when_team_has_no_apps (
773+ logged_in_cli : None , tmp_path : Path , respx_mock : respx .MockRouter
774+ ) -> None :
775+ steps = [
776+ Keys .ENTER , # Setup and deploy
777+ Keys .ENTER , # Select team
778+ Keys .RIGHT_ARROW , # Choose existing app (No)
779+ Keys .ENTER ,
780+ ]
781+
782+ team = _get_random_team ()
783+
784+ respx_mock .get ("/teams/" ).mock (return_value = Response (200 , json = {"data" : [team ]}))
785+
786+ # Mock empty apps list for the team
787+ respx_mock .get ("/apps/" , params = {"team_id" : team ["id" ]}).mock (
788+ return_value = Response (200 , json = {"data" : []})
789+ )
790+
791+ with changing_dir (tmp_path ), patch ("click.getchar" ) as mock_getchar :
792+ mock_getchar .side_effect = steps
793+
794+ result = runner .invoke (app , ["deploy" ])
795+
796+ assert result .exit_code == 1
797+ assert (
798+ "No apps found in this team. You can create a new app instead."
799+ in result .output
800+ )
0 commit comments