github.com/google/go-github/v66@v66.0.0/github/issue_import_test.go (about)

     1  // Copyright 2020 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"fmt"
    12  	"net/http"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/google/go-cmp/cmp"
    17  )
    18  
    19  func TestIssueImportService_Create(t *testing.T) {
    20  	t.Parallel()
    21  	client, mux, _ := setup(t)
    22  
    23  	createdAt := time.Date(2020, time.August, 11, 15, 30, 0, 0, time.UTC)
    24  	input := &IssueImportRequest{
    25  		IssueImport: IssueImport{
    26  			Assignee:  String("developer"),
    27  			Body:      "Dummy description",
    28  			CreatedAt: &Timestamp{createdAt},
    29  			Labels:    []string{"l1", "l2"},
    30  			Milestone: Int(1),
    31  			Title:     "Dummy Issue",
    32  		},
    33  		Comments: []*Comment{{
    34  			CreatedAt: &Timestamp{createdAt},
    35  			Body:      "Comment body",
    36  		}},
    37  	}
    38  
    39  	mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) {
    40  		v := new(IssueImportRequest)
    41  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
    42  		testMethod(t, r, "POST")
    43  		testHeader(t, r, "Accept", mediaTypeIssueImportAPI)
    44  		if !cmp.Equal(v, input) {
    45  			t.Errorf("Request body = %+v, want %+v", v, input)
    46  		}
    47  
    48  		assertWrite(t, w, issueImportResponseJSON)
    49  	})
    50  
    51  	ctx := context.Background()
    52  	got, _, err := client.IssueImport.Create(ctx, "o", "r", input)
    53  	if err != nil {
    54  		t.Errorf("Create returned error: %v", err)
    55  	}
    56  
    57  	want := wantIssueImportResponse
    58  	if !cmp.Equal(got, want) {
    59  		t.Errorf("Create = %+v, want %+v", got, want)
    60  	}
    61  
    62  	const methodName = "Create"
    63  	testBadOptions(t, methodName, func() (err error) {
    64  		_, _, err = client.IssueImport.Create(ctx, "\n", "\n", input)
    65  		return err
    66  	})
    67  
    68  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    69  		got, resp, err := client.IssueImport.Create(ctx, "o", "r", input)
    70  		if got != nil {
    71  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    72  		}
    73  		return resp, err
    74  	})
    75  }
    76  
    77  func TestIssueImportService_Create_deferred(t *testing.T) {
    78  	t.Parallel()
    79  	client, mux, _ := setup(t)
    80  
    81  	createdAt := time.Date(2020, time.August, 11, 15, 30, 0, 0, time.UTC)
    82  	input := &IssueImportRequest{
    83  		IssueImport: IssueImport{
    84  			Assignee:  String("developer"),
    85  			Body:      "Dummy description",
    86  			CreatedAt: &Timestamp{createdAt},
    87  			Labels:    []string{"l1", "l2"},
    88  			Milestone: Int(1),
    89  			Title:     "Dummy Issue",
    90  		},
    91  		Comments: []*Comment{{
    92  			CreatedAt: &Timestamp{createdAt},
    93  			Body:      "Comment body",
    94  		}},
    95  	}
    96  
    97  	mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) {
    98  		v := new(IssueImportRequest)
    99  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   100  		testMethod(t, r, "POST")
   101  		testHeader(t, r, "Accept", mediaTypeIssueImportAPI)
   102  		if !cmp.Equal(v, input) {
   103  			t.Errorf("Request body = %+v, want %+v", v, input)
   104  		}
   105  
   106  		w.WriteHeader(http.StatusAccepted)
   107  		assertWrite(t, w, issueImportResponseJSON)
   108  	})
   109  
   110  	ctx := context.Background()
   111  	got, _, err := client.IssueImport.Create(ctx, "o", "r", input)
   112  
   113  	if _, ok := err.(*AcceptedError); !ok {
   114  		t.Errorf("Create returned error: %v (want AcceptedError)", err)
   115  	}
   116  
   117  	want := wantIssueImportResponse
   118  	if !cmp.Equal(got, want) {
   119  		t.Errorf("Create = %+v, want %+v", got, want)
   120  	}
   121  }
   122  
   123  func TestIssueImportService_Create_badResponse(t *testing.T) {
   124  	t.Parallel()
   125  	client, mux, _ := setup(t)
   126  
   127  	createdAt := time.Date(2020, time.August, 11, 15, 30, 0, 0, time.UTC)
   128  	input := &IssueImportRequest{
   129  		IssueImport: IssueImport{
   130  			Assignee:  String("developer"),
   131  			Body:      "Dummy description",
   132  			CreatedAt: &Timestamp{createdAt},
   133  			Labels:    []string{"l1", "l2"},
   134  			Milestone: Int(1),
   135  			Title:     "Dummy Issue",
   136  		},
   137  		Comments: []*Comment{{
   138  			CreatedAt: &Timestamp{createdAt},
   139  			Body:      "Comment body",
   140  		}},
   141  	}
   142  
   143  	mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) {
   144  		v := new(IssueImportRequest)
   145  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   146  		testMethod(t, r, "POST")
   147  		testHeader(t, r, "Accept", mediaTypeIssueImportAPI)
   148  		if !cmp.Equal(v, input) {
   149  			t.Errorf("Request body = %+v, want %+v", v, input)
   150  		}
   151  
   152  		w.WriteHeader(http.StatusAccepted)
   153  		assertWrite(t, w, []byte("{[}"))
   154  	})
   155  
   156  	ctx := context.Background()
   157  	_, _, err := client.IssueImport.Create(ctx, "o", "r", input)
   158  
   159  	if err == nil || err.Error() != "invalid character '[' looking for beginning of object key string" {
   160  		t.Errorf("unexpected error: %v", err)
   161  	}
   162  }
   163  
   164  func TestIssueImportService_Create_invalidOwner(t *testing.T) {
   165  	t.Parallel()
   166  	client, _, _ := setup(t)
   167  
   168  	ctx := context.Background()
   169  	_, _, err := client.IssueImport.Create(ctx, "%", "r", nil)
   170  	testURLParseError(t, err)
   171  }
   172  
   173  func TestIssueImportService_CheckStatus(t *testing.T) {
   174  	t.Parallel()
   175  	client, mux, _ := setup(t)
   176  
   177  	mux.HandleFunc("/repos/o/r/import/issues/3", func(w http.ResponseWriter, r *http.Request) {
   178  		testMethod(t, r, "GET")
   179  		testHeader(t, r, "Accept", mediaTypeIssueImportAPI)
   180  		w.WriteHeader(http.StatusOK)
   181  		assertWrite(t, w, issueImportResponseJSON)
   182  	})
   183  
   184  	ctx := context.Background()
   185  	got, _, err := client.IssueImport.CheckStatus(ctx, "o", "r", 3)
   186  	if err != nil {
   187  		t.Errorf("CheckStatus returned error: %v", err)
   188  	}
   189  
   190  	want := wantIssueImportResponse
   191  	if !cmp.Equal(got, want) {
   192  		t.Errorf("CheckStatus = %+v, want %+v", got, want)
   193  	}
   194  
   195  	const methodName = "CheckStatus"
   196  	testBadOptions(t, methodName, func() (err error) {
   197  		_, _, err = client.IssueImport.CheckStatus(ctx, "\n", "\n", -3)
   198  		return err
   199  	})
   200  
   201  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   202  		got, resp, err := client.IssueImport.CheckStatus(ctx, "o", "r", 3)
   203  		if got != nil {
   204  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   205  		}
   206  		return resp, err
   207  	})
   208  }
   209  
   210  func TestIssueImportService_CheckStatus_invalidOwner(t *testing.T) {
   211  	t.Parallel()
   212  	client, _, _ := setup(t)
   213  
   214  	ctx := context.Background()
   215  	_, _, err := client.IssueImport.CheckStatus(ctx, "%", "r", 1)
   216  	testURLParseError(t, err)
   217  }
   218  
   219  func TestIssueImportService_CheckStatusSince(t *testing.T) {
   220  	t.Parallel()
   221  	client, mux, _ := setup(t)
   222  
   223  	mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) {
   224  		testMethod(t, r, "GET")
   225  		testHeader(t, r, "Accept", mediaTypeIssueImportAPI)
   226  		w.WriteHeader(http.StatusOK)
   227  		assertWrite(t, w, []byte(fmt.Sprintf("[%s]", issueImportResponseJSON)))
   228  	})
   229  
   230  	ctx := context.Background()
   231  	got, _, err := client.IssueImport.CheckStatusSince(ctx, "o", "r", Timestamp{time.Now()})
   232  	if err != nil {
   233  		t.Errorf("CheckStatusSince returned error: %v", err)
   234  	}
   235  
   236  	want := []*IssueImportResponse{wantIssueImportResponse}
   237  	if !cmp.Equal(want, got) {
   238  		t.Errorf("CheckStatusSince = %v, want = %v", got, want)
   239  	}
   240  
   241  	const methodName = "CheckStatusSince"
   242  	testBadOptions(t, methodName, func() (err error) {
   243  		_, _, err = client.IssueImport.CheckStatusSince(ctx, "\n", "\n", Timestamp{time.Now()})
   244  		return err
   245  	})
   246  
   247  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   248  		got, resp, err := client.IssueImport.CheckStatusSince(ctx, "o", "r", Timestamp{time.Now()})
   249  		if got != nil {
   250  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   251  		}
   252  		return resp, err
   253  	})
   254  }
   255  
   256  func TestIssueImportService_CheckStatusSince_badResponse(t *testing.T) {
   257  	t.Parallel()
   258  	client, mux, _ := setup(t)
   259  
   260  	mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) {
   261  		testMethod(t, r, "GET")
   262  		testHeader(t, r, "Accept", mediaTypeIssueImportAPI)
   263  		w.WriteHeader(http.StatusOK)
   264  		assertWrite(t, w, []byte("{badly-formed JSON"))
   265  	})
   266  
   267  	ctx := context.Background()
   268  	if _, _, err := client.IssueImport.CheckStatusSince(ctx, "o", "r", Timestamp{time.Now()}); err == nil {
   269  		t.Errorf("CheckStatusSince returned no error, want JSON err")
   270  	}
   271  }
   272  
   273  func TestIssueImportService_CheckStatusSince_invalidOwner(t *testing.T) {
   274  	t.Parallel()
   275  	client, _, _ := setup(t)
   276  
   277  	ctx := context.Background()
   278  	_, _, err := client.IssueImport.CheckStatusSince(ctx, "%", "r", Timestamp{time.Now()})
   279  	testURLParseError(t, err)
   280  }
   281  
   282  var issueImportResponseJSON = []byte(`{
   283  	"id": 3,
   284  	"status": "pending",
   285  	"url": "https://api.github.com/repos/o/r/import/issues/3",
   286  	"import_issues_url": "https://api.github.com/repos/o/r/import/issues",
   287  	"repository_url": "https://api.github.com/repos/o/r"
   288  }`)
   289  
   290  var wantIssueImportResponse = &IssueImportResponse{
   291  	ID:              Int(3),
   292  	Status:          String("pending"),
   293  	URL:             String("https://api.github.com/repos/o/r/import/issues/3"),
   294  	ImportIssuesURL: String("https://api.github.com/repos/o/r/import/issues"),
   295  	RepositoryURL:   String("https://api.github.com/repos/o/r"),
   296  }
   297  
   298  func TestIssueImportError_Marshal(t *testing.T) {
   299  	t.Parallel()
   300  	testJSONMarshal(t, &IssueImportError{}, "{}")
   301  
   302  	u := &IssueImportError{
   303  		Location: String("loc"),
   304  		Resource: String("res"),
   305  		Field:    String("field"),
   306  		Value:    String("value"),
   307  		Code:     String("code"),
   308  	}
   309  
   310  	want := `{
   311  		"location": "loc",
   312  		"resource": "res",
   313  		"field": "field",
   314  		"value": "value",
   315  		"code": "code"
   316  	}`
   317  
   318  	testJSONMarshal(t, u, want)
   319  }
   320  
   321  func TestIssueImportResponse_Marshal(t *testing.T) {
   322  	t.Parallel()
   323  	testJSONMarshal(t, &IssueImportResponse{}, "{}")
   324  
   325  	u := &IssueImportResponse{
   326  		ID:               Int(1),
   327  		Status:           String("status"),
   328  		URL:              String("url"),
   329  		ImportIssuesURL:  String("iiu"),
   330  		RepositoryURL:    String("ru"),
   331  		CreatedAt:        &Timestamp{referenceTime},
   332  		UpdatedAt:        &Timestamp{referenceTime},
   333  		Message:          String("msg"),
   334  		DocumentationURL: String("durl"),
   335  		Errors: []*IssueImportError{
   336  			{
   337  				Location: String("loc"),
   338  				Resource: String("res"),
   339  				Field:    String("field"),
   340  				Value:    String("value"),
   341  				Code:     String("code"),
   342  			},
   343  		},
   344  	}
   345  
   346  	want := `{
   347  		"id": 1,
   348  		"status": "status",
   349  		"url": "url",
   350  		"import_issues_url": "iiu",
   351  		"repository_url": "ru",
   352  		"created_at": ` + referenceTimeStr + `,
   353  		"updated_at": ` + referenceTimeStr + `,
   354  		"message": "msg",
   355  		"documentation_url": "durl",
   356  		"errors": [
   357  			{
   358  				"location": "loc",
   359  				"resource": "res",
   360  				"field": "field",
   361  				"value": "value",
   362  				"code": "code"
   363  			}
   364  		]
   365  	}`
   366  
   367  	testJSONMarshal(t, u, want)
   368  }
   369  
   370  func TestComment_Marshal(t *testing.T) {
   371  	t.Parallel()
   372  	testJSONMarshal(t, &Comment{}, "{}")
   373  
   374  	u := &Comment{
   375  		CreatedAt: &Timestamp{referenceTime},
   376  		Body:      "body",
   377  	}
   378  
   379  	want := `{
   380  		"created_at": ` + referenceTimeStr + `,
   381  		"body": "body"
   382  	}`
   383  
   384  	testJSONMarshal(t, u, want)
   385  }
   386  
   387  func TestIssueImport_Marshal(t *testing.T) {
   388  	t.Parallel()
   389  	testJSONMarshal(t, &IssueImport{}, "{}")
   390  
   391  	u := &IssueImport{
   392  		Title:     "title",
   393  		Body:      "body",
   394  		CreatedAt: &Timestamp{referenceTime},
   395  		ClosedAt:  &Timestamp{referenceTime},
   396  		UpdatedAt: &Timestamp{referenceTime},
   397  		Assignee:  String("a"),
   398  		Milestone: Int(1),
   399  		Closed:    Bool(false),
   400  		Labels:    []string{"l"},
   401  	}
   402  
   403  	want := `{
   404  		"title": "title",
   405  		"body": "body",
   406  		"created_at": ` + referenceTimeStr + `,
   407  		"closed_at": ` + referenceTimeStr + `,
   408  		"updated_at": ` + referenceTimeStr + `,
   409  		"assignee": "a",
   410  		"milestone": 1,
   411  		"closed": false,
   412  		"labels": [
   413  			"l"
   414  		]
   415  	}`
   416  
   417  	testJSONMarshal(t, u, want)
   418  }
   419  
   420  func TestIssueImportRequest_Marshal(t *testing.T) {
   421  	t.Parallel()
   422  	testJSONMarshal(t, &IssueImportRequest{}, "{}")
   423  
   424  	u := &IssueImportRequest{
   425  		IssueImport: IssueImport{
   426  			Title:     "title",
   427  			Body:      "body",
   428  			CreatedAt: &Timestamp{referenceTime},
   429  			ClosedAt:  &Timestamp{referenceTime},
   430  			UpdatedAt: &Timestamp{referenceTime},
   431  			Assignee:  String("a"),
   432  			Milestone: Int(1),
   433  			Closed:    Bool(false),
   434  			Labels:    []string{"l"},
   435  		},
   436  		Comments: []*Comment{
   437  			{
   438  				CreatedAt: &Timestamp{referenceTime},
   439  				Body:      "body",
   440  			},
   441  		},
   442  	}
   443  
   444  	want := `{
   445  		"issue": {
   446  			"title": "title",
   447  			"body": "body",
   448  			"created_at": ` + referenceTimeStr + `,
   449  			"closed_at": ` + referenceTimeStr + `,
   450  			"updated_at": ` + referenceTimeStr + `,
   451  			"assignee": "a",
   452  			"milestone": 1,
   453  			"closed": false,
   454  			"labels": [
   455  				"l"
   456  			]
   457  		},
   458  		"comments": [
   459  			{
   460  				"created_at": ` + referenceTimeStr + `,
   461  				"body": "body"
   462  			}
   463  		]
   464  	}`
   465  
   466  	testJSONMarshal(t, u, want)
   467  }