github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/intents/intents_test.go (about) 1 package intents 2 3 import ( 4 "testing" 5 6 "github.com/cozy/cozy-stack/model/app" 7 "github.com/cozy/cozy-stack/model/instance/lifecycle" 8 "github.com/cozy/cozy-stack/model/permission" 9 "github.com/cozy/cozy-stack/pkg/config/config" 10 "github.com/cozy/cozy-stack/pkg/consts" 11 "github.com/cozy/cozy-stack/pkg/couchdb" 12 "github.com/cozy/cozy-stack/tests/testutils" 13 "github.com/cozy/cozy-stack/web/errors" 14 "github.com/gavv/httpexpect/v2" 15 "github.com/labstack/echo/v4" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestIntents(t *testing.T) { 20 if testing.Short() { 21 t.Skip("an instance is required for this test: test skipped due to the use of --short flag") 22 } 23 24 var err error 25 var intentID string 26 27 config.UseTestFile(t) 28 testutils.NeedCouchdb(t) 29 setup := testutils.NewSetup(t, t.Name()) 30 ins := setup.GetTestInstance(&lifecycle.Options{ 31 Domain: "cozy.example.net", 32 }) 33 _, _ = setup.GetTestClient(consts.Settings) 34 35 webapp := &couchdb.JSONDoc{ 36 Type: consts.Apps, 37 M: map[string]interface{}{ 38 "_id": consts.Apps + "/app", 39 "slug": "app", 40 }, 41 } 42 require.NoError(t, couchdb.CreateNamedDoc(ins, webapp)) 43 44 appPerms, err := permission.CreateWebappSet(ins, "app", permission.Set{}, "1.0.0") 45 if err != nil { 46 require.NoError(t, err) 47 } 48 appToken := ins.BuildAppToken("app", "") 49 files := &couchdb.JSONDoc{ 50 Type: consts.Apps, 51 M: map[string]interface{}{ 52 "_id": consts.Apps + "/files", 53 "slug": "files", 54 "intents": []app.Intent{ 55 { 56 Action: "PICK", 57 Types: []string{"io.cozy.files", "image/gif"}, 58 Href: "/pick", 59 }, 60 }, 61 }, 62 } 63 64 require.NoError(t, couchdb.CreateNamedDoc(ins, files)) 65 if _, err := permission.CreateWebappSet(ins, "files", permission.Set{}, "1.0.0"); err != nil { 66 require.NoError(t, err) 67 } 68 filesToken := ins.BuildAppToken("files", "") 69 70 ts := setup.GetTestServer("/intents", Routes) 71 ts.Config.Handler.(*echo.Echo).HTTPErrorHandler = errors.ErrorHandler 72 t.Cleanup(ts.Close) 73 74 t.Run("CreateIntent", func(t *testing.T) { 75 e := testutils.CreateTestClient(t, ts.URL) 76 77 obj := e.POST("/intents"). 78 WithHeader("Authorization", "Bearer "+appToken). 79 WithHeader("Content-Type", "application/vnd.api+json"). 80 WithHeader("Accept", "application/vnd.api+json"). 81 WithBytes([]byte(`{ 82 "data": { 83 "type": "io.cozy.settings", 84 "attributes": { 85 "action": "PICK", 86 "type": "io.cozy.files", 87 "permissions": ["GET"] 88 } 89 } 90 }`)). 91 Expect().Status(200). 92 JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}). 93 Object() 94 95 intentID = checkIntentResult(obj, appPerms, true) 96 }) 97 98 t.Run("GetIntent", func(t *testing.T) { 99 e := testutils.CreateTestClient(t, ts.URL) 100 101 obj := e.GET("/intents/"+intentID). 102 WithHeader("Authorization", "Bearer "+filesToken). 103 WithHeader("Accept", "application/vnd.api+json"). 104 Expect().Status(200). 105 JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}). 106 Object() 107 108 checkIntentResult(obj, appPerms, true) 109 }) 110 111 t.Run("GetIntentNotFromTheService", func(t *testing.T) { 112 e := testutils.CreateTestClient(t, ts.URL) 113 114 e.GET("/intents/"+intentID). 115 WithHeader("Authorization", "Bearer "+appToken). 116 WithHeader("Accept", "application/vnd.api+json"). 117 Expect().Status(403) 118 }) 119 120 t.Run("CreateIntentOAuth", func(t *testing.T) { 121 e := testutils.CreateTestClient(t, ts.URL) 122 123 obj := e.POST("/intents"). 124 WithHeader("Authorization", "Bearer "+appToken). 125 WithHeader("Content-Type", "application/vnd.api+json"). 126 WithHeader("Accept", "application/vnd.api+json"). 127 WithBytes([]byte(`{ 128 "data": { 129 "type": "io.cozy.settings", 130 "attributes": { 131 "action": "PICK", 132 "type": "io.cozy.files", 133 "permissions": ["GET"] 134 } 135 } 136 }`)). 137 Expect().Status(200). 138 JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}). 139 Object() 140 141 checkIntentResult(obj, appPerms, false) 142 }) 143 } 144 145 func checkIntentResult(obj *httpexpect.Object, appPerms *permission.Permission, fromWeb bool) string { 146 data := obj.Value("data").Object() 147 data.ValueEqual("type", "io.cozy.intents") 148 intentID := data.Value("id").String().NotEmpty().Raw() 149 150 attrs := data.Value("attributes").Object() 151 attrs.ValueEqual("action", "PICK") 152 attrs.ValueEqual("type", "io.cozy.files") 153 154 perms := attrs.Value("permissions").Array() 155 perms.Length().Equal(1) 156 perms.First().String().Equal("GET") 157 158 if !fromWeb { 159 return intentID 160 } 161 162 attrs.ValueEqual("client", "https://app.cozy.example.net") 163 164 links := data.Value("links").Object() 165 links.ValueEqual("self", "/intents/"+intentID) 166 links.ValueEqual("permissions", "/permissions/"+appPerms.ID()) 167 168 return intentID 169 }