1
2
3
4
5
6 package github
7
8 import (
9 "context"
10 "fmt"
11 "net/http"
12 "testing"
13
14 "github.com/google/go-cmp/cmp"
15 )
16
17 func TestSearchService_Repositories(t *testing.T) {
18 client, mux, _, teardown := setup()
19 defer teardown()
20
21 mux.HandleFunc("/search/repositories", func(w http.ResponseWriter, r *http.Request) {
22 testMethod(t, r, "GET")
23 testFormValues(t, r, values{
24 "q": "blah",
25 "sort": "forks",
26 "order": "desc",
27 "page": "2",
28 "per_page": "2",
29 })
30
31 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`)
32 })
33
34 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
35 ctx := context.Background()
36 result, _, err := client.Search.Repositories(ctx, "blah", opts)
37 if err != nil {
38 t.Errorf("Search.Repositories returned error: %v", err)
39 }
40
41 want := &RepositoriesSearchResult{
42 Total: Int(4),
43 IncompleteResults: Bool(false),
44 Repositories: []*Repository{{ID: Int64(1)}, {ID: Int64(2)}},
45 }
46 if !cmp.Equal(result, want) {
47 t.Errorf("Search.Repositories returned %+v, want %+v", result, want)
48 }
49 }
50
51 func TestSearchService_Repositories_coverage(t *testing.T) {
52 client, _, _, teardown := setup()
53 defer teardown()
54
55 ctx := context.Background()
56
57 const methodName = "Repositories"
58 testBadOptions(t, methodName, func() (err error) {
59 _, _, err = client.Search.Repositories(ctx, "\n", nil)
60 return err
61 })
62 }
63
64 func TestSearchService_Topics(t *testing.T) {
65 client, mux, _, teardown := setup()
66 defer teardown()
67
68 mux.HandleFunc("/search/topics", func(w http.ResponseWriter, r *http.Request) {
69 testMethod(t, r, "GET")
70 testFormValues(t, r, values{
71 "q": "blah",
72 "page": "2",
73 "per_page": "2",
74 })
75
76 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"name":"blah"},{"name":"blahblah"}]}`)
77 })
78
79 opts := &SearchOptions{ListOptions: ListOptions{Page: 2, PerPage: 2}}
80 ctx := context.Background()
81 result, _, err := client.Search.Topics(ctx, "blah", opts)
82 if err != nil {
83 t.Errorf("Search.Topics returned error: %v", err)
84 }
85
86 want := &TopicsSearchResult{
87 Total: Int(4),
88 IncompleteResults: Bool(false),
89 Topics: []*TopicResult{{Name: String("blah")}, {Name: String("blahblah")}},
90 }
91 if !cmp.Equal(result, want) {
92 t.Errorf("Search.Topics returned %+v, want %+v", result, want)
93 }
94 }
95
96 func TestSearchService_Topics_coverage(t *testing.T) {
97 client, _, _, teardown := setup()
98 defer teardown()
99
100 ctx := context.Background()
101
102 const methodName = "Topics"
103 testBadOptions(t, methodName, func() (err error) {
104 _, _, err = client.Search.Topics(ctx, "\n", nil)
105 return err
106 })
107 }
108
109 func TestSearchService_Commits(t *testing.T) {
110 client, mux, _, teardown := setup()
111 defer teardown()
112
113 mux.HandleFunc("/search/commits", func(w http.ResponseWriter, r *http.Request) {
114 testMethod(t, r, "GET")
115 testFormValues(t, r, values{
116 "q": "blah",
117 "sort": "author-date",
118 "order": "desc",
119 })
120
121 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"sha":"random_hash1"},{"sha":"random_hash2"}]}`)
122 })
123
124 opts := &SearchOptions{Sort: "author-date", Order: "desc"}
125 ctx := context.Background()
126 result, _, err := client.Search.Commits(ctx, "blah", opts)
127 if err != nil {
128 t.Errorf("Search.Commits returned error: %v", err)
129 }
130
131 want := &CommitsSearchResult{
132 Total: Int(4),
133 IncompleteResults: Bool(false),
134 Commits: []*CommitResult{{SHA: String("random_hash1")}, {SHA: String("random_hash2")}},
135 }
136 if !cmp.Equal(result, want) {
137 t.Errorf("Search.Commits returned %+v, want %+v", result, want)
138 }
139 }
140
141 func TestSearchService_Commits_coverage(t *testing.T) {
142 client, _, _, teardown := setup()
143 defer teardown()
144
145 ctx := context.Background()
146
147 const methodName = "Commits"
148 testBadOptions(t, methodName, func() (err error) {
149 _, _, err = client.Search.Commits(ctx, "\n", nil)
150 return err
151 })
152 }
153
154 func TestSearchService_Issues(t *testing.T) {
155 client, mux, _, teardown := setup()
156 defer teardown()
157
158 mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) {
159 testMethod(t, r, "GET")
160 testFormValues(t, r, values{
161 "q": "blah",
162 "sort": "forks",
163 "order": "desc",
164 "page": "2",
165 "per_page": "2",
166 })
167
168 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`)
169 })
170
171 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
172 ctx := context.Background()
173 result, _, err := client.Search.Issues(ctx, "blah", opts)
174 if err != nil {
175 t.Errorf("Search.Issues returned error: %v", err)
176 }
177
178 want := &IssuesSearchResult{
179 Total: Int(4),
180 IncompleteResults: Bool(true),
181 Issues: []*Issue{{Number: Int(1)}, {Number: Int(2)}},
182 }
183 if !cmp.Equal(result, want) {
184 t.Errorf("Search.Issues returned %+v, want %+v", result, want)
185 }
186 }
187
188 func TestSearchService_Issues_coverage(t *testing.T) {
189 client, _, _, teardown := setup()
190 defer teardown()
191
192 ctx := context.Background()
193
194 const methodName = "Issues"
195 testBadOptions(t, methodName, func() (err error) {
196 _, _, err = client.Search.Issues(ctx, "\n", nil)
197 return err
198 })
199 }
200
201 func TestSearchService_Issues_withQualifiersNoOpts(t *testing.T) {
202 client, mux, _, teardown := setup()
203 defer teardown()
204
205 const q = "gopher is:issue label:bug language:c++ pushed:>=2018-01-01 stars:>=200"
206
207 var requestURI string
208 mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) {
209 testMethod(t, r, "GET")
210 testFormValues(t, r, values{
211 "q": q,
212 })
213 requestURI = r.RequestURI
214
215 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`)
216 })
217
218 opts := &SearchOptions{}
219 ctx := context.Background()
220 result, _, err := client.Search.Issues(ctx, q, opts)
221 if err != nil {
222 t.Errorf("Search.Issues returned error: %v", err)
223 }
224
225 if want := "/api-v3/search/issues?q=gopher+is%3Aissue+label%3Abug+language%3Ac%2B%2B+pushed%3A%3E%3D2018-01-01+stars%3A%3E%3D200"; requestURI != want {
226 t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want)
227 }
228
229 want := &IssuesSearchResult{
230 Total: Int(4),
231 IncompleteResults: Bool(true),
232 Issues: []*Issue{{Number: Int(1)}, {Number: Int(2)}},
233 }
234 if !cmp.Equal(result, want) {
235 t.Errorf("Search.Issues returned %+v, want %+v", result, want)
236 }
237 }
238
239 func TestSearchService_Issues_withQualifiersAndOpts(t *testing.T) {
240 client, mux, _, teardown := setup()
241 defer teardown()
242
243 const q = "gopher is:issue label:bug language:c++ pushed:>=2018-01-01 stars:>=200"
244
245 var requestURI string
246 mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) {
247 testMethod(t, r, "GET")
248 testFormValues(t, r, values{
249 "q": q,
250 "sort": "forks",
251 })
252 requestURI = r.RequestURI
253
254 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`)
255 })
256
257 opts := &SearchOptions{Sort: "forks"}
258 ctx := context.Background()
259 result, _, err := client.Search.Issues(ctx, q, opts)
260 if err != nil {
261 t.Errorf("Search.Issues returned error: %v", err)
262 }
263
264 if want := "/api-v3/search/issues?q=gopher+is%3Aissue+label%3Abug+language%3Ac%2B%2B+pushed%3A%3E%3D2018-01-01+stars%3A%3E%3D200&sort=forks"; requestURI != want {
265 t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want)
266 }
267
268 want := &IssuesSearchResult{
269 Total: Int(4),
270 IncompleteResults: Bool(true),
271 Issues: []*Issue{{Number: Int(1)}, {Number: Int(2)}},
272 }
273 if !cmp.Equal(result, want) {
274 t.Errorf("Search.Issues returned %+v, want %+v", result, want)
275 }
276 }
277
278 func TestSearchService_Users(t *testing.T) {
279 client, mux, _, teardown := setup()
280 defer teardown()
281
282 mux.HandleFunc("/search/users", func(w http.ResponseWriter, r *http.Request) {
283 testMethod(t, r, "GET")
284 testFormValues(t, r, values{
285 "q": "blah",
286 "sort": "forks",
287 "order": "desc",
288 "page": "2",
289 "per_page": "2",
290 })
291
292 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`)
293 })
294
295 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
296 ctx := context.Background()
297 result, _, err := client.Search.Users(ctx, "blah", opts)
298 if err != nil {
299 t.Errorf("Search.Issues returned error: %v", err)
300 }
301
302 want := &UsersSearchResult{
303 Total: Int(4),
304 IncompleteResults: Bool(false),
305 Users: []*User{{ID: Int64(1)}, {ID: Int64(2)}},
306 }
307 if !cmp.Equal(result, want) {
308 t.Errorf("Search.Users returned %+v, want %+v", result, want)
309 }
310 }
311
312 func TestSearchService_Users_coverage(t *testing.T) {
313 client, _, _, teardown := setup()
314 defer teardown()
315
316 ctx := context.Background()
317
318 const methodName = "Users"
319 testBadOptions(t, methodName, func() (err error) {
320 _, _, err = client.Search.Users(ctx, "\n", nil)
321 return err
322 })
323 }
324
325 func TestSearchService_Code(t *testing.T) {
326 client, mux, _, teardown := setup()
327 defer teardown()
328
329 mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) {
330 testMethod(t, r, "GET")
331 testFormValues(t, r, values{
332 "q": "blah",
333 "sort": "forks",
334 "order": "desc",
335 "page": "2",
336 "per_page": "2",
337 })
338
339 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"name":"1"},{"name":"2"}]}`)
340 })
341
342 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
343 ctx := context.Background()
344 result, _, err := client.Search.Code(ctx, "blah", opts)
345 if err != nil {
346 t.Errorf("Search.Code returned error: %v", err)
347 }
348
349 want := &CodeSearchResult{
350 Total: Int(4),
351 IncompleteResults: Bool(false),
352 CodeResults: []*CodeResult{{Name: String("1")}, {Name: String("2")}},
353 }
354 if !cmp.Equal(result, want) {
355 t.Errorf("Search.Code returned %+v, want %+v", result, want)
356 }
357 }
358
359 func TestSearchService_Code_coverage(t *testing.T) {
360 client, _, _, teardown := setup()
361 defer teardown()
362
363 ctx := context.Background()
364
365 const methodName = "Code"
366 testBadOptions(t, methodName, func() (err error) {
367 _, _, err = client.Search.Code(ctx, "\n", nil)
368 return err
369 })
370 }
371
372 func TestSearchService_CodeTextMatch(t *testing.T) {
373 client, mux, _, teardown := setup()
374 defer teardown()
375
376 mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) {
377 testMethod(t, r, "GET")
378
379 textMatchResponse := `
380 {
381 "total_count": 1,
382 "incomplete_results": false,
383 "items": [
384 {
385 "name":"gopher1",
386 "text_matches": [
387 {
388 "fragment": "I'm afraid my friend what you have found\nIs a gopher who lives to feed",
389 "matches": [
390 {
391 "text": "gopher",
392 "indices": [
393 14,
394 21
395 ]
396 }
397 ]
398 }
399 ]
400 }
401 ]
402 }
403 `
404
405 fmt.Fprint(w, textMatchResponse)
406 })
407
408 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}, TextMatch: true}
409 ctx := context.Background()
410 result, _, err := client.Search.Code(ctx, "blah", opts)
411 if err != nil {
412 t.Errorf("Search.Code returned error: %v", err)
413 }
414
415 wantedCodeResult := &CodeResult{
416 Name: String("gopher1"),
417 TextMatches: []*TextMatch{{
418 Fragment: String("I'm afraid my friend what you have found\nIs a gopher who lives to feed"),
419 Matches: []*Match{{Text: String("gopher"), Indices: []int{14, 21}}},
420 },
421 },
422 }
423
424 want := &CodeSearchResult{
425 Total: Int(1),
426 IncompleteResults: Bool(false),
427 CodeResults: []*CodeResult{wantedCodeResult},
428 }
429 if !cmp.Equal(result, want) {
430 t.Errorf("Search.Code returned %+v, want %+v", result, want)
431 }
432 }
433
434 func TestSearchService_Labels(t *testing.T) {
435 client, mux, _, teardown := setup()
436 defer teardown()
437
438 mux.HandleFunc("/search/labels", func(w http.ResponseWriter, r *http.Request) {
439 testMethod(t, r, "GET")
440 testFormValues(t, r, values{
441 "repository_id": "1234",
442 "q": "blah",
443 "sort": "updated",
444 "order": "desc",
445 "page": "2",
446 "per_page": "2",
447 })
448
449 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id": 1234, "name":"bug", "description": "some text"},{"id": 4567, "name":"feature"}]}`)
450 })
451
452 opts := &SearchOptions{Sort: "updated", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}}
453 ctx := context.Background()
454 result, _, err := client.Search.Labels(ctx, 1234, "blah", opts)
455 if err != nil {
456 t.Errorf("Search.Code returned error: %v", err)
457 }
458
459 want := &LabelsSearchResult{
460 Total: Int(4),
461 IncompleteResults: Bool(false),
462 Labels: []*LabelResult{
463 {ID: Int64(1234), Name: String("bug"), Description: String("some text")},
464 {ID: Int64(4567), Name: String("feature")},
465 },
466 }
467 if !cmp.Equal(result, want) {
468 t.Errorf("Search.Labels returned %+v, want %+v", result, want)
469 }
470 }
471
472 func TestSearchService_Labels_coverage(t *testing.T) {
473 client, _, _, teardown := setup()
474 defer teardown()
475
476 ctx := context.Background()
477
478 const methodName = "Labels"
479 testBadOptions(t, methodName, func() (err error) {
480 _, _, err = client.Search.Labels(ctx, -1234, "\n", nil)
481 return err
482 })
483 }
484
485 func TestMatch_Marshal(t *testing.T) {
486 testJSONMarshal(t, &Match{}, "{}")
487
488 u := &Match{
489 Text: String("txt"),
490 Indices: []int{1},
491 }
492
493 want := `{
494 "text": "txt",
495 "indices": [1]
496 }`
497
498 testJSONMarshal(t, u, want)
499 }
500
501 func TestTextMatch_Marshal(t *testing.T) {
502 testJSONMarshal(t, &TextMatch{}, "{}")
503
504 u := &TextMatch{
505 ObjectURL: String("ourl"),
506 ObjectType: String("otype"),
507 Property: String("prop"),
508 Fragment: String("fragment"),
509 Matches: []*Match{
510 {
511 Text: String("txt"),
512 Indices: []int{1},
513 },
514 },
515 }
516
517 want := `{
518 "object_url": "ourl",
519 "object_type": "otype",
520 "property": "prop",
521 "fragment": "fragment",
522 "matches": [{
523 "text": "txt",
524 "indices": [1]
525 }]
526 }`
527
528 testJSONMarshal(t, u, want)
529 }
530
531 func TestTopicResult_Marshal(t *testing.T) {
532 testJSONMarshal(t, &TopicResult{}, "{}")
533
534 u := &TopicResult{
535 Name: String("name"),
536 DisplayName: String("displayName"),
537 ShortDescription: String("shortDescription"),
538 Description: String("description"),
539 CreatedBy: String("createdBy"),
540 UpdatedAt: String("2021-10-26"),
541 Featured: Bool(false),
542 Curated: Bool(true),
543 Score: Float64(99.9),
544 }
545
546 want := `{
547 "name": "name",
548 "display_name": "displayName",
549 "short_description": "shortDescription",
550 "description": "description",
551 "created_by": "createdBy",
552 "updated_at": "2021-10-26",
553 "featured": false,
554 "curated": true,
555 "score": 99.9
556 }`
557
558 testJSONMarshal(t, u, want)
559 }
560
561 func TestRepositoriesSearchResult_Marshal(t *testing.T) {
562 testJSONMarshal(t, &RepositoriesSearchResult{}, "{}")
563
564 u := &RepositoriesSearchResult{
565 Total: Int(0),
566 IncompleteResults: Bool(true),
567 Repositories: []*Repository{{ID: Int64(1)}},
568 }
569
570 want := `{
571 "total_count" : 0,
572 "incomplete_results" : true,
573 "items" : [{"id":1}]
574 }`
575
576 testJSONMarshal(t, u, want)
577 }
578
579 func TestCommitsSearchResult_Marshal(t *testing.T) {
580 testJSONMarshal(t, &CommitsSearchResult{}, "{}")
581
582 c := &CommitsSearchResult{
583 Total: Int(0),
584 IncompleteResults: Bool(true),
585 Commits: []*CommitResult{{
586 SHA: String("s"),
587 }},
588 }
589
590 want := `{
591 "total_count" : 0,
592 "incomplete_results" : true,
593 "items" : [{"sha" : "s"}]
594 }`
595
596 testJSONMarshal(t, c, want)
597 }
598
599 func TestTopicsSearchResult_Marshal(t *testing.T) {
600 testJSONMarshal(t, &TopicsSearchResult{}, "{}")
601
602 u := &TopicsSearchResult{
603 Total: Int(2),
604 IncompleteResults: Bool(false),
605 Topics: []*TopicResult{
606 {
607 Name: String("t1"),
608 DisplayName: String("tt"),
609 ShortDescription: String("t desc"),
610 Description: String("desc"),
611 CreatedBy: String("mi"),
612 CreatedAt: &Timestamp{referenceTime},
613 UpdatedAt: String("2006-01-02T15:04:05Z"),
614 Featured: Bool(true),
615 Curated: Bool(true),
616 Score: Float64(123),
617 },
618 },
619 }
620
621 want := `{
622 "total_count" : 2,
623 "incomplete_results" : false,
624 "items" : [
625 {
626 "name" : "t1",
627 "display_name":"tt",
628 "short_description":"t desc",
629 "description":"desc",
630 "created_by":"mi",
631 "created_at":` + referenceTimeStr + `,
632 "updated_at":"2006-01-02T15:04:05Z",
633 "featured":true,
634 "curated":true,
635 "score":123
636 }
637 ]
638 }`
639
640 testJSONMarshal(t, u, want)
641 }
642
643 func TestLabelResult_Marshal(t *testing.T) {
644 testJSONMarshal(t, &LabelResult{}, "{}")
645
646 u := &LabelResult{
647 ID: Int64(11),
648 URL: String("url"),
649 Name: String("label"),
650 Color: String("green"),
651 Default: Bool(true),
652 Description: String("desc"),
653 Score: Float64(123),
654 }
655
656 want := `{
657 "id":11,
658 "url":"url",
659 "name":"label",
660 "color":"green",
661 "default":true,
662 "description":"desc",
663 "score":123
664 }`
665
666 testJSONMarshal(t, u, want)
667 }
668
669 func TestSearchOptions_Marshal(t *testing.T) {
670 testJSONMarshal(t, &SearchOptions{}, "{}")
671
672 u := &SearchOptions{
673 Sort: "author-date",
674 Order: "asc",
675 TextMatch: false,
676 ListOptions: ListOptions{
677 Page: int(1),
678 PerPage: int(10),
679 },
680 }
681
682 want := `{
683 "sort": "author-date",
684 "order": "asc",
685 "page": 1,
686 "perPage": 10
687 }`
688
689 testJSONMarshal(t, u, want)
690 }
691
692 func TestIssuesSearchResult_Marshal(t *testing.T) {
693 testJSONMarshal(t, &IssuesSearchResult{}, "{}")
694
695 u := &IssuesSearchResult{
696 Total: Int(48),
697 IncompleteResults: Bool(false),
698 Issues: []*Issue{
699 {
700 ID: Int64(1),
701 Number: Int(1),
702 State: String("s"),
703 Locked: Bool(false),
704 Title: String("title"),
705 Body: String("body"),
706 AuthorAssociation: String("aa"),
707 User: &User{ID: Int64(1)},
708 Labels: []*Label{{ID: Int64(1)}},
709 Assignee: &User{ID: Int64(1)},
710 Comments: Int(1),
711 ClosedAt: &referenceTime,
712 CreatedAt: &referenceTime,
713 UpdatedAt: &referenceTime,
714 ClosedBy: &User{ID: Int64(1)},
715 URL: String("url"),
716 HTMLURL: String("hurl"),
717 CommentsURL: String("curl"),
718 EventsURL: String("eurl"),
719 LabelsURL: String("lurl"),
720 RepositoryURL: String("rurl"),
721 Milestone: &Milestone{ID: Int64(1)},
722 PullRequestLinks: &PullRequestLinks{URL: String("url")},
723 Repository: &Repository{ID: Int64(1)},
724 Reactions: &Reactions{TotalCount: Int(1)},
725 Assignees: []*User{{ID: Int64(1)}},
726 NodeID: String("nid"),
727 TextMatches: []*TextMatch{{ObjectURL: String("ourl")}},
728 ActiveLockReason: String("alr"),
729 },
730 },
731 }
732
733 want := `{
734 "total_count": 48,
735 "incomplete_results": false,
736 "items": [
737 {
738 "id": 1,
739 "number": 1,
740 "state": "s",
741 "locked": false,
742 "title": "title",
743 "body": "body",
744 "author_association": "aa",
745 "user": {
746 "id": 1
747 },
748 "labels": [
749 {
750 "id": 1
751 }
752 ],
753 "assignee": {
754 "id": 1
755 },
756 "comments": 1,
757 "closed_at": ` + referenceTimeStr + `,
758 "created_at": ` + referenceTimeStr + `,
759 "updated_at": ` + referenceTimeStr + `,
760 "closed_by": {
761 "id": 1
762 },
763 "url": "url",
764 "html_url": "hurl",
765 "comments_url": "curl",
766 "events_url": "eurl",
767 "labels_url": "lurl",
768 "repository_url": "rurl",
769 "milestone": {
770 "id": 1
771 },
772 "pull_request": {
773 "url": "url"
774 },
775 "repository": {
776 "id": 1
777 },
778 "reactions": {
779 "total_count": 1
780 },
781 "assignees": [
782 {
783 "id": 1
784 }
785 ],
786 "node_id": "nid",
787 "text_matches": [
788 {
789 "object_url": "ourl"
790 }
791 ],
792 "active_lock_reason": "alr"
793 }
794 ]
795 }`
796
797 testJSONMarshal(t, u, want)
798 }
799
View as plain text