code.gitea.io/gitea@v1.22.3/tests/integration/api_notification_test.go (about)

     1  // Copyright 2020 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package integration
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"testing"
    10  
    11  	activities_model "code.gitea.io/gitea/models/activities"
    12  	auth_model "code.gitea.io/gitea/models/auth"
    13  	"code.gitea.io/gitea/models/db"
    14  	repo_model "code.gitea.io/gitea/models/repo"
    15  	"code.gitea.io/gitea/models/unittest"
    16  	user_model "code.gitea.io/gitea/models/user"
    17  	api "code.gitea.io/gitea/modules/structs"
    18  	"code.gitea.io/gitea/tests"
    19  
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestAPINotification(t *testing.T) {
    24  	defer tests.PrepareTestEnv(t)()
    25  
    26  	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
    27  	repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
    28  	thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
    29  	assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
    30  	session := loginUser(t, user2.Name)
    31  	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteNotification, auth_model.AccessTokenScopeWriteRepository)
    32  
    33  	MakeRequest(t, NewRequest(t, "GET", "/api/v1/notifications"), http.StatusUnauthorized)
    34  
    35  	// -- GET /notifications --
    36  	// test filter
    37  	since := "2000-01-01T00%3A50%3A01%2B00%3A00" // 946687801
    38  	req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?since=%s", since)).
    39  		AddTokenAuth(token)
    40  	resp := MakeRequest(t, req, http.StatusOK)
    41  	var apiNL []api.NotificationThread
    42  	DecodeJSON(t, resp, &apiNL)
    43  
    44  	assert.Len(t, apiNL, 1)
    45  	assert.EqualValues(t, 5, apiNL[0].ID)
    46  
    47  	// test filter
    48  	before := "2000-01-01T01%3A06%3A59%2B00%3A00" // 946688819
    49  
    50  	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?all=%s&before=%s", "true", before)).
    51  		AddTokenAuth(token)
    52  	resp = MakeRequest(t, req, http.StatusOK)
    53  	DecodeJSON(t, resp, &apiNL)
    54  
    55  	assert.Len(t, apiNL, 3)
    56  	assert.EqualValues(t, 4, apiNL[0].ID)
    57  	assert.True(t, apiNL[0].Unread)
    58  	assert.False(t, apiNL[0].Pinned)
    59  	assert.EqualValues(t, 3, apiNL[1].ID)
    60  	assert.False(t, apiNL[1].Unread)
    61  	assert.True(t, apiNL[1].Pinned)
    62  	assert.EqualValues(t, 2, apiNL[2].ID)
    63  	assert.False(t, apiNL[2].Unread)
    64  	assert.False(t, apiNL[2].Pinned)
    65  
    66  	// -- GET /repos/{owner}/{repo}/notifications --
    67  	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?status-types=unread", user2.Name, repo1.Name)).
    68  		AddTokenAuth(token)
    69  	resp = MakeRequest(t, req, http.StatusOK)
    70  	DecodeJSON(t, resp, &apiNL)
    71  
    72  	assert.Len(t, apiNL, 1)
    73  	assert.EqualValues(t, 4, apiNL[0].ID)
    74  
    75  	// -- GET /repos/{owner}/{repo}/notifications -- multiple status-types
    76  	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?status-types=unread&status-types=pinned", user2.Name, repo1.Name)).
    77  		AddTokenAuth(token)
    78  	resp = MakeRequest(t, req, http.StatusOK)
    79  	DecodeJSON(t, resp, &apiNL)
    80  
    81  	assert.Len(t, apiNL, 2)
    82  	assert.EqualValues(t, 4, apiNL[0].ID)
    83  	assert.True(t, apiNL[0].Unread)
    84  	assert.False(t, apiNL[0].Pinned)
    85  	assert.EqualValues(t, 3, apiNL[1].ID)
    86  	assert.False(t, apiNL[1].Unread)
    87  	assert.True(t, apiNL[1].Pinned)
    88  
    89  	MakeRequest(t, NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/threads/%d", 1)), http.StatusUnauthorized)
    90  
    91  	// -- GET /notifications/threads/{id} --
    92  	// get forbidden
    93  	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/threads/%d", 1)).
    94  		AddTokenAuth(token)
    95  	MakeRequest(t, req, http.StatusForbidden)
    96  
    97  	// get own
    98  	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/threads/%d", thread5.ID)).
    99  		AddTokenAuth(token)
   100  	resp = MakeRequest(t, req, http.StatusOK)
   101  	var apiN api.NotificationThread
   102  	DecodeJSON(t, resp, &apiN)
   103  
   104  	assert.EqualValues(t, 5, apiN.ID)
   105  	assert.False(t, apiN.Pinned)
   106  	assert.True(t, apiN.Unread)
   107  	assert.EqualValues(t, "issue4", apiN.Subject.Title)
   108  	assert.EqualValues(t, "Issue", apiN.Subject.Type)
   109  	assert.EqualValues(t, thread5.Issue.APIURL(db.DefaultContext), apiN.Subject.URL)
   110  	assert.EqualValues(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL)
   111  
   112  	MakeRequest(t, NewRequest(t, "GET", "/api/v1/notifications/new"), http.StatusUnauthorized)
   113  
   114  	newStruct := struct {
   115  		New int64 `json:"new"`
   116  	}{}
   117  
   118  	// -- check notifications --
   119  	req = NewRequest(t, "GET", "/api/v1/notifications/new").
   120  		AddTokenAuth(token)
   121  	resp = MakeRequest(t, req, http.StatusOK)
   122  	DecodeJSON(t, resp, &newStruct)
   123  	assert.True(t, newStruct.New > 0)
   124  
   125  	// -- mark notifications as read --
   126  	req = NewRequest(t, "GET", "/api/v1/notifications?status-types=unread").
   127  		AddTokenAuth(token)
   128  	resp = MakeRequest(t, req, http.StatusOK)
   129  	DecodeJSON(t, resp, &apiNL)
   130  	assert.Len(t, apiNL, 2)
   131  
   132  	lastReadAt := "2000-01-01T00%3A50%3A01%2B00%3A00" // 946687801 <- only Notification 4 is in this filter ...
   133  	req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?last_read_at=%s", user2.Name, repo1.Name, lastReadAt)).
   134  		AddTokenAuth(token)
   135  	MakeRequest(t, req, http.StatusResetContent)
   136  
   137  	req = NewRequest(t, "GET", "/api/v1/notifications?status-types=unread").
   138  		AddTokenAuth(token)
   139  	resp = MakeRequest(t, req, http.StatusOK)
   140  	DecodeJSON(t, resp, &apiNL)
   141  	assert.Len(t, apiNL, 1)
   142  
   143  	// -- PATCH /notifications/threads/{id} --
   144  	req = NewRequest(t, "PATCH", fmt.Sprintf("/api/v1/notifications/threads/%d", thread5.ID)).
   145  		AddTokenAuth(token)
   146  	MakeRequest(t, req, http.StatusResetContent)
   147  
   148  	assert.Equal(t, activities_model.NotificationStatusUnread, thread5.Status)
   149  	thread5 = unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
   150  	assert.Equal(t, activities_model.NotificationStatusRead, thread5.Status)
   151  
   152  	// -- check notifications --
   153  	req = NewRequest(t, "GET", "/api/v1/notifications/new").
   154  		AddTokenAuth(token)
   155  	resp = MakeRequest(t, req, http.StatusOK)
   156  	DecodeJSON(t, resp, &newStruct)
   157  	assert.True(t, newStruct.New == 0)
   158  }
   159  
   160  func TestAPINotificationPUT(t *testing.T) {
   161  	defer tests.PrepareTestEnv(t)()
   162  
   163  	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
   164  	thread5 := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: 5})
   165  	assert.NoError(t, thread5.LoadAttributes(db.DefaultContext))
   166  	session := loginUser(t, user2.Name)
   167  	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteNotification)
   168  
   169  	// Check notifications are as expected
   170  	req := NewRequest(t, "GET", "/api/v1/notifications?all=true").
   171  		AddTokenAuth(token)
   172  	resp := MakeRequest(t, req, http.StatusOK)
   173  	var apiNL []api.NotificationThread
   174  	DecodeJSON(t, resp, &apiNL)
   175  
   176  	assert.Len(t, apiNL, 4)
   177  	assert.EqualValues(t, 5, apiNL[0].ID)
   178  	assert.True(t, apiNL[0].Unread)
   179  	assert.False(t, apiNL[0].Pinned)
   180  	assert.EqualValues(t, 4, apiNL[1].ID)
   181  	assert.True(t, apiNL[1].Unread)
   182  	assert.False(t, apiNL[1].Pinned)
   183  	assert.EqualValues(t, 3, apiNL[2].ID)
   184  	assert.False(t, apiNL[2].Unread)
   185  	assert.True(t, apiNL[2].Pinned)
   186  	assert.EqualValues(t, 2, apiNL[3].ID)
   187  	assert.False(t, apiNL[3].Unread)
   188  	assert.False(t, apiNL[3].Pinned)
   189  
   190  	//
   191  	// Notification ID 2 is the only one with status-type read & pinned
   192  	// change it to unread.
   193  	//
   194  	req = NewRequest(t, "PUT", "/api/v1/notifications?status-types=read&status-type=pinned&to-status=unread").
   195  		AddTokenAuth(token)
   196  	resp = MakeRequest(t, req, http.StatusResetContent)
   197  	DecodeJSON(t, resp, &apiNL)
   198  	assert.Len(t, apiNL, 1)
   199  	assert.EqualValues(t, 2, apiNL[0].ID)
   200  	assert.True(t, apiNL[0].Unread)
   201  	assert.False(t, apiNL[0].Pinned)
   202  
   203  	//
   204  	// Now nofication ID 2 is the first in the list and is unread.
   205  	//
   206  	req = NewRequest(t, "GET", "/api/v1/notifications?all=true").
   207  		AddTokenAuth(token)
   208  	resp = MakeRequest(t, req, http.StatusOK)
   209  	DecodeJSON(t, resp, &apiNL)
   210  
   211  	assert.Len(t, apiNL, 4)
   212  	assert.EqualValues(t, 2, apiNL[0].ID)
   213  	assert.True(t, apiNL[0].Unread)
   214  	assert.False(t, apiNL[0].Pinned)
   215  }