44 "bytes"
55 "encoding/json"
66 "errors"
7+ "fmt"
78 "io"
89 "mime/multipart"
910 "net/http/httptest"
@@ -17,12 +18,14 @@ import (
1718 "github.com/gotify/server/v2/test"
1819 "github.com/gotify/server/v2/test/testdb"
1920 "github.com/stretchr/testify/assert"
21+ "github.com/stretchr/testify/require"
2022 "github.com/stretchr/testify/suite"
2123)
2224
2325var (
2426 firstApplicationToken = "Aaaaaaaaaaaaaaa"
2527 secondApplicationToken = "Abbbbbbbbbbbbbb"
28+ thirdApplicationToken = "Acccccccccccccc"
2629)
2730
2831func TestApplicationSuite (t * testing.T ) {
4548func (s * ApplicationSuite ) BeforeTest (suiteName , testName string ) {
4649 originalGenerateApplicationToken = generateApplicationToken
4750 originalGenerateImageName = generateImageName
48- generateApplicationToken = test .Tokens (firstApplicationToken , secondApplicationToken )
49- generateImageName = test .Tokens (firstApplicationToken [1 :], secondApplicationToken [1 :])
51+ generateApplicationToken = test .Tokens (firstApplicationToken , secondApplicationToken , thirdApplicationToken )
52+ generateImageName = test .Tokens (firstApplicationToken [1 :], secondApplicationToken [1 :], thirdApplicationToken [ 1 :] )
5053 mode .Set (mode .TestDev )
5154 s .recorder = httptest .NewRecorder ()
5255 s .db = testdb .NewDB (s .T ())
@@ -65,7 +68,7 @@ func (s *ApplicationSuite) Test_CreateApplication_mapAllParameters() {
6568 s .db .User (5 )
6669
6770 test .WithUser (s .ctx , 5 )
68- s .withFormData ("name=custom_name&description=description_text" )
71+ s .withFormData ("name=custom_name&description=description_text&sortKey=a5 " )
6972 s .a .CreateApplication (s .ctx )
7073
7174 expected := & model.Application {
@@ -74,6 +77,7 @@ func (s *ApplicationSuite) Test_CreateApplication_mapAllParameters() {
7477 UserID : 5 ,
7578 Name : "custom_name" ,
7679 Description : "description_text" ,
80+ SortKey : "a5" ,
7781 }
7882 assert .Equal (s .T (), 200 , s .recorder .Code )
7983 if app , err := s .db .GetApplicationByID (1 ); assert .NoError (s .T (), err ) {
@@ -91,8 +95,9 @@ func (s *ApplicationSuite) Test_ensureApplicationHasCorrectJsonRepresentation()
9195 Image : "asd" ,
9296 Internal : true ,
9397 LastUsed : nil ,
98+ SortKey : "a1" ,
9499 }
95- test .JSONEquals (s .T (), actual , `{"id":1,"token":"Aasdasfgeeg","name":"myapp","description":"mydesc", "image": "asd", "internal":true, "defaultPriority":0, "lastUsed":null}` )
100+ test .JSONEquals (s .T (), actual , `{"id":1,"token":"Aasdasfgeeg","name":"myapp","description":"mydesc", "image": "asd", "internal":true, "defaultPriority":0, "lastUsed":null, "sortKey":"a1" }` )
96101}
97102
98103func (s * ApplicationSuite ) Test_CreateApplication_expectBadRequestOnEmptyName () {
@@ -119,6 +124,7 @@ func (s *ApplicationSuite) Test_CreateApplication_ignoresReadOnlyPropertiesInPar
119124 Internal : true ,
120125 Token : "token" ,
121126 Image : "adfdf" ,
127+ SortKey : "a5" ,
122128 })
123129
124130 s .a .CreateApplication (s .ctx )
@@ -131,6 +137,7 @@ func (s *ApplicationSuite) Test_CreateApplication_ignoresReadOnlyPropertiesInPar
131137 Description : "description" ,
132138 Internal : false ,
133139 Image : "static/defaultapp.png" ,
140+ SortKey : "a5" ,
134141 })
135142
136143 assert .Equal (s .T (), 200 , s .recorder .Code )
@@ -158,7 +165,7 @@ func (s *ApplicationSuite) Test_CreateApplication_onlyRequiredParameters() {
158165 s .withFormData ("name=custom_name" )
159166 s .a .CreateApplication (s .ctx )
160167
161- expected := & model.Application {ID : 1 , Token : firstApplicationToken , Name : "custom_name" , UserID : 5 }
168+ expected := & model.Application {ID : 1 , Token : firstApplicationToken , Name : "custom_name" , UserID : 5 , SortKey : "a0" }
162169 assert .Equal (s .T (), 200 , s .recorder .Code )
163170 if app , err := s .db .GetApplicationsByUser (5 ); assert .NoError (s .T (), err ) {
164171 assert .Contains (s .T (), app , expected )
@@ -174,11 +181,12 @@ func (s *ApplicationSuite) Test_CreateApplication_returnsApplicationWithID() {
174181 s .a .CreateApplication (s .ctx )
175182
176183 expected := & model.Application {
177- ID : 1 ,
178- Token : firstApplicationToken ,
179- Name : "custom_name" ,
180- Image : "static/defaultapp.png" ,
181- UserID : 5 ,
184+ ID : 1 ,
185+ Token : firstApplicationToken ,
186+ Name : "custom_name" ,
187+ Image : "static/defaultapp.png" ,
188+ UserID : 5 ,
189+ SortKey : "a0" ,
182190 }
183191 assert .Equal (s .T (), 200 , s .recorder .Code )
184192 test .BodyEquals (s .T (), expected , s .recorder )
@@ -193,13 +201,53 @@ func (s *ApplicationSuite) Test_CreateApplication_withExistingToken() {
193201
194202 s .a .CreateApplication (s .ctx )
195203
196- expected := & model.Application {ID : 2 , Token : secondApplicationToken , Name : "custom_name" , UserID : 5 }
204+ expected := & model.Application {ID : 2 , Token : secondApplicationToken , Name : "custom_name" , UserID : 5 , SortKey : "a0" }
197205 assert .Equal (s .T (), 200 , s .recorder .Code )
198206 if app , err := s .db .GetApplicationsByUser (5 ); assert .NoError (s .T (), err ) {
199207 assert .Contains (s .T (), app , expected )
200208 }
201209}
202210
211+ func (s * ApplicationSuite ) Test_Sorting () {
212+ s .db .User (5 )
213+
214+ test .WithUser (s .ctx , 5 )
215+ s .withFormData ("name=one" )
216+ s .a .CreateApplication (s .ctx )
217+
218+ test .WithUser (s .ctx , 5 )
219+ s .withFormData ("name=two" )
220+ s .a .CreateApplication (s .ctx )
221+
222+ test .WithUser (s .ctx , 5 )
223+ s .withFormData ("name=three" )
224+ s .a .CreateApplication (s .ctx )
225+
226+ apps , err := s .db .GetApplicationsByUser (5 )
227+ require .NoError (s .T (), err )
228+ require .Len (s .T (), apps , 3 )
229+ assert .Equal (s .T (), apps [0 ].Name , "one" )
230+ assert .Equal (s .T (), apps [0 ].SortKey , "a0" )
231+ assert .Equal (s .T (), apps [1 ].Name , "two" )
232+ assert .Equal (s .T (), apps [1 ].SortKey , "a1" )
233+ assert .Equal (s .T (), apps [2 ].Name , "three" )
234+ assert .Equal (s .T (), apps [2 ].SortKey , "a2" )
235+
236+ s .withFormData ("name=one&description=&sortKey=a1V" )
237+ s .ctx .Params = gin.Params {{Key : "id" , Value : fmt .Sprint (apps [0 ].ID )}}
238+ s .a .UpdateApplication (s .ctx )
239+
240+ apps , err = s .db .GetApplicationsByUser (5 )
241+ require .NoError (s .T (), err )
242+ require .Len (s .T (), apps , 3 )
243+ assert .Equal (s .T (), apps [0 ].Name , "two" )
244+ assert .Equal (s .T (), apps [0 ].SortKey , "a1" )
245+ assert .Equal (s .T (), apps [1 ].Name , "one" )
246+ assert .Equal (s .T (), apps [1 ].SortKey , "a1V" )
247+ assert .Equal (s .T (), apps [2 ].Name , "three" )
248+ assert .Equal (s .T (), apps [2 ].SortKey , "a2" )
249+ }
250+
203251func (s * ApplicationSuite ) Test_GetApplications () {
204252 userBuilder := s .db .User (5 )
205253 first := userBuilder .NewAppWithToken (1 , "perfper" )
@@ -481,6 +529,7 @@ func (s *ApplicationSuite) Test_UpdateApplicationNameAndDescription_expectSucces
481529 UserID : 5 ,
482530 Name : "new_name" ,
483531 Description : "new_description_text" ,
532+ SortKey : "a0" ,
484533 }
485534
486535 assert .Equal (s .T (), 200 , s .recorder .Code )
@@ -503,6 +552,7 @@ func (s *ApplicationSuite) Test_UpdateApplicationName_expectSuccess() {
503552 UserID : 5 ,
504553 Name : "new_name" ,
505554 Description : "" ,
555+ SortKey : "a0" ,
506556 }
507557
508558 assert .Equal (s .T (), 200 , s .recorder .Code )
@@ -526,6 +576,7 @@ func (s *ApplicationSuite) Test_UpdateApplicationDefaultPriority_expectSuccess()
526576 Name : "name" ,
527577 Description : "" ,
528578 DefaultPriority : 4 ,
579+ SortKey : "a0" ,
529580 }
530581
531582 assert .Equal (s .T (), 200 , s .recorder .Code )
@@ -534,9 +585,10 @@ func (s *ApplicationSuite) Test_UpdateApplicationDefaultPriority_expectSuccess()
534585 }
535586}
536587
537- func (s * ApplicationSuite ) Test_UpdateApplication_preservesImage () {
588+ func (s * ApplicationSuite ) Test_UpdateApplication_preservesImageAndSortKey () {
538589 app := s .db .User (5 ).NewAppWithToken (2 , "app-2" )
539590 app .Image = "existing.png"
591+ app .SortKey = "a5"
540592 assert .Nil (s .T (), s .db .UpdateApplication (app ))
541593
542594 test .WithUser (s .ctx , 5 )
@@ -548,6 +600,7 @@ func (s *ApplicationSuite) Test_UpdateApplication_preservesImage() {
548600 assert .Equal (s .T (), 200 , s .recorder .Code )
549601 if app , err := s .db .GetApplicationByID (2 ); assert .NoError (s .T (), err ) {
550602 assert .Equal (s .T (), "existing.png" , app .Image )
603+ assert .Equal (s .T (), "a5" , app .SortKey )
551604 }
552605}
553606
@@ -594,6 +647,21 @@ func (s *ApplicationSuite) Test_UpdateApplication_WithoutPermission_expectNotFou
594647 assert .Equal (s .T (), 404 , s .recorder .Code )
595648}
596649
650+ func (s * ApplicationSuite ) Test_UpdateApplication_duplicateSortKey () {
651+ user := s .db .User (5 )
652+ user .App (1 ) // sortKey=a0
653+ user .App (2 ) // sortKey=a1
654+
655+ s .withFormData ("name=new_name&sortKey=a0" )
656+ test .WithUser (s .ctx , 5 )
657+ s .ctx .Params = gin.Params {{Key : "id" , Value : "2" }}
658+
659+ s .a .UpdateApplication (s .ctx )
660+
661+ assert .EqualError (s .T (), s .ctx .Errors [0 ].Err , "sort key is not unique" )
662+ assert .Equal (s .T (), 400 , s .recorder .Code )
663+ }
664+
597665func (s * ApplicationSuite ) withFormData (formData string ) {
598666 s .ctx .Request = httptest .NewRequest ("POST" , "/token" , strings .NewReader (formData ))
599667 s .ctx .Request .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
0 commit comments