77 "net/http"
88 "net/http/httptest"
99 "net/url"
10- "strings"
1110 "testing"
1211
1312 gitea_context "code.gitea.io/gitea/services/context"
@@ -37,30 +36,58 @@ func TestNewWebHookLink(t *testing.T) {
3736 for _ , url := range tests {
3837 resp := session .MakeRequest (t , NewRequest (t , "GET" , url ), http .StatusOK )
3938 htmlDoc := NewHTMLParser (t , resp .Body )
40- menus := htmlDoc .doc .Find (".ui.top.attached.header .ui.dropdown .menu a" )
41- menus .Each (func (i int , menu * goquery.Selection ) {
42- url , exist := menu .Attr ("href" )
43- assert .True (t , exist )
44- assert .True (t , strings .HasPrefix (url , baseurl ))
45- })
46- assert .Equal (t , webhooksLen , htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (), "not all webhooks are listed in the 'new' dropdown" )
39+ assert .Equal (t ,
40+ webhooksLen ,
41+ htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (),
42+ "not all webhooks are listed in the 'new' dropdown" )
43+
4744 csrfToken = htmlDoc .GetCSRF ()
4845 }
4946
5047 // ensure that the "failure" pages has the full dropdown as well
5148 resp := session .MakeRequest (t , NewRequestWithValues (t , "POST" , baseurl + "/gitea/new" , map [string ]string {"_csrf" : csrfToken }), http .StatusUnprocessableEntity )
5249 htmlDoc := NewHTMLParser (t , resp .Body )
53- assert .Equal (t , webhooksLen , htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (), "not all webhooks are listed in the 'new' dropdown on failure" )
50+ assert .Equal (t ,
51+ webhooksLen ,
52+ htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (),
53+ "not all webhooks are listed in the 'new' dropdown on failure" )
5454
5555 resp = session .MakeRequest (t , NewRequestWithValues (t , "POST" , baseurl + "/1" , map [string ]string {"_csrf" : csrfToken }), http .StatusUnprocessableEntity )
5656 htmlDoc = NewHTMLParser (t , resp .Body )
57- assert .Equal (t , webhooksLen , htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (), "not all webhooks are listed in the 'new' dropdown on failure" )
57+ assert .Equal (t ,
58+ webhooksLen ,
59+ htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (),
60+ "not all webhooks are listed in the 'new' dropdown on failure" )
61+
62+ adminSession := loginUser (t , "user1" )
63+ t .Run ("org3" , func (t * testing.T ) {
64+ baseurl := "/org/org3/settings/hooks"
65+ resp := adminSession .MakeRequest (t , NewRequest (t , "GET" , baseurl ), http .StatusOK )
66+ htmlDoc := NewHTMLParser (t , resp .Body )
67+ assert .Equal (t ,
68+ webhooksLen ,
69+ htmlDoc .Find (`a[href^="` + baseurl + `/"][href$="/new"]` ).Length (),
70+ "not all webhooks are listed in the 'new' dropdown" )
71+ })
72+ t .Run ("admin" , func (t * testing.T ) {
73+ baseurl := "/admin/hooks"
74+ resp := adminSession .MakeRequest (t , NewRequest (t , "GET" , baseurl ), http .StatusOK )
75+ htmlDoc := NewHTMLParser (t , resp .Body )
76+ assert .Equal (t ,
77+ webhooksLen ,
78+ htmlDoc .Find (`a[href^="/admin/default-hooks/"][href$="/new"]` ).Length (),
79+ "not all webhooks are listed in the 'new' dropdown for default-hooks" )
80+ assert .Equal (t ,
81+ webhooksLen ,
82+ htmlDoc .Find (`a[href^="/admin/system-hooks/"][href$="/new"]` ).Length (),
83+ "not all webhooks are listed in the 'new' dropdown for system-hooks" )
84+ })
5885}
5986
6087func TestWebhookForms (t * testing.T ) {
6188 defer tests .PrepareTestEnv (t )()
6289
63- session := loginUser (t , "user2 " )
90+ session := loginUser (t , "user1 " )
6491
6592 t .Run ("forgejo/required" , testWebhookForms ("forgejo" , session , map [string ]string {
6693 "payload_url" : "https://forgejo.example.com" ,
@@ -272,7 +299,9 @@ func assertInput(t testing.TB, form *goquery.Selection, name string) string {
272299 t .Helper ()
273300 input := form .Find (`input[name="` + name + `"]` )
274301 if input .Length () != 1 {
275- t .Log (form .Html ())
302+ form .Find ("input" ).Each (func (i int , s * goquery.Selection ) {
303+ t .Logf ("found <input name=%q />" , s .AttrOr ("name" , "" ))
304+ })
276305 t .Errorf ("field <input name=%q /> found %d times, expected once" , name , input .Length ())
277306 }
278307 switch input .AttrOr ("type" , "" ) {
@@ -288,99 +317,126 @@ func assertInput(t testing.TB, form *goquery.Selection, name string) string {
288317
289318func testWebhookForms (name string , session * TestSession , validFields map [string ]string , invalidPatches ... map [string ]string ) func (t * testing.T ) {
290319 return func (t * testing.T ) {
291- // new webhook form
292- resp := session .MakeRequest (t , NewRequest (t , "GET" , "/user2/repo1/settings/hooks/" + name + "/new" ), http .StatusOK )
293- htmlForm := NewHTMLParser (t , resp .Body ).Find (`form[action^="/user2/repo1/settings/hooks/"]` )
294-
295- // fill the form
296- payload := map [string ]string {
297- "_csrf" : htmlForm .Find (`input[name="_csrf"]` ).AttrOr ("value" , "" ),
298- "events" : "send_everything" ,
299- }
300- for k , v := range validFields {
301- assertInput (t , htmlForm , k )
302- payload [k ] = v
303- }
304- if t .Failed () {
305- t .FailNow () // prevent further execution if the form could not be filled properly
306- }
320+ t .Run ("repo1" , func (t * testing.T ) {
321+ testWebhookFormsShared (t , "/user2/repo1/settings/hooks" , name , session , validFields , invalidPatches ... )
322+ })
323+ t .Run ("org3" , func (t * testing.T ) {
324+ testWebhookFormsShared (t , "/org/org3/settings/hooks" , name , session , validFields , invalidPatches ... )
325+ })
326+ t .Run ("system" , func (t * testing.T ) {
327+ testWebhookFormsShared (t , "/admin/system-hooks" , name , session , validFields , invalidPatches ... )
328+ })
329+ t .Run ("default" , func (t * testing.T ) {
330+ testWebhookFormsShared (t , "/admin/default-hooks" , name , session , validFields , invalidPatches ... )
331+ })
332+ }
333+ }
307334
308- // create the webhook (this redirects back to the hook list)
309- resp = session .MakeRequest (t , NewRequestWithValues (t , "POST" , "/user2/repo1/settings/hooks/" + name + "/new" , payload ), http .StatusSeeOther )
310- assertHasFlashMessages (t , resp , "success" )
335+ func testWebhookFormsShared (t * testing.T , endpoint , name string , session * TestSession , validFields map [string ]string , invalidPatches ... map [string ]string ) {
336+ // new webhook form
337+ resp := session .MakeRequest (t , NewRequest (t , "GET" , endpoint + "/" + name + "/new" ), http .StatusOK )
338+ htmlForm := NewHTMLParser (t , resp .Body ).Find (`form[action^="` + endpoint + `/"]` )
311339
312- // find last created hook in the hook list
313- // (a bit hacky, but the list should be sorted)
314- resp = session .MakeRequest (t , NewRequest (t , "GET" , "/user2/repo1/settings/hooks" ), http .StatusOK )
315- htmlDoc := NewHTMLParser (t , resp .Body )
316- editFormURL := htmlDoc .Find (`a[href^="/user2/repo1/settings/hooks/"]` ).Last ().AttrOr ("href" , "" )
317- assert .NotEmpty (t , editFormURL )
318-
319- // edit webhook form
320- resp = session .MakeRequest (t , NewRequest (t , "GET" , editFormURL ), http .StatusOK )
321- htmlForm = NewHTMLParser (t , resp .Body ).Find (`form[action^="/user2/repo1/settings/hooks/"]` )
322- editPostURL := htmlForm .AttrOr ("action" , "" )
323- assert .NotEmpty (t , editPostURL )
324-
325- // fill the form
326- payload = map [string ]string {
327- "_csrf" : htmlForm .Find (`input[name="_csrf"]` ).AttrOr ("value" , "" ),
328- "events" : "push_only" ,
329- }
330- for k , v := range validFields {
331- assert .Equal (t , v , assertInput (t , htmlForm , k ), "input %q did not contain value %q" , k , v )
332- payload [k ] = v
333- }
340+ // fill the form
341+ payload := map [string ]string {
342+ "_csrf" : htmlForm .Find (`input[name="_csrf"]` ).AttrOr ("value" , "" ),
343+ "events" : "send_everything" ,
344+ }
345+ for k , v := range validFields {
346+ assertInput (t , htmlForm , k )
347+ payload [k ] = v
348+ }
349+ if t .Failed () {
350+ t .FailNow () // prevent further execution if the form could not be filled properly
351+ }
334352
335- // update the webhook
336- resp = session .MakeRequest (t , NewRequestWithValues (t , "POST" , editPostURL , payload ), http .StatusSeeOther )
337- assertHasFlashMessages (t , resp , "success" )
353+ // create the webhook (this redirects back to the hook list)
354+ resp = session .MakeRequest (t , NewRequestWithValues (t , "POST" , endpoint + "/" + name + "/new" , payload ), http .StatusSeeOther )
355+ assertHasFlashMessages (t , resp , "success" )
356+ listEndpoint := resp .Header ().Get ("Location" )
357+ updateEndpoint := endpoint + "/"
358+ if endpoint == "/admin/system-hooks" || endpoint == "/admin/default-hooks" {
359+ updateEndpoint = "/admin/hooks/"
360+ }
338361
339- // check the updated webhook
340- resp = session .MakeRequest (t , NewRequest (t , "GET" , editFormURL ), http .StatusOK )
341- htmlForm = NewHTMLParser (t , resp .Body ).Find (`form[action^="/user2/repo1/settings/hooks/"]` )
342- for k , v := range validFields {
343- assert .Equal (t , v , assertInput (t , htmlForm , k ), "input %q did not contain value %q" , k , v )
344- }
362+ // find last created hook in the hook list
363+ // (a bit hacky, but the list should be sorted)
364+ resp = session .MakeRequest (t , NewRequest (t , "GET" , listEndpoint ), http .StatusOK )
365+ htmlDoc := NewHTMLParser (t , resp .Body )
366+ selector := `a[href^="` + updateEndpoint + `"]`
367+ if endpoint == "/admin/system-hooks" {
368+ // system-hooks and default-hooks are listed on the same page
369+ // add a specifier to select the latest system-hooks
370+ // (the default-hooks are at the end, so no further specifier needed)
371+ selector = `.admin-setting-content > div:first-of-type ` + selector
372+ }
373+ editFormURL := htmlDoc .Find (selector ).Last ().AttrOr ("href" , "" )
374+ assert .NotEmpty (t , editFormURL )
375+
376+ // edit webhook form
377+ resp = session .MakeRequest (t , NewRequest (t , "GET" , editFormURL ), http .StatusOK )
378+ htmlForm = NewHTMLParser (t , resp .Body ).Find (`form[action^="` + updateEndpoint + `"]` )
379+ editPostURL := htmlForm .AttrOr ("action" , "" )
380+ assert .NotEmpty (t , editPostURL )
381+
382+ // fill the form
383+ payload = map [string ]string {
384+ "_csrf" : htmlForm .Find (`input[name="_csrf"]` ).AttrOr ("value" , "" ),
385+ "events" : "push_only" ,
386+ }
387+ for k , v := range validFields {
388+ assert .Equal (t , v , assertInput (t , htmlForm , k ), "input %q did not contain value %q" , k , v )
389+ payload [k ] = v
390+ }
345391
346- if len (invalidPatches ) > 0 {
347- // check that invalid fields are rejected
348- resp := session .MakeRequest (t , NewRequest (t , "GET" , "/user2/repo1/settings/hooks/" + name + "/new" ), http .StatusOK )
349- htmlForm := NewHTMLParser (t , resp .Body ).Find (`form[action^="/user2/repo1/settings/hooks/"]` )
350-
351- for _ , invalidPatch := range invalidPatches {
352- t .Run ("invalid" , func (t * testing.T ) {
353- // fill the form
354- payload := map [string ]string {
355- "_csrf" : htmlForm .Find (`input[name="_csrf"]` ).AttrOr ("value" , "" ),
356- "events" : "send_everything" ,
357- }
358- for k , v := range validFields {
392+ // update the webhook
393+ resp = session .MakeRequest (t , NewRequestWithValues (t , "POST" , editPostURL , payload ), http .StatusSeeOther )
394+ assertHasFlashMessages (t , resp , "success" )
395+
396+ // check the updated webhook
397+ resp = session .MakeRequest (t , NewRequest (t , "GET" , editFormURL ), http .StatusOK )
398+ htmlForm = NewHTMLParser (t , resp .Body ).Find (`form[action^="` + updateEndpoint + `"]` )
399+ for k , v := range validFields {
400+ assert .Equal (t , v , assertInput (t , htmlForm , k ), "input %q did not contain value %q" , k , v )
401+ }
402+
403+ if len (invalidPatches ) > 0 {
404+ // check that invalid fields are rejected
405+ resp := session .MakeRequest (t , NewRequest (t , "GET" , endpoint + "/" + name + "/new" ), http .StatusOK )
406+ htmlForm := NewHTMLParser (t , resp .Body ).Find (`form[action^="` + endpoint + `/"]` )
407+
408+ for _ , invalidPatch := range invalidPatches {
409+ t .Run ("invalid" , func (t * testing.T ) {
410+ // fill the form
411+ payload := map [string ]string {
412+ "_csrf" : htmlForm .Find (`input[name="_csrf"]` ).AttrOr ("value" , "" ),
413+ "events" : "send_everything" ,
414+ }
415+ for k , v := range validFields {
416+ payload [k ] = v
417+ }
418+ for k , v := range invalidPatch {
419+ if v == "" {
420+ delete (payload , k )
421+ } else {
359422 payload [k ] = v
360423 }
361- for k , v := range invalidPatch {
362- if v == "" {
363- delete (payload , k )
364- } else {
365- payload [k ] = v
366- }
367- }
424+ }
368425
369- resp := session .MakeRequest (t , NewRequestWithValues (t , "POST" , "/user2/repo1/settings/hooks/" + name + "/new" , payload ), http .StatusUnprocessableEntity )
370- // check that the invalid form is pre-filled
371- htmlForm = NewHTMLParser (t , resp .Body ).Find (`form[action^="/user2/repo1/settings/hooks/"]` )
372- for k , v := range payload {
373- if k == "_csrf" || k == "events" || v == "" {
374- // the 'events' is a radio input, which is buggy below
375- continue
376- }
377- assert .Equal (t , v , assertInput (t , htmlForm , k ), "input %q did not contain value %q" , k , v )
426+ resp := session .MakeRequest (t , NewRequestWithValues (t , "POST" , endpoint + "/" + name + "/new" , payload ), http .StatusUnprocessableEntity )
427+ // check that the invalid form is pre-filled
428+ htmlForm = NewHTMLParser (t , resp .Body ).Find (`form[action^="` + endpoint + `/"]` )
429+ for k , v := range payload {
430+ if k == "_csrf" || k == "events" || v == "" {
431+ // the 'events' is a radio input, which is buggy below
432+ continue
378433 }
379- if t .Failed () {
380- t .Log (invalidPatch )
381- }
382- })
383- }
434+ assert .Equal (t , v , assertInput (t , htmlForm , k ), "input %q did not contain value %q" , k , v )
435+ }
436+ if t .Failed () {
437+ t .Log (invalidPatch )
438+ }
439+ })
384440 }
385441 }
386442}
0 commit comments