@@ -16,12 +16,17 @@ package project
1616
1717import (
1818 "context"
19+ "fmt"
1920 "testing"
2021
22+ "github.com/slackapi/slack-cli/internal/api"
23+ "github.com/slackapi/slack-cli/internal/app"
2124 "github.com/slackapi/slack-cli/internal/config"
2225 "github.com/slackapi/slack-cli/internal/iostreams"
2326 "github.com/slackapi/slack-cli/internal/pkg/create"
2427 "github.com/slackapi/slack-cli/internal/shared"
28+ "github.com/slackapi/slack-cli/internal/shared/types"
29+ "github.com/slackapi/slack-cli/internal/slackdeps"
2530 "github.com/slackapi/slack-cli/internal/slackerror"
2631 "github.com/slackapi/slack-cli/test/testutil"
2732 "github.com/spf13/cobra"
@@ -853,3 +858,157 @@ func TestCreateCommand_confirmExternalTemplateSelection(t *testing.T) {
853858 })
854859 }
855860}
861+
862+ func TestCreateCommand_AppFlag (t * testing.T ) {
863+ var createClientMock * CreateClientMock
864+
865+ testutil .TableTestCommand (t , testutil.CommandTests {
866+ "app flag without template flag returns error" : {
867+ CmdArgs : []string {"my-app" , "--app" , "A0123456789" },
868+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
869+ createClientMock = new (CreateClientMock )
870+ CreateFunc = createClientMock .Create
871+ },
872+ ExpectedErrorStrings : []string {"The --app flag requires the --template flag when used with create" },
873+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
874+ createClientMock .AssertNotCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
875+ },
876+ },
877+ "app flag with environment-style value returns error" : {
878+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "local" },
879+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
880+ createClientMock = new (CreateClientMock )
881+ CreateFunc = createClientMock .Create
882+ },
883+ ExpectedErrorStrings : []string {"The --app flag requires an app ID when used with create" },
884+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
885+ createClientMock .AssertNotCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
886+ },
887+ },
888+ "app flag with lowercase id returns error" : {
889+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "a0123456789" },
890+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
891+ createClientMock = new (CreateClientMock )
892+ CreateFunc = createClientMock .Create
893+ },
894+ ExpectedErrorStrings : []string {"The --app flag requires an app ID when used with create" },
895+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
896+ createClientMock .AssertNotCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
897+ },
898+ },
899+ "environment flag without app flag returns error" : {
900+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--environment" , "deployed" },
901+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
902+ createClientMock = new (CreateClientMock )
903+ CreateFunc = createClientMock .Create
904+ },
905+ ExpectedErrorStrings : []string {"The --environment flag requires the --app flag when used with create" },
906+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
907+ createClientMock .AssertNotCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
908+ },
909+ },
910+ "invalid environment flag returns error" : {
911+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "A0123456789" , "--environment" , "invalid" },
912+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
913+ createClientMock = new (CreateClientMock )
914+ CreateFunc = createClientMock .Create
915+ },
916+ ExpectedErrorStrings : []string {"The --environment flag must be either 'local' or 'deployed'" },
917+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
918+ createClientMock .AssertNotCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
919+ },
920+ },
921+ "app flag with template creates project and links a deployed app" : {
922+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "A0123456789" , "--environment" , "deployed" },
923+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
924+ createClientMock = new (CreateClientMock )
925+ createClientMock .On ("Create" , mock .Anything , mock .Anything , mock .Anything ).Return (t .TempDir (), nil )
926+ CreateFunc = createClientMock .Create
927+
928+ cm .Auth .On ("Auths" , mock .Anything ).Return ([]types.SlackAuth {mockCreateLinkAuth }, nil )
929+ cm .AddDefaultMocks ()
930+ setupCreateLinkMocks (t , ctx , cm , cf )
931+ cm .IO .On ("SelectPrompt" , mock .Anything , "Select a category:" , mock .Anything , mock .Anything , mock .Anything ).
932+ Return (iostreams.SelectPromptResponse {Flag : true , Option : "slack-samples/bolt-js-starter-template" }, nil ).Maybe ()
933+ cm .IO .On ("SelectPrompt" , mock .Anything , "Select the existing app team" , mock .Anything , mock .Anything , mock .Anything ).
934+ Return (iostreams.SelectPromptResponse {Flag : true , Option : mockCreateLinkAuth .TeamDomain }, nil )
935+ cm .IO .On ("InputPrompt" , mock .Anything , "Enter the existing app ID" , mock .Anything ).
936+ Return ("A0123456789" , nil )
937+ cm .IO .On ("SelectPrompt" , mock .Anything , "Choose the app environment" , mock .Anything , mock .Anything , mock .Anything ).
938+ Return (iostreams.SelectPromptResponse {Flag : true , Option : "deployed" }, nil )
939+ cm .API .On ("GetAppStatus" , mock .Anything , mockCreateLinkAuth .Token , []string {"A0123456789" }, mockCreateLinkAuth .TeamID ).
940+ Return (api.GetAppStatusResult {}, nil )
941+ },
942+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
943+ createClientMock .AssertCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
944+ saved , err := cm .AppClient .GetDeployed (ctx , mockCreateLinkAuth .TeamID )
945+ require .NoError (t , err )
946+ assert .Equal (t , "A0123456789" , saved .AppID )
947+ assert .Equal (t , mockCreateLinkAuth .TeamID , saved .TeamID )
948+ assert .False (t , saved .IsDev )
949+ },
950+ },
951+ "app flag without environment links a local app via prompt" : {
952+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "A0123456789" },
953+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
954+ createClientMock = new (CreateClientMock )
955+ createClientMock .On ("Create" , mock .Anything , mock .Anything , mock .Anything ).Return (t .TempDir (), nil )
956+ CreateFunc = createClientMock .Create
957+
958+ cm .Auth .On ("Auths" , mock .Anything ).Return ([]types.SlackAuth {mockCreateLinkAuth }, nil )
959+ cm .AddDefaultMocks ()
960+ setupCreateLinkMocks (t , ctx , cm , cf )
961+ cm .IO .On ("SelectPrompt" , mock .Anything , "Select a category:" , mock .Anything , mock .Anything , mock .Anything ).
962+ Return (iostreams.SelectPromptResponse {Flag : true , Option : "slack-samples/bolt-js-starter-template" }, nil ).Maybe ()
963+ cm .IO .On ("SelectPrompt" , mock .Anything , "Select the existing app team" , mock .Anything , mock .Anything , mock .Anything ).
964+ Return (iostreams.SelectPromptResponse {Prompt : true , Option : mockCreateLinkAuth .TeamDomain }, nil )
965+ cm .IO .On ("InputPrompt" , mock .Anything , "Enter the existing app ID" , mock .Anything ).
966+ Return ("A0123456789" , nil )
967+ cm .IO .On ("SelectPrompt" , mock .Anything , "Choose the app environment" , mock .Anything , mock .Anything , mock .Anything ).
968+ Return (iostreams.SelectPromptResponse {Prompt : true , Option : "local" }, nil )
969+ cm .API .On ("GetAppStatus" , mock .Anything , mockCreateLinkAuth .Token , []string {"A0123456789" }, mockCreateLinkAuth .TeamID ).
970+ Return (api.GetAppStatusResult {}, nil )
971+ },
972+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
973+ createClientMock .AssertCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
974+ saved , err := cm .AppClient .GetLocal (ctx , mockCreateLinkAuth .TeamID )
975+ require .NoError (t , err )
976+ assert .Equal (t , "A0123456789" , saved .AppID )
977+ assert .Equal (t , mockCreateLinkAuth .TeamID , saved .TeamID )
978+ assert .True (t , saved .IsDev )
979+ },
980+ },
981+ }, func (cf * shared.ClientFactory ) * cobra.Command {
982+ return NewCreateCommand (cf )
983+ })
984+ }
985+
986+ var mockCreateLinkAuth = types.SlackAuth {
987+ Token : "xoxp-example" ,
988+ TeamDomain : "team1" ,
989+ TeamID : "T001" ,
990+ EnterpriseID : "E001" ,
991+ UserID : "U001" ,
992+ }
993+
994+ // setupCreateLinkMocks prepares the in-memory project config and manifest mocks
995+ // needed by app.LinkExistingApp when called from the create command.
996+ func setupCreateLinkMocks (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
997+ projectDirPath := slackdeps .MockWorkingDirectory
998+ cm .Os .On ("Getwd" ).Return (projectDirPath , nil )
999+
1000+ if _ , err := config .CreateProjectConfigDir (ctx , cm .Fs , projectDirPath ); err != nil {
1001+ require .FailNow (t , fmt .Sprintf ("Failed to create the project config directory: %s" , err ))
1002+ }
1003+ if _ , err := config .CreateProjectHooksJSONFile (cm .Fs , projectDirPath , []byte ("{}" )); err != nil {
1004+ require .FailNow (t , fmt .Sprintf ("Failed to create the hooks file: %s" , err ))
1005+ }
1006+ if err := config .SetManifestSource (ctx , cm .Fs , cm .Os , config .ManifestSourceRemote ); err != nil {
1007+ require .FailNow (t , fmt .Sprintf ("Failed to set the manifest source: %s" , err ))
1008+ }
1009+
1010+ manifestMock := & app.ManifestMockObject {}
1011+ manifestMock .On ("GetManifestLocal" , mock .Anything , mock .Anything , mock .Anything ).
1012+ Return (types.SlackYaml {}, nil )
1013+ cf .AppClient ().Manifest = manifestMock
1014+ }
0 commit comments