@@ -18,12 +18,16 @@ import (
1818 "context"
1919 "testing"
2020
21+ "github.com/slackapi/slack-cli/internal/api"
22+ internalApp "github.com/slackapi/slack-cli/internal/app"
2123 "github.com/slackapi/slack-cli/internal/config"
2224 "github.com/slackapi/slack-cli/internal/iostreams"
2325 "github.com/slackapi/slack-cli/internal/pkg/create"
2426 "github.com/slackapi/slack-cli/internal/shared"
27+ "github.com/slackapi/slack-cli/internal/shared/types"
2528 "github.com/slackapi/slack-cli/internal/slackerror"
2629 "github.com/slackapi/slack-cli/test/testutil"
30+ "github.com/spf13/afero"
2731 "github.com/spf13/cobra"
2832 "github.com/stretchr/testify/assert"
2933 "github.com/stretchr/testify/mock"
@@ -884,3 +888,99 @@ func TestCreateCommand_AppFlag(t *testing.T) {
884888 return NewCreateCommand (cf )
885889 })
886890}
891+
892+ func TestCreateCommand_AppFlag_FetchesRemoteManifest (t * testing.T ) {
893+ var createClientMock * CreateClientMock
894+
895+ mockAuth := types.SlackAuth {
896+ Token : "xoxp-test-token" ,
897+ TeamDomain : "test-team" ,
898+ TeamID : "T001" ,
899+ UserID : "U001" ,
900+ }
901+ mockManifest := types.SlackYaml {
902+ AppManifest : types.AppManifest {
903+ DisplayInformation : types.DisplayInformation {
904+ Name : "My Remote App" ,
905+ Description : "An app from remote settings" ,
906+ },
907+ },
908+ }
909+
910+ setupAppFlagMocks := func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) string {
911+ projectDir := t .TempDir ()
912+ createClientMock = new (CreateClientMock )
913+ createClientMock .On ("Create" , mock .Anything , mock .Anything , mock .Anything ).Return (projectDir , nil )
914+ CreateFunc = createClientMock .Create
915+
916+ // Getwd is called to save original dir, then GetProjectDirPath calls it inside LinkExistingApp.
917+ // After os.Chdir, the second call should return the project dir.
918+ cm .Os .On ("Getwd" ).Return (projectDir , nil )
919+
920+ // Set up .slack/hooks.json so GetProjectDirPath validates the project
921+ err := cm .Fs .MkdirAll (projectDir + "/.slack" , 0755 )
922+ require .NoError (t , err )
923+ err = afero .WriteFile (cm .Fs , projectDir + "/.slack/hooks.json" , []byte ("{}" ), 0644 )
924+ require .NoError (t , err )
925+
926+ // Template selection returns via flag
927+ cm .IO .On ("SelectPrompt" , mock .Anything , "Select a category:" , mock .Anything , mock .Anything ).
928+ Return (iostreams.SelectPromptResponse {Flag : true , Option : "slack-samples/bolt-js-starter-template" }, nil )
929+
930+ // Link prompts
931+ cm .Auth .On ("Auths" , mock .Anything ).Return ([]types.SlackAuth {mockAuth }, nil )
932+ cm .IO .On ("SelectPrompt" , mock .Anything , "Select the existing app team" , mock .Anything , mock .Anything , mock .Anything ).
933+ Return (iostreams.SelectPromptResponse {Prompt : true , Index : 0 , Option : mockAuth .TeamDomain }, nil )
934+ cm .IO .On ("SelectPrompt" , mock .Anything , "Choose the app environment" , mock .Anything , mock .Anything , mock .Anything ).
935+ Return (iostreams.SelectPromptResponse {Prompt : true , Option : "local" }, nil )
936+
937+ cm .API .On ("GetAppStatus" , mock .Anything , mockAuth .Token , []string {"A0123456789" }, mockAuth .TeamID ).
938+ Return (api.GetAppStatusResult {}, nil )
939+
940+ return projectDir
941+ }
942+
943+ var projectDir string
944+
945+ testutil .TableTestCommand (t , testutil.CommandTests {
946+ "fetches remote manifest after linking app" : {
947+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "A0123456789" , "--environment" , "local" },
948+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
949+ projectDir = setupAppFlagMocks (t , ctx , cm , cf )
950+
951+ manifestMock := & internalApp.ManifestMockObject {}
952+ manifestMock .On ("GetManifestRemote" , mock .Anything , mockAuth .Token , "A0123456789" ).
953+ Return (mockManifest , nil )
954+ cf .AppClient ().Manifest = manifestMock
955+ },
956+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
957+ createClientMock .AssertCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
958+
959+ manifestData , err := afero .ReadFile (cm .Fs , projectDir + "/manifest.json" )
960+ require .NoError (t , err )
961+ assert .Contains (t , string (manifestData ), `"name": "My Remote App"` )
962+ assert .Contains (t , string (manifestData ), `"description": "An app from remote settings"` )
963+ },
964+ },
965+ "warns on manifest fetch failure" : {
966+ CmdArgs : []string {"my-app" , "--template" , "slack-samples/bolt-js-starter-template" , "--app" , "A0123456789" , "--environment" , "local" },
967+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
968+ projectDir = setupAppFlagMocks (t , ctx , cm , cf )
969+
970+ manifestMock := & internalApp.ManifestMockObject {}
971+ manifestMock .On ("GetManifestRemote" , mock .Anything , mockAuth .Token , "A0123456789" ).
972+ Return (types.SlackYaml {}, slackerror .New ("network error" ))
973+ cf .AppClient ().Manifest = manifestMock
974+ },
975+ ExpectedStdoutOutputs : []string {
976+ "Could not fetch the remote app manifest" ,
977+ "The template manifest was kept unchanged" ,
978+ },
979+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
980+ createClientMock .AssertCalled (t , "Create" , mock .Anything , mock .Anything , mock .Anything )
981+ },
982+ },
983+ }, func (cf * shared.ClientFactory ) * cobra.Command {
984+ return NewCreateCommand (cf )
985+ })
986+ }
0 commit comments