github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/data/not_synchronizing_test.go (about)

     1  package data
     2  
     3  import (
     4  	"net/url"
     5  	"testing"
     6  
     7  	"github.com/cozy/cozy-stack/model/instance"
     8  	"github.com/cozy/cozy-stack/model/vfs"
     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/gavv/httpexpect/v2"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestNot(t *testing.T) {
    19  	if testing.Short() {
    20  		t.Skip("an instance is required for this test: test skipped due to the use of --short flag")
    21  	}
    22  
    23  	const Type = "io.cozy.events"
    24  	const ID = "4521C325F6478E45"
    25  
    26  	config.UseTestFile(t)
    27  	testutils.NeedCouchdb(t)
    28  	setup := testutils.NewSetup(t, t.Name())
    29  	testInstance := setup.GetTestInstance()
    30  	scope := "io.cozy.doctypes io.cozy.files io.cozy.events " +
    31  		"io.cozy.anothertype io.cozy.nottype"
    32  
    33  	_, token := setup.GetTestClient(scope)
    34  	ts := setup.GetTestServer("/data", Routes)
    35  	t.Cleanup(ts.Close)
    36  
    37  	_ = couchdb.ResetDB(testInstance, Type)
    38  	_ = couchdb.CreateNamedDoc(testInstance, &couchdb.JSONDoc{
    39  		Type: Type,
    40  		M: map[string]interface{}{
    41  			"_id":  ID,
    42  			"test": "testvalue",
    43  		},
    44  	})
    45  
    46  	t.Run("ListNotSynchronizingHandler", func(t *testing.T) {
    47  		e := testutils.CreateTestClient(t, ts.URL)
    48  
    49  		// Make doc
    50  		doc := getDocForTest(Type, testInstance)
    51  
    52  		// Make directories
    53  		makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_1")
    54  		makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_2")
    55  		makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_3")
    56  		makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_4")
    57  
    58  		// Simple query
    59  		obj := e.GET("/data/"+doc.DocType()+"/"+doc.ID()+"/relationships/not_synchronizing").
    60  			WithHeader("Authorization", "Bearer "+token).
    61  			Expect().Status(200).
    62  			JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
    63  			Object()
    64  
    65  		obj.Path("$.meta.count").Equal(4)
    66  		obj.Value("links").Object().NotContainsKey("next")
    67  		obj.Value("data").Array().Length().Equal(4)
    68  
    69  		// Use the page limit
    70  		obj = e.GET("/data/"+doc.DocType()+"/"+doc.ID()+"/relationships/not_synchronizing").
    71  			WithQuery("page[limit]", 3).
    72  			WithHeader("Authorization", "Bearer "+token).
    73  			Expect().Status(200).
    74  			JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
    75  			Object()
    76  
    77  		obj.Path("$.meta.count").Equal(4)
    78  		obj.Value("data").Array().Length().Equal(3)
    79  		rawNext := obj.Value("links").Object().Value("next").String().NotEmpty().Raw()
    80  
    81  		nextURL, err := url.Parse(rawNext)
    82  		require.NoError(t, err)
    83  
    84  		// Use the bookmark
    85  		obj = e.GET(nextURL.Path).
    86  			WithQueryString(nextURL.RawQuery).
    87  			WithHeader("Authorization", "Bearer "+token).
    88  			Expect().Status(200).
    89  			JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
    90  			Object()
    91  
    92  		obj.Value("data").Array().Length().Equal(1)
    93  		obj.Value("links").Object().NotContainsKey("next")
    94  
    95  		// Include the files
    96  		obj = e.GET("/data/"+doc.DocType()+"/"+doc.ID()+"/relationships/not_synchronizing").
    97  			WithQuery("include", "files").
    98  			WithHeader("Authorization", "Bearer "+token).
    99  			Expect().Status(200).
   100  			JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
   101  			Object()
   102  
   103  		obj.Value("included").Array().Length().Equal(4)
   104  		obj.Path("$.included[0].id").String().NotEmpty()
   105  	})
   106  
   107  	t.Run("AddNotSynchronizing", func(t *testing.T) {
   108  		e := testutils.CreateTestClient(t, ts.URL)
   109  
   110  		// Make doc
   111  		doc := getDocForTest(Type, testInstance)
   112  
   113  		// Make dir
   114  		dir := makeNotSynchronzedOnTestDir(t, testInstance, nil, "test_not_sync_on")
   115  
   116  		// update it
   117  		e.POST("/data/"+doc.DocType()+"/"+doc.ID()+"/relationships/not_synchronizing").
   118  			WithHeader("Authorization", "Bearer "+token).
   119  			WithHeader("Content-Type", "application/vnd.api+json").
   120  			WithBytes([]byte(`{
   121          "data": {
   122            "id": "` + dir.ID() + `",
   123            "type": "` + dir.DocType() + `"
   124          }
   125        }`)).
   126  			Expect().Status(204)
   127  
   128  		dirdoc, err := testInstance.VFS().DirByID(dir.ID())
   129  		assert.NoError(t, err)
   130  		assert.Len(t, dirdoc.NotSynchronizedOn, 1)
   131  	})
   132  
   133  	t.Run("RemoveNotSynchronizing", func(t *testing.T) {
   134  		e := testutils.CreateTestClient(t, ts.URL)
   135  
   136  		// Make doc
   137  		doc := getDocForTest(Type, testInstance)
   138  
   139  		// Make directories
   140  		d6 := makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_6").ID()
   141  		d7 := makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_7").ID()
   142  		d8 := makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_8").ID()
   143  		d9 := makeNotSynchronzedOnTestDir(t, testInstance, doc, "test_not_sync_on_9").ID()
   144  
   145  		// update it
   146  		e.DELETE("/data/"+doc.DocType()+"/"+doc.ID()+"/relationships/not_synchronizing").
   147  			WithHeader("Authorization", "Bearer "+token).
   148  			WithHeader("Content-Type", "application/vnd.api+json").
   149  			WithBytes([]byte(`{
   150          "data": [
   151            {"id": "` + d8 + `", "type": "` + consts.Files + `"},
   152            {"id": "` + d6 + `", "type": "` + consts.Files + `"}
   153          ]
   154        }`)).
   155  			Expect().Status(204)
   156  
   157  		doc6, err := testInstance.VFS().DirByID(d6)
   158  		assert.NoError(t, err)
   159  		assert.Len(t, doc6.NotSynchronizedOn, 0)
   160  		doc8, err := testInstance.VFS().DirByID(d8)
   161  		assert.NoError(t, err)
   162  		assert.Len(t, doc8.NotSynchronizedOn, 0)
   163  
   164  		doc7, err := testInstance.VFS().DirByID(d7)
   165  		assert.NoError(t, err)
   166  		assert.Len(t, doc7.NotSynchronizedOn, 1)
   167  		doc9, err := testInstance.VFS().DirByID(d9)
   168  		assert.NoError(t, err)
   169  		assert.Len(t, doc9.NotSynchronizedOn, 1)
   170  	})
   171  }
   172  
   173  func makeNotSynchronzedOnTestDir(t *testing.T, instance *instance.Instance, doc couchdb.Doc, name string) *vfs.DirDoc {
   174  	fs := instance.VFS()
   175  	dirID := consts.RootDirID
   176  	dir, err := vfs.NewDirDoc(fs, name, dirID, nil)
   177  	if !assert.NoError(t, err) {
   178  		return nil
   179  	}
   180  
   181  	if doc != nil {
   182  		dir.NotSynchronizedOn = []couchdb.DocReference{
   183  			{
   184  				ID:   doc.ID(),
   185  				Type: doc.DocType(),
   186  			},
   187  		}
   188  	}
   189  
   190  	err = fs.CreateDir(dir)
   191  
   192  	if !assert.NoError(t, err) {
   193  		return nil
   194  	}
   195  
   196  	return dir
   197  }