Repository: google/go-github
Pull request #2948 (2023-10-03 15:43:20)

Escape branch string before inserting it in URL
When a branch name with special characters like `%` is passed to the [`RepositoryService.GetBranch()` method](https://github.com/google/go-github/blob/8cd452b85e821c32eefcc5964e91e57f9731891f/github/repos.go#L1277) as is, an error is currently returned:
```
invalid URL escape "%"
```

Passing an escaped branch name to `RepositoriesService.GetBranch()` works fine.

Here's a minimal reproducer
```golang
import (
	"context"
	"net/http"
	"testing"

	"github.com/google/go-github/v53/github"
	"github.com/stretchr/testify/require"
)

func TestGetBranch(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	githubClient := github.NewClient(&http.Client{
		Transport: http.DefaultTransport,
	})
	owner := "samstickkz"
	project := "curr"
	branchName := "Feature/authentication_90%"
	branch, response, err := githubClient.Repositories.GetBranch(ctx, owner, project, branchName, false)

	require.Nil(t, err)
	t.Logf("Response: %+v", response)
	t.Logf("Branch: %+v", branch)
}
```

This sounds like a bug to me, as I believe users of that method shouldn't be expected to escape the branch name before calling it, as this is a private implementation quirk that they shouldn't be aware of. This PR patches all branch-related methods to automatically escape the branch name in the endpoint URL. 

There's actually [a precedent for `ref` parameter](https://github.com/google/go-github/pull/2454), and I suspect that other variables are prone to the same issue. I am conservatively patching only the branch variable, as this is the only one I have tested thoroughly. Note that, contrary to `ref` use case, my tests suggest that it's okay to escape `/` characters for branch names. 

:warning: Breaking change: for users that currently _bypass_ this issue by feeding escaped strings to `RepositoryService.GetBranch()` method (and other branch-related methods), this change will be breaking.

gmlewis: Honestly, I'm quite surprised that this issue has never come up before... as this repo is how many years old? 10?!?

However, I think you are right.

I'm wondering if each of the modified endpoints needs a comment in the documentation stating something like:

```
// Note that the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape
```
k0ral: @gmlewis PR updated with additional comments and unit tests.

Patch:
diff --git a/github/event_types.go b/github/event_types.go
index 3161384f..b3e58b33 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -76,6 +76,10 @@ type CommitCommentEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // ContentReferenceEvent is triggered when the body or comment of an issue or
@@ -132,6 +136,10 @@ type DeleteEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // DependabotAlertEvent is triggered when there is activity relating to Dependabot alerts.
@@ -192,6 +200,10 @@ type DeploymentEvent struct {
 	// The following fields are only populated by Webhook events.
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // DeploymentProtectionRuleEvent represents a deployment protection rule event.
@@ -227,6 +239,10 @@ type DeploymentStatusEvent struct {
 	// The following fields are only populated by Webhook events.
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // DiscussionCommentEvent represents a webhook event for a comment on discussion.
@@ -363,6 +379,10 @@ type GollumEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // EditChange represents the changes when an issue, pull request, comment,
@@ -510,6 +530,10 @@ type InstallationEvent struct {
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
 	Requester    *User         `json:"requester,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // InstallationRepositoriesEvent is triggered when a repository is added or
@@ -524,6 +548,10 @@ type InstallationRepositoriesEvent struct {
 	RepositorySelection *string       `json:"repository_selection,omitempty"`
 	Sender              *User         `json:"sender,omitempty"`
 	Installation        *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // InstallationLoginChange represents a change in login on an installation.
@@ -603,6 +631,10 @@ type IssuesEvent struct {
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
 	Milestone    *Milestone    `json:"milestone,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // LabelEvent is triggered when a repository's label is created, edited, or deleted.
@@ -639,6 +671,10 @@ type MarketplacePurchaseEvent struct {
 	PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"`
 	Sender                      *User                `json:"sender,omitempty"`
 	Installation                *Installation        `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // MemberEvent is triggered when a user is added as a collaborator to a repository.
@@ -654,6 +690,10 @@ type MemberEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // MembershipEvent is triggered when a user is added or removed from a team.
@@ -825,6 +865,10 @@ type PageBuildEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // PersonalAccessTokenRequestEvent occurs when there is activity relating to a
@@ -885,6 +929,10 @@ type PersonalAccessTokenRequest struct {
 
 	// Date and time when the associated fine-grained personal access token was last used for authentication.
 	TokenLastUsedAt *Timestamp `json:"token_last_used_at,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // PersonalAccessTokenPermissions represents the original or newly requested
@@ -1044,6 +1092,10 @@ type PublicEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled,
@@ -1129,6 +1181,10 @@ type PullRequestReviewCommentEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // PullRequestReviewThreadEvent is triggered when a comment made as part of a
@@ -1147,6 +1203,10 @@ type PullRequestReviewThreadEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // PullRequestTargetEvent is triggered when a pull request is assigned, unassigned, labeled,
@@ -1315,6 +1375,10 @@ type ReleaseEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // RepositoryEvent is triggered when a repository is created, archived, unarchived,
@@ -1385,6 +1449,10 @@ type RepositoryVulnerabilityAlertEvent struct {
 
 	// The user that triggered the event.
 	Sender *User `json:"sender,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // RepositoryVulnerabilityAlert represents a repository security alert.
@@ -1491,6 +1559,10 @@ type StatusEvent struct {
 	Repo         *Repository       `json:"repository,omitempty"`
 	Sender       *User             `json:"sender,omitempty"`
 	Installation *Installation     `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // TeamEvent is triggered when an organization's team is created, modified or deleted.
@@ -1561,6 +1633,10 @@ type WatchEvent struct {
 	Repo         *Repository   `json:"repository,omitempty"`
 	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Org *Organization `json:"organization,omitempty"`
 }
 
 // WorkflowDispatchEvent is triggered when someone triggers a workflow run on GitHub or
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 73170816..8519de2d 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -3814,6 +3814,14 @@ func (c *CommitCommentEvent) GetInstallation() *Installation {
 	return c.Installation
 }
 
+// GetOrg returns the Org field.
+func (c *CommitCommentEvent) GetOrg() *Organization {
+	if c == nil {
+		return nil
+	}
+	return c.Org
+}
+
 // GetRepo returns the Repo field.
 func (c *CommitCommentEvent) GetRepo() *Repository {
 	if c == nil {
@@ -5046,6 +5054,14 @@ func (d *DeleteEvent) GetInstallation() *Installation {
 	return d.Installation
 }
 
+// GetOrg returns the Org field.
+func (d *DeleteEvent) GetOrg() *Organization {
+	if d == nil {
+		return nil
+	}
+	return d.Org
+}
+
 // GetPusherType returns the PusherType field if it's non-nil, zero value otherwise.
 func (d *DeleteEvent) GetPusherType() string {
 	if d == nil || d.PusherType == nil {
@@ -5582,6 +5598,14 @@ func (d *DeploymentEvent) GetInstallation() *Installation {
 	return d.Installation
 }
 
+// GetOrg returns the Org field.
+func (d *DeploymentEvent) GetOrg() *Organization {
+	if d == nil {
+		return nil
+	}
+	return d.Org
+}
+
 // GetRepo returns the Repo field.
 func (d *DeploymentEvent) GetRepo() *Repository {
 	if d == nil {
@@ -5886,6 +5910,14 @@ func (d *DeploymentStatusEvent) GetInstallation() *Installation {
 	return d.Installation
 }
 
+// GetOrg returns the Org field.
+func (d *DeploymentStatusEvent) GetOrg() *Organization {
+	if d == nil {
+		return nil
+	}
+	return d.Org
+}
+
 // GetRepo returns the Repo field.
 func (d *DeploymentStatusEvent) GetRepo() *Repository {
 	if d == nil {
@@ -7686,6 +7718,14 @@ func (g *GollumEvent) GetInstallation() *Installation {
 	return g.Installation
 }
 
+// GetOrg returns the Org field.
+func (g *GollumEvent) GetOrg() *Organization {
+	if g == nil {
+		return nil
+	}
+	return g.Org
+}
+
 // GetRepo returns the Repo field.
 func (g *GollumEvent) GetRepo() *Repository {
 	if g == nil {
@@ -8558,6 +8598,14 @@ func (i *InstallationEvent) GetInstallation() *Installation {
 	return i.Installation
 }
 
+// GetOrg returns the Org field.
+func (i *InstallationEvent) GetOrg() *Organization {
+	if i == nil {
+		return nil
+	}
+	return i.Org
+}
+
 // GetRequester returns the Requester field.
 func (i *InstallationEvent) GetRequester() *User {
 	if i == nil {
@@ -8894,6 +8942,14 @@ func (i *InstallationRepositoriesEvent) GetInstallation() *Installation {
 	return i.Installation
 }
 
+// GetOrg returns the Org field.
+func (i *InstallationRepositoriesEvent) GetOrg() *Organization {
+	if i == nil {
+		return nil
+	}
+	return i.Org
+}
+
 // GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise.
 func (i *InstallationRepositoriesEvent) GetRepositorySelection() string {
 	if i == nil || i.RepositorySelection == nil {
@@ -9998,6 +10054,14 @@ func (i *IssuesEvent) GetMilestone() *Milestone {
 	return i.Milestone
 }
 
+// GetOrg returns the Org field.
+func (i *IssuesEvent) GetOrg() *Organization {
+	if i == nil {
+		return nil
+	}
+	return i.Org
+}
+
 // GetRepo returns the Repo field.
 func (i *IssuesEvent) GetRepo() *Repository {
 	if i == nil {
@@ -11046,6 +11110,14 @@ func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase
 	return m.MarketplacePurchase
 }
 
+// GetOrg returns the Org field.
+func (m *MarketplacePurchaseEvent) GetOrg() *Organization {
+	if m == nil {
+		return nil
+	}
+	return m.Org
+}
+
 // GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field.
 func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase {
 	if m == nil {
@@ -11094,6 +11166,14 @@ func (m *MemberEvent) GetMember() *User {
 	return m.Member
 }
 
+// GetOrg returns the Org field.
+func (m *MemberEvent) GetOrg() *Organization {
+	if m == nil {
+		return nil
+	}
+	return m.Org
+}
+
 // GetRepo returns the Repo field.
 func (m *MemberEvent) GetRepo() *Repository {
 	if m == nil {
@@ -13326,6 +13406,14 @@ func (p *PageBuildEvent) GetInstallation() *Installation {
 	return p.Installation
 }
 
+// GetOrg returns the Org field.
+func (p *PageBuildEvent) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
 // GetRepo returns the Repo field.
 func (p *PageBuildEvent) GetRepo() *Repository {
 	if p == nil {
@@ -13862,6 +13950,14 @@ func (p *PersonalAccessTokenRequest) GetID() int64 {
 	return *p.ID
 }
 
+// GetOrg returns the Org field.
+func (p *PersonalAccessTokenRequest) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
 // GetOwner returns the Owner field.
 func (p *PersonalAccessTokenRequest) GetOwner() *User {
 	if p == nil {
@@ -15454,6 +15550,14 @@ func (p *PublicEvent) GetInstallation() *Installation {
 	return p.Installation
 }
 
+// GetOrg returns the Org field.
+func (p *PublicEvent) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
 // GetRepo returns the Repo field.
 func (p *PublicEvent) GetRepo() *Repository {
 	if p == nil {
@@ -16430,6 +16534,14 @@ func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation {
 	return p.Installation
 }
 
+// GetOrg returns the Org field.
+func (p *PullRequestReviewCommentEvent) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
 // GetPullRequest returns the PullRequest field.
 func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest {
 	if p == nil {
@@ -16654,6 +16766,14 @@ func (p *PullRequestReviewThreadEvent) GetInstallation() *Installation {
 	return p.Installation
 }
 
+// GetOrg returns the Org field.
+func (p *PullRequestReviewThreadEvent) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
 // GetPullRequest returns the PullRequest field.
 func (p *PullRequestReviewThreadEvent) GetPullRequest() *PullRequest {
 	if p == nil {
@@ -17686,6 +17806,14 @@ func (r *ReleaseEvent) GetInstallation() *Installation {
 	return r.Installation
 }
 
+// GetOrg returns the Org field.
+func (r *ReleaseEvent) GetOrg() *Organization {
+	if r == nil {
+		return nil
+	}
+	return r.Org
+}
+
 // GetRelease returns the Release field.
 func (r *ReleaseEvent) GetRelease() *RepositoryRelease {
 	if r == nil {
@@ -19774,6 +19902,14 @@ func (r *RepositoryVulnerabilityAlertEvent) GetInstallation() *Installation {
 	return r.Installation
 }
 
+// GetOrg returns the Org field.
+func (r *RepositoryVulnerabilityAlertEvent) GetOrg() *Organization {
+	if r == nil {
+		return nil
+	}
+	return r.Org
+}
+
 // GetRepository returns the Repository field.
 func (r *RepositoryVulnerabilityAlertEvent) GetRepository() *Repository {
 	if r == nil {
@@ -21622,6 +21758,14 @@ func (s *StatusEvent) GetName() string {
 	return *s.Name
 }
 
+// GetOrg returns the Org field.
+func (s *StatusEvent) GetOrg() *Organization {
+	if s == nil {
+		return nil
+	}
+	return s.Org
+}
+
 // GetRepo returns the Repo field.
 func (s *StatusEvent) GetRepo() *Repository {
 	if s == nil {
@@ -23950,6 +24094,14 @@ func (w *WatchEvent) GetInstallation() *Installation {
 	return w.Installation
 }
 
+// GetOrg returns the Org field.
+func (w *WatchEvent) GetOrg() *Organization {
+	if w == nil {
+		return nil
+	}
+	return w.Org
+}
+
 // GetRepo returns the Repo field.
 func (w *WatchEvent) GetRepo() *Repository {
 	if w == nil {
diff --git a/github/repos.go b/github/repos.go
index e09971ab..f2059926 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -11,6 +11,7 @@ import (
 	"errors"
 	"fmt"
 	"net/http"
+	"net/url"
 	"strings"
 )
 
@@ -1273,9 +1274,11 @@ func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, re
 
 // GetBranch gets the specified branch for a repository.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branches#get-a-branch
 func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, maxRedirects int) (*Branch, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, url.PathEscape(branch))
 
 	resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, maxRedirects)
 	if err != nil {
@@ -1302,9 +1305,11 @@ type renameBranchRequest struct {
 // To rename a non-default branch: Users must have push access. GitHub Apps must have the `contents:write` repository permission.
 // To rename the default branch: Users must have admin or owner permissions. GitHub Apps must have the `administration:write` repository permission.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branches#rename-a-branch
 func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, branch, newName string) (*Branch, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, url.PathEscape(branch))
 	r := &renameBranchRequest{NewName: newName}
 	req, err := s.client.NewRequest("POST", u, r)
 	if err != nil {
@@ -1322,9 +1327,11 @@ func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, bra
 
 // GetBranchProtection gets the protection of a given branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-branch-protection
 func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1347,9 +1354,11 @@ func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, re
 
 // GetRequiredStatusChecks gets the required status checks for a given protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-status-checks-protection
 func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1369,9 +1378,11 @@ func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner
 
 // ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-all-status-check-contexts
 func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1390,9 +1401,11 @@ func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Conte
 
 // UpdateBranchProtection updates the protection of a given branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-branch-protection
 func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("PUT", u, preq)
 	if err != nil {
 		return nil, nil, err
@@ -1412,9 +1425,11 @@ func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner,
 
 // RemoveBranchProtection removes the protection of a given branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-branch-protection
 func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, nil)
 	if err != nil {
 		return nil, err
@@ -1425,9 +1440,11 @@ func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner,
 
 // GetSignaturesProtectedBranch gets required signatures of protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-commit-signature-protection
 func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1448,9 +1465,11 @@ func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context,
 // RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch.
 // It requires admin access and branch protection to be enabled.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#create-commit-signature-protection
 func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("POST", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1470,9 +1489,11 @@ func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Con
 
 // OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-commit-signature-protection
 func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, nil)
 	if err != nil {
 		return nil, err
@@ -1486,9 +1507,11 @@ func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Co
 
 // UpdateRequiredStatusChecks updates the required status checks for a given protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-status-check-protection
 func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("PATCH", u, sreq)
 	if err != nil {
 		return nil, nil, err
@@ -1505,9 +1528,11 @@ func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, ow
 
 // RemoveRequiredStatusChecks removes the required status checks for a given protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-status-check-protection
 func (s *RepositoriesService) RemoveRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, nil)
 	if err != nil {
 		return nil, err
@@ -1537,9 +1562,11 @@ func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (
 
 // GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-pull-request-review-protection
 func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1560,9 +1587,11 @@ func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Contex
 // UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch.
 // It requires admin access and branch protection to be enabled.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection
 func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("PATCH", u, patch)
 	if err != nil {
 		return nil, nil, err
@@ -1583,9 +1612,11 @@ func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Con
 // DisableDismissalRestrictions disables dismissal restrictions of a protected branch.
 // It requires admin access and branch protection to be enabled.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection
 func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch))
 
 	data := new(struct {
 		DismissalRestrictionsRequest `json:"dismissal_restrictions"`
@@ -1610,9 +1641,11 @@ func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context,
 
 // RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-pull-request-review-protection
 func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, nil)
 	if err != nil {
 		return nil, err
@@ -1623,9 +1656,11 @@ func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Con
 
 // GetAdminEnforcement gets admin enforcement information of a protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-admin-branch-protection
 func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1643,9 +1678,11 @@ func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, re
 // AddAdminEnforcement adds admin enforcement to a protected branch.
 // It requires admin access and branch protection to be enabled.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-admin-branch-protection
 func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("POST", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1662,9 +1699,11 @@ func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, re
 
 // RemoveAdminEnforcement removes admin enforcement from a protected branch.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-admin-branch-protection
 func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, nil)
 	if err != nil {
 		return nil, err
@@ -1731,11 +1770,13 @@ func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo
 // ListApps lists the GitHub apps that have push access to a given protected branch.
 // It requires the GitHub apps to have `write` access to the `content` permission.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch
 //
 // Deprecated: Please use ListAppRestrictions instead.
 func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1766,9 +1807,11 @@ func (s *RepositoriesService) ListAppRestrictions(ctx context.Context, owner, re
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-app-access-restrictions
 func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("PUT", u, apps)
 	if err != nil {
 		return nil, nil, err
@@ -1788,9 +1831,11 @@ func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner,
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#add-app-access-restrictions
 func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("POST", u, apps)
 	if err != nil {
 		return nil, nil, err
@@ -1810,9 +1855,11 @@ func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, rep
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-app-access-restrictions
 func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, apps []string) ([]*App, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, apps)
 	if err != nil {
 		return nil, nil, err
@@ -1830,9 +1877,11 @@ func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner,
 // ListTeamRestrictions lists the GitHub teams that have push access to a given protected branch.
 // It requires the GitHub teams to have `write` access to the `content` permission.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-teams-with-access-to-the-protected-branch
 func (s *RepositoriesService) ListTeamRestrictions(ctx context.Context, owner, repo, branch string) ([]*Team, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1853,9 +1902,11 @@ func (s *RepositoriesService) ListTeamRestrictions(ctx context.Context, owner, r
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-team-access-restrictions
 func (s *RepositoriesService) ReplaceTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("PUT", u, teams)
 	if err != nil {
 		return nil, nil, err
@@ -1875,9 +1926,11 @@ func (s *RepositoriesService) ReplaceTeamRestrictions(ctx context.Context, owner
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#add-team-access-restrictions
 func (s *RepositoriesService) AddTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("POST", u, teams)
 	if err != nil {
 		return nil, nil, err
@@ -1897,9 +1950,11 @@ func (s *RepositoriesService) AddTeamRestrictions(ctx context.Context, owner, re
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-team-access-restrictions
 func (s *RepositoriesService) RemoveTeamRestrictions(ctx context.Context, owner, repo, branch string, teams []string) ([]*Team, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/teams", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, teams)
 	if err != nil {
 		return nil, nil, err
@@ -1917,9 +1972,11 @@ func (s *RepositoriesService) RemoveTeamRestrictions(ctx context.Context, owner,
 // ListUserRestrictions lists the GitHub users that have push access to a given protected branch.
 // It requires the GitHub users to have `write` access to the `content` permission.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-users-with-access-to-the-protected-branch
 func (s *RepositoriesService) ListUserRestrictions(ctx context.Context, owner, repo, branch string) ([]*User, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
 		return nil, nil, err
@@ -1940,9 +1997,11 @@ func (s *RepositoriesService) ListUserRestrictions(ctx context.Context, owner, r
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-team-access-restrictions
 func (s *RepositoriesService) ReplaceUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("PUT", u, users)
 	if err != nil {
 		return nil, nil, err
@@ -1962,9 +2021,11 @@ func (s *RepositoriesService) ReplaceUserRestrictions(ctx context.Context, owner
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#add-team-access-restrictions
 func (s *RepositoriesService) AddUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("POST", u, users)
 	if err != nil {
 		return nil, nil, err
@@ -1984,9 +2045,11 @@ func (s *RepositoriesService) AddUserRestrictions(ctx context.Context, owner, re
 //
 // Note: The list of users, apps, and teams in total is limited to 100 items.
 //
+// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape .
+//
 // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-team-access-restrictions
 func (s *RepositoriesService) RemoveUserRestrictions(ctx context.Context, owner, repo, branch string, users []string) ([]*User, *Response, error) {
-	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, branch)
+	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/users", owner, repo, url.PathEscape(branch))
 	req, err := s.client.NewRequest("DELETE", u, users)
 	if err != nil {
 		return nil, nil, err


Test patch:
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index bdb4209a..c3e02988 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -4519,6 +4519,13 @@ func TestCommitCommentEvent_GetInstallation(tt *testing.T) {
 	c.GetInstallation()
 }
 
+func TestCommitCommentEvent_GetOrg(tt *testing.T) {
+	c := &CommitCommentEvent{}
+	c.GetOrg()
+	c = nil
+	c.GetOrg()
+}
+
 func TestCommitCommentEvent_GetRepo(tt *testing.T) {
 	c := &CommitCommentEvent{}
 	c.GetRepo()
@@ -5969,6 +5976,13 @@ func TestDeleteEvent_GetInstallation(tt *testing.T) {
 	d.GetInstallation()
 }
 
+func TestDeleteEvent_GetOrg(tt *testing.T) {
+	d := &DeleteEvent{}
+	d.GetOrg()
+	d = nil
+	d.GetOrg()
+}
+
 func TestDeleteEvent_GetPusherType(tt *testing.T) {
 	var zeroValue string
 	d := &DeleteEvent{PusherType: &zeroValue}
@@ -6570,6 +6584,13 @@ func TestDeploymentEvent_GetInstallation(tt *testing.T) {
 	d.GetInstallation()
 }
 
+func TestDeploymentEvent_GetOrg(tt *testing.T) {
+	d := &DeploymentEvent{}
+	d.GetOrg()
+	d = nil
+	d.GetOrg()
+}
+
 func TestDeploymentEvent_GetRepo(tt *testing.T) {
 	d := &DeploymentEvent{}
 	d.GetRepo()
@@ -6911,6 +6932,13 @@ func TestDeploymentStatusEvent_GetInstallation(tt *testing.T) {
 	d.GetInstallation()
 }
 
+func TestDeploymentStatusEvent_GetOrg(tt *testing.T) {
+	d := &DeploymentStatusEvent{}
+	d.GetOrg()
+	d = nil
+	d.GetOrg()
+}
+
 func TestDeploymentStatusEvent_GetRepo(tt *testing.T) {
 	d := &DeploymentStatusEvent{}
 	d.GetRepo()
@@ -9011,6 +9039,13 @@ func TestGollumEvent_GetInstallation(tt *testing.T) {
 	g.GetInstallation()
 }
 
+func TestGollumEvent_GetOrg(tt *testing.T) {
+	g := &GollumEvent{}
+	g.GetOrg()
+	g = nil
+	g.GetOrg()
+}
+
 func TestGollumEvent_GetRepo(tt *testing.T) {
 	g := &GollumEvent{}
 	g.GetRepo()
@@ -10059,6 +10094,13 @@ func TestInstallationEvent_GetInstallation(tt *testing.T) {
 	i.GetInstallation()
 }
 
+func TestInstallationEvent_GetOrg(tt *testing.T) {
+	i := &InstallationEvent{}
+	i.GetOrg()
+	i = nil
+	i.GetOrg()
+}
+
 func TestInstallationEvent_GetRequester(tt *testing.T) {
 	i := &InstallationEvent{}
 	i.GetRequester()
@@ -10470,6 +10512,13 @@ func TestInstallationRepositoriesEvent_GetInstallation(tt *testing.T) {
 	i.GetInstallation()
 }
 
+func TestInstallationRepositoriesEvent_GetOrg(tt *testing.T) {
+	i := &InstallationRepositoriesEvent{}
+	i.GetOrg()
+	i = nil
+	i.GetOrg()
+}
+
 func TestInstallationRepositoriesEvent_GetRepositorySelection(tt *testing.T) {
 	var zeroValue string
 	i := &InstallationRepositoriesEvent{RepositorySelection: &zeroValue}
@@ -11706,6 +11755,13 @@ func TestIssuesEvent_GetMilestone(tt *testing.T) {
 	i.GetMilestone()
 }
 
+func TestIssuesEvent_GetOrg(tt *testing.T) {
+	i := &IssuesEvent{}
+	i.GetOrg()
+	i = nil
+	i.GetOrg()
+}
+
 func TestIssuesEvent_GetRepo(tt *testing.T) {
 	i := &IssuesEvent{}
 	i.GetRepo()
@@ -12965,6 +13021,13 @@ func TestMarketplacePurchaseEvent_GetMarketplacePurchase(tt *testing.T) {
 	m.GetMarketplacePurchase()
 }
 
+func TestMarketplacePurchaseEvent_GetOrg(tt *testing.T) {
+	m := &MarketplacePurchaseEvent{}
+	m.GetOrg()
+	m = nil
+	m.GetOrg()
+}
+
 func TestMarketplacePurchaseEvent_GetPreviousMarketplacePurchase(tt *testing.T) {
 	m := &MarketplacePurchaseEvent{}
 	m.GetPreviousMarketplacePurchase()
@@ -13013,6 +13076,13 @@ func TestMemberEvent_GetMember(tt *testing.T) {
 	m.GetMember()
 }
 
+func TestMemberEvent_GetOrg(tt *testing.T) {
+	m := &MemberEvent{}
+	m.GetOrg()
+	m = nil
+	m.GetOrg()
+}
+
 func TestMemberEvent_GetRepo(tt *testing.T) {
 	m := &MemberEvent{}
 	m.GetRepo()
@@ -15620,6 +15690,13 @@ func TestPageBuildEvent_GetInstallation(tt *testing.T) {
 	p.GetInstallation()
 }
 
+func TestPageBuildEvent_GetOrg(tt *testing.T) {
+	p := &PageBuildEvent{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
 func TestPageBuildEvent_GetRepo(tt *testing.T) {
 	p := &PageBuildEvent{}
 	p.GetRepo()
@@ -16263,6 +16340,13 @@ func TestPersonalAccessTokenRequest_GetID(tt *testing.T) {
 	p.GetID()
 }
 
+func TestPersonalAccessTokenRequest_GetOrg(tt *testing.T) {
+	p := &PersonalAccessTokenRequest{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
 func TestPersonalAccessTokenRequest_GetOwner(tt *testing.T) {
 	p := &PersonalAccessTokenRequest{}
 	p.GetOwner()
@@ -17980,6 +18064,13 @@ func TestPublicEvent_GetInstallation(tt *testing.T) {
 	p.GetInstallation()
 }
 
+func TestPublicEvent_GetOrg(tt *testing.T) {
+	p := &PublicEvent{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
 func TestPublicEvent_GetRepo(tt *testing.T) {
 	p := &PublicEvent{}
 	p.GetRepo()
@@ -19110,6 +19201,13 @@ func TestPullRequestReviewCommentEvent_GetInstallation(tt *testing.T) {
 	p.GetInstallation()
 }
 
+func TestPullRequestReviewCommentEvent_GetOrg(tt *testing.T) {
+	p := &PullRequestReviewCommentEvent{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
 func TestPullRequestReviewCommentEvent_GetPullRequest(tt *testing.T) {
 	p := &PullRequestReviewCommentEvent{}
 	p.GetPullRequest()
@@ -19342,6 +19440,13 @@ func TestPullRequestReviewThreadEvent_GetInstallation(tt *testing.T) {
 	p.GetInstallation()
 }
 
+func TestPullRequestReviewThreadEvent_GetOrg(tt *testing.T) {
+	p := &PullRequestReviewThreadEvent{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
 func TestPullRequestReviewThreadEvent_GetPullRequest(tt *testing.T) {
 	p := &PullRequestReviewThreadEvent{}
 	p.GetPullRequest()
@@ -20530,6 +20635,13 @@ func TestReleaseEvent_GetInstallation(tt *testing.T) {
 	r.GetInstallation()
 }
 
+func TestReleaseEvent_GetOrg(tt *testing.T) {
+	r := &ReleaseEvent{}
+	r.GetOrg()
+	r = nil
+	r.GetOrg()
+}
+
 func TestReleaseEvent_GetRelease(tt *testing.T) {
 	r := &ReleaseEvent{}
 	r.GetRelease()
@@ -23011,6 +23123,13 @@ func TestRepositoryVulnerabilityAlertEvent_GetInstallation(tt *testing.T) {
 	r.GetInstallation()
 }
 
+func TestRepositoryVulnerabilityAlertEvent_GetOrg(tt *testing.T) {
+	r := &RepositoryVulnerabilityAlertEvent{}
+	r.GetOrg()
+	r = nil
+	r.GetOrg()
+}
+
 func TestRepositoryVulnerabilityAlertEvent_GetRepository(tt *testing.T) {
 	r := &RepositoryVulnerabilityAlertEvent{}
 	r.GetRepository()
@@ -25165,6 +25284,13 @@ func TestStatusEvent_GetName(tt *testing.T) {
 	s.GetName()
 }
 
+func TestStatusEvent_GetOrg(tt *testing.T) {
+	s := &StatusEvent{}
+	s.GetOrg()
+	s = nil
+	s.GetOrg()
+}
+
 func TestStatusEvent_GetRepo(tt *testing.T) {
 	s := &StatusEvent{}
 	s.GetRepo()
@@ -27925,6 +28051,13 @@ func TestWatchEvent_GetInstallation(tt *testing.T) {
 	w.GetInstallation()
 }
 
+func TestWatchEvent_GetOrg(tt *testing.T) {
+	w := &WatchEvent{}
+	w.GetOrg()
+	w = nil
+	w.GetOrg()
+}
+
 func TestWatchEvent_GetRepo(tt *testing.T) {
 	w := &WatchEvent{}
 	w.GetRepo()
diff --git a/github/repos_test.go b/github/repos_test.go
index 6aba962a..7486e488 100644
--- a/github/repos_test.go
+++ b/github/repos_test.go
@@ -919,51 +919,73 @@ func TestRepositoriesService_GetBranch(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`)
-	})
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%"},
+	}
+
+	for _, test := range tests {
+		mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+			testMethod(t, r, "GET")
+			fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`)
+		})
 
-	ctx := context.Background()
-	branch, _, err := client.Repositories.GetBranch(ctx, "o", "r", "b", 0)
-	if err != nil {
-		t.Errorf("Repositories.GetBranch returned error: %v", err)
-	}
+		ctx := context.Background()
+		branch, _, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 0)
+		if err != nil {
+			t.Errorf("Repositories.GetBranch returned error: %v", err)
+		}
 
-	want := &Branch{
-		Name: String("n"),
-		Commit: &RepositoryCommit{
-			SHA: String("s"),
-			Commit: &Commit{
-				Message: String("m"),
+		want := &Branch{
+			Name: String("n"),
+			Commit: &RepositoryCommit{
+				SHA: String("s"),
+				Commit: &Commit{
+					Message: String("m"),
+				},
 			},
-		},
-		Protected: Bool(true),
-	}
+			Protected: Bool(true),
+		}
 
-	if !cmp.Equal(branch, want) {
-		t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)
-	}
+		if !cmp.Equal(branch, want) {
+			t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)
+		}
 
-	const methodName = "GetBranch"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 0)
-		return err
-	})
+		const methodName = "GetBranch"
+		testBadOptions(t, methodName, func() (err error) {
+			_, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 0)
+			return err
+		})
+	}
 }
 
 func TestRepositoriesService_GetBranch_BadJSONResponse(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprint(w, `{"name":"n", "commit":{"sha":...truncated`)
-	})
-
-	ctx := context.Background()
-	if _, _, err := client.Repositories.GetBranch(ctx, "o", "r", "b", 0); err == nil {
-		t.Error("Repositories.GetBranch returned no error; wanted JSON error")
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				fmt.Fprint(w, `{"name":"n", "commit":{"sha":...truncated`)
+			})
+
+			ctx := context.Background()
+			if _, _, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 0); err == nil {
+				t.Error("Repositories.GetBranch returned no error; wanted JSON error")
+			}
+		})
 	}
 }
 
@@ -1005,492 +1027,1013 @@ func TestRepositoriesService_GetBranch_StatusMovedPermanently_followRedirects(t
 }
 
 func TestRepositoriesService_GetBranch_notFound(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat-branch-50%"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				http.Error(w, "branch not found", http.StatusNotFound)
+			})
+			ctx := context.Background()
+			_, resp, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 1)
+			if err == nil {
+				t.Error("Repositories.GetBranch returned error: nil")
+			}
+			if resp.StatusCode != http.StatusNotFound {
+				t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusNotFound)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		http.Error(w, "branch not found", http.StatusNotFound)
-	})
-	ctx := context.Background()
-	_, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b", 1)
-	if err == nil {
-		t.Error("Repositories.GetBranch returned error: nil")
+			// Add custom round tripper
+			client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) {
+				return nil, errors.New("failed to get branch")
+			})
+
+			const methodName = "GetBranch"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 1)
+				return err
+			})
+		})
 	}
-	if resp.StatusCode != http.StatusNotFound {
-		t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusNotFound)
+}
+
+func TestRepositoriesService_RenameBranch(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/rename"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/rename"},
 	}
 
-	// Add custom round tripper
-	client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) {
-		return nil, errors.New("failed to get branch")
-	})
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
 
-	const methodName = "GetBranch"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 1)
-		return err
-	})
-}
+			renameBranchReq := "nn"
 
-func TestRepositoriesService_RenameBranch(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(renameBranchRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
 
-	renameBranchReq := "nn"
+				testMethod(t, r, "POST")
+				want := &renameBranchRequest{NewName: renameBranchReq}
+				if !cmp.Equal(v, want) {
+					t.Errorf("Request body = %+v, want %+v", v, want)
+				}
 
-	mux.HandleFunc("/repos/o/r/branches/b/rename", func(w http.ResponseWriter, r *http.Request) {
-		v := new(renameBranchRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+				fmt.Fprint(w, `{"protected":true,"name":"nn"}`)
+			})
 
-		testMethod(t, r, "POST")
-		want := &renameBranchRequest{NewName: "nn"}
-		if !cmp.Equal(v, want) {
-			t.Errorf("Request body = %+v, want %+v", v, want)
-		}
+			ctx := context.Background()
+			got, _, err := client.Repositories.RenameBranch(ctx, "o", "r", test.branch, renameBranchReq)
+			if err != nil {
+				t.Errorf("Repositories.RenameBranch returned error: %v", err)
+			}
 
-		fmt.Fprint(w, `{"protected":true,"name":"nn"}`)
-	})
+			want := &Branch{Name: String("nn"), Protected: Bool(true)}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.RenameBranch returned %+v, want %+v", got, want)
+			}
 
-	ctx := context.Background()
-	got, _, err := client.Repositories.RenameBranch(ctx, "o", "r", "b", renameBranchReq)
-	if err != nil {
-		t.Errorf("Repositories.RenameBranch returned error: %v", err)
-	}
+			const methodName = "RenameBranch"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.RenameBranch(ctx, "\n", "\n", "\n", renameBranchReq)
+				return err
+			})
 
-	want := &Branch{Name: String("nn"), Protected: Bool(true)}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.RenameBranch returned %+v, want %+v", got, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.RenameBranch(ctx, "o", "r", test.branch, renameBranchReq)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "RenameBranch"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.RenameBranch(ctx, "\n", "\n", "\n", renameBranchReq)
-		return err
-	})
+func TestRepositoriesService_GetBranchProtection(t *testing.T) {
+	tests := []struct {
+		branch               string
+		urlPath              string
+		enforceAdminsURLPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection", enforceAdminsURLPath: "/repos/o/r/branches/b/protection/enforce_admins"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection", enforceAdminsURLPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				fmt.Fprintf(w, `{
+						"required_status_checks":{
+							"strict":true,
+							"contexts":["continuous-integration"],
+							"checks": [
+								{
+									"context": "continuous-integration",
+									"app_id": null
+								}
+							]
+						},
+						"required_pull_request_reviews":{
+							"dismissal_restrictions":{
+								"users":[{
+									"id":3,
+									"login":"u"
+								}],
+								"teams":[{
+									"id":4,
+									"slug":"t"
+								}],
+								"apps":[{
+									"id":5,
+									"slug":"a"
+								}]
+							},
+							"dismiss_stale_reviews":true,
+							"require_code_owner_reviews":true,
+							"require_last_push_approval":false,
+							"required_approving_review_count":1
+							},
+							"enforce_admins":{
+								"url":"%s",
+								"enabled":true
+							},
+							"restrictions":{
+								"users":[{"id":1,"login":"u"}],
+								"teams":[{"id":2,"slug":"t"}],
+								"apps":[{"id":3,"slug":"a"}]
+							},
+							"required_conversation_resolution": {
+								"enabled": true
+							},
+							"block_creations": {
+								"enabled": false
+							},
+							"lock_branch": {
+								"enabled": false
+							},
+							"allow_fork_syncing": {
+								"enabled": false
+							}
+						}`, test.enforceAdminsURLPath)
+			})
+
+			ctx := context.Background()
+			protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.RenameBranch(ctx, "o", "r", "b", renameBranchReq)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			want := &Protection{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict:   true,
+					Contexts: []string{"continuous-integration"},
+					Checks: []*RequiredStatusCheck{
+						{
+							Context: "continuous-integration",
+						},
+					},
+				},
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+					DismissStaleReviews: true,
+					DismissalRestrictions: &DismissalRestrictions{
+						Users: []*User{
+							{Login: String("u"), ID: Int64(3)},
+						},
+						Teams: []*Team{
+							{Slug: String("t"), ID: Int64(4)},
+						},
+						Apps: []*App{
+							{Slug: String("a"), ID: Int64(5)},
+						},
+					},
+					RequireCodeOwnerReviews:      true,
+					RequiredApprovingReviewCount: 1,
+					RequireLastPushApproval:      false,
+				},
+				EnforceAdmins: &AdminEnforcement{
+					URL:     String(test.enforceAdminsURLPath),
+					Enabled: true,
+				},
+				Restrictions: &BranchRestrictions{
+					Users: []*User{
+						{Login: String("u"), ID: Int64(1)},
+					},
+					Teams: []*Team{
+						{Slug: String("t"), ID: Int64(2)},
+					},
+					Apps: []*App{
+						{Slug: String("a"), ID: Int64(3)},
+					},
+				},
+				RequiredConversationResolution: &RequiredConversationResolution{
+					Enabled: true,
+				},
+				BlockCreations: &BlockCreations{
+					Enabled: Bool(false),
+				},
+				LockBranch: &LockBranch{
+					Enabled: Bool(false),
+				},
+				AllowForkSyncing: &AllowForkSyncing{
+					Enabled: Bool(false),
+				},
+			}
+			if !cmp.Equal(protection, want) {
+				t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
+			}
+
+			const methodName = "GetBranchProtection"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.GetBranchProtection(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
 }
 
-func TestRepositoriesService_GetBranchProtection(t *testing.T) {
+func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-				"required_status_checks":{
-					"strict":true,
-					"contexts":["continuous-integration"],
-					"checks": [
-						{
-							"context": "continuous-integration",
-							"app_id": null
+	tests := []struct {
+		branch               string
+		urlPath              string
+		enforceAdminsURLPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection", enforceAdminsURLPath: "/repos/o/r/branches/b/protection/enforce_admins"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection", enforceAdminsURLPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
+	}
+
+	for _, test := range tests {
+		mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+			testMethod(t, r, "GET")
+			// TODO: remove custom Accept header when this API fully launches
+			testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+			fmt.Fprintf(w, `{
+					"required_status_checks":{
+						"strict":true,
+						"contexts":["continuous-integration"],
+						"checks": [
+							{
+								"context": "continuous-integration",
+								"app_id": null
+							}
+						]
+					},
+					"required_pull_request_reviews":{
+						"dismiss_stale_reviews":true,
+						"require_code_owner_reviews":true,
+						"required_approving_review_count":1
+						},
+						"enforce_admins":{
+							"url":"%s",
+							"enabled":true
+						},
+						"restrictions":{
+							"users":[{"id":1,"login":"u"}],
+							"teams":[{"id":2,"slug":"t"}]
 						}
-					]
+					}`, test.enforceAdminsURLPath)
+		})
+
+		ctx := context.Background()
+		protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
+		if err != nil {
+			t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
+		}
+
+		want := &Protection{
+			RequiredStatusChecks: &RequiredStatusChecks{
+				Strict:   true,
+				Contexts: []string{"continuous-integration"},
+				Checks: []*RequiredStatusCheck{
+					{
+						Context: "continuous-integration",
+					},
 				},
-				"required_pull_request_reviews":{
-					"dismissal_restrictions":{
-						"users":[{
-							"id":3,
-							"login":"u"
-						}],
-						"teams":[{
-							"id":4,
-							"slug":"t"
-						}],
-						"apps":[{
-							"id":5,
-							"slug":"a"
-						}]
+			},
+			RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+				DismissStaleReviews:          true,
+				DismissalRestrictions:        nil,
+				RequireCodeOwnerReviews:      true,
+				RequiredApprovingReviewCount: 1,
+			},
+			EnforceAdmins: &AdminEnforcement{
+				URL:     String(test.enforceAdminsURLPath),
+				Enabled: true,
+			},
+			Restrictions: &BranchRestrictions{
+				Users: []*User{
+					{Login: String("u"), ID: Int64(1)},
+				},
+				Teams: []*Team{
+					{Slug: String("t"), ID: Int64(2)},
+				},
+			},
+		}
+		if !cmp.Equal(protection, want) {
+			t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
+		}
+	}
+}
+
+func TestRepositoriesService_GetBranchProtection_branchNotProtected(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+
+				w.WriteHeader(http.StatusBadRequest)
+				fmt.Fprintf(w, `{
+					"message": %q,
+					"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
+					}`, githubBranchNotProtected)
+			})
+
+			ctx := context.Background()
+			protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
+
+			if protection != nil {
+				t.Errorf("Repositories.GetBranchProtection returned non-nil protection data")
+			}
+
+			if err != ErrBranchNotProtected {
+				t.Errorf("Repositories.GetBranchProtection returned an invalid error: %v", err)
+			}
+		})
+	}
+}
+
+func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			input := &ProtectionRequest{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict:   true,
+					Contexts: []string{"continuous-integration"},
+				},
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
+					DismissStaleReviews: true,
+					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+						Users: &[]string{"uu"},
+						Teams: &[]string{"tt"},
+						Apps:  &[]string{"aa"},
 					},
-					"dismiss_stale_reviews":true,
-					"require_code_owner_reviews":true,
-					"require_last_push_approval":false,
-					"required_approving_review_count":1
+					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
+						Users: []string{"uuu"},
+						Teams: []string{"ttt"},
+						Apps:  []string{"aaa"},
+					},
+				},
+				Restrictions: &BranchRestrictionsRequest{
+					Users: []string{"u"},
+					Teams: []string{"t"},
+					Apps:  []string{"a"},
+				},
+				BlockCreations:   Bool(true),
+				LockBranch:       Bool(true),
+				AllowForkSyncing: Bool(true),
+			}
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(ProtectionRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+
+				testMethod(t, r, "PUT")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
+				}
+
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				fmt.Fprintf(w, `{
+					"required_status_checks":{
+						"strict":true,
+						"contexts":["continuous-integration"],
+						"checks": [
+							{
+								"context": "continuous-integration",
+								"app_id": null
+							}
+						]
 					},
-					"enforce_admins":{
-						"url":"/repos/o/r/branches/b/protection/enforce_admins",
-						"enabled":true
+					"required_pull_request_reviews":{
+						"dismissal_restrictions":{
+							"users":[{
+								"id":3,
+								"login":"uu"
+							}],
+							"teams":[{
+								"id":4,
+								"slug":"tt"
+							}],
+							"apps":[{
+								"id":5,
+								"slug":"aa"
+							}]
+						},
+						"dismiss_stale_reviews":true,
+						"require_code_owner_reviews":true,
+						"bypass_pull_request_allowances": {
+							"users":[{"id":10,"login":"uuu"}],
+							"teams":[{"id":20,"slug":"ttt"}],
+							"apps":[{"id":30,"slug":"aaa"}]
+						}
 					},
 					"restrictions":{
 						"users":[{"id":1,"login":"u"}],
 						"teams":[{"id":2,"slug":"t"}],
 						"apps":[{"id":3,"slug":"a"}]
 					},
-					"required_conversation_resolution": {
-						"enabled": true
-					},
 					"block_creations": {
-						"enabled": false
+						"enabled": true
 					},
 					"lock_branch": {
-						"enabled": false
+						"enabled": true
 					},
 					"allow_fork_syncing": {
-						"enabled": false
+						"enabled": true
 					}
 				}`)
-	})
+			})
 
-	ctx := context.Background()
-	protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
-	}
+			ctx := context.Background()
+			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+			}
 
-	want := &Protection{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict:   true,
-			Contexts: []string{"continuous-integration"},
-			Checks: []*RequiredStatusCheck{
-				{
-					Context: "continuous-integration",
+			want := &Protection{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict:   true,
+					Contexts: []string{"continuous-integration"},
+					Checks: []*RequiredStatusCheck{
+						{
+							Context: "continuous-integration",
+						},
+					},
 				},
-			},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
-			DismissStaleReviews: true,
-			DismissalRestrictions: &DismissalRestrictions{
-				Users: []*User{
-					{Login: String("u"), ID: Int64(3)},
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+					DismissStaleReviews: true,
+					DismissalRestrictions: &DismissalRestrictions{
+						Users: []*User{
+							{Login: String("uu"), ID: Int64(3)},
+						},
+						Teams: []*Team{
+							{Slug: String("tt"), ID: Int64(4)},
+						},
+						Apps: []*App{
+							{Slug: String("aa"), ID: Int64(5)},
+						},
+					},
+					RequireCodeOwnerReviews: true,
+					BypassPullRequestAllowances: &BypassPullRequestAllowances{
+						Users: []*User{
+							{Login: String("uuu"), ID: Int64(10)},
+						},
+						Teams: []*Team{
+							{Slug: String("ttt"), ID: Int64(20)},
+						},
+						Apps: []*App{
+							{Slug: String("aaa"), ID: Int64(30)},
+						},
+					},
 				},
-				Teams: []*Team{
-					{Slug: String("t"), ID: Int64(4)},
+				Restrictions: &BranchRestrictions{
+					Users: []*User{
+						{Login: String("u"), ID: Int64(1)},
+					},
+					Teams: []*Team{
+						{Slug: String("t"), ID: Int64(2)},
+					},
+					Apps: []*App{
+						{Slug: String("a"), ID: Int64(3)},
+					},
 				},
-				Apps: []*App{
-					{Slug: String("a"), ID: Int64(5)},
+				BlockCreations: &BlockCreations{
+					Enabled: Bool(true),
 				},
-			},
-			RequireCodeOwnerReviews:      true,
-			RequiredApprovingReviewCount: 1,
-			RequireLastPushApproval:      false,
-		},
-		EnforceAdmins: &AdminEnforcement{
-			URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
-			Enabled: true,
-		},
-		Restrictions: &BranchRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-			Apps: []*App{
-				{Slug: String("a"), ID: Int64(3)},
-			},
-		},
-		RequiredConversationResolution: &RequiredConversationResolution{
-			Enabled: true,
-		},
-		BlockCreations: &BlockCreations{
-			Enabled: Bool(false),
-		},
-		LockBranch: &LockBranch{
-			Enabled: Bool(false),
-		},
-		AllowForkSyncing: &AllowForkSyncing{
-			Enabled: Bool(false),
-		},
-	}
-	if !cmp.Equal(protection, want) {
-		t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
-	}
+				LockBranch: &LockBranch{
+					Enabled: Bool(true),
+				},
+				AllowForkSyncing: &AllowForkSyncing{
+					Enabled: Bool(true),
+				},
+			}
+			if !cmp.Equal(protection, want) {
+				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			}
 
-	const methodName = "GetBranchProtection"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetBranchProtection(ctx, "\n", "\n", "\n")
-		return err
-	})
+			const methodName = "UpdateBranchProtection"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.UpdateBranchProtection(ctx, "\n", "\n", "\n", input)
+				return err
+			})
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.GetBranchProtection(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
 }
 
-func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-				"required_status_checks":{
-					"strict":true,
-					"contexts":["continuous-integration"],
-					"checks": [
+func TestRepositoriesService_UpdateBranchProtection_Checks(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			input := &ProtectionRequest{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict: true,
+					Checks: []*RequiredStatusCheck{
 						{
-							"context": "continuous-integration",
-							"app_id": null
-						}
-					]
+							Context: "continuous-integration",
+						},
+					},
 				},
-				"required_pull_request_reviews":{
-					"dismiss_stale_reviews":true,
-					"require_code_owner_reviews":true,
-					"required_approving_review_count":1
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
+					DismissStaleReviews: true,
+					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+						Users: &[]string{"uu"},
+						Teams: &[]string{"tt"},
+						Apps:  &[]string{"aa"},
+					},
+					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
+						Users: []string{"uuu"},
+						Teams: []string{"ttt"},
+						Apps:  []string{"aaa"},
+					},
+				},
+				Restrictions: &BranchRestrictionsRequest{
+					Users: []string{"u"},
+					Teams: []string{"t"},
+					Apps:  []string{"a"},
+				},
+			}
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(ProtectionRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+
+				testMethod(t, r, "PUT")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
+				}
+
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				fmt.Fprintf(w, `{
+					"required_status_checks":{
+						"strict":true,
+						"contexts":["continuous-integration"],
+						"checks": [
+							{
+								"context": "continuous-integration",
+								"app_id": null
+							}
+						]
 					},
-					"enforce_admins":{
-						"url":"/repos/o/r/branches/b/protection/enforce_admins",
-						"enabled":true
+					"required_pull_request_reviews":{
+						"dismissal_restrictions":{
+							"users":[{
+								"id":3,
+								"login":"uu"
+							}],
+							"teams":[{
+								"id":4,
+								"slug":"tt"
+							}],
+							"apps":[{
+								"id":5,
+								"slug":"aa"
+							}]
+						},
+						"dismiss_stale_reviews":true,
+						"require_code_owner_reviews":true,
+						"bypass_pull_request_allowances": {
+							"users":[{"id":10,"login":"uuu"}],
+							"teams":[{"id":20,"slug":"ttt"}],
+							"apps":[{"id":30,"slug":"aaa"}]
+						}
 					},
 					"restrictions":{
 						"users":[{"id":1,"login":"u"}],
-						"teams":[{"id":2,"slug":"t"}]
+						"teams":[{"id":2,"slug":"t"}],
+						"apps":[{"id":3,"slug":"a"}]
 					}
 				}`)
-	})
+			})
 
-	ctx := context.Background()
-	protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
-	}
+			ctx := context.Background()
+			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+			}
 
-	want := &Protection{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict:   true,
-			Contexts: []string{"continuous-integration"},
-			Checks: []*RequiredStatusCheck{
-				{
-					Context: "continuous-integration",
+			want := &Protection{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict:   true,
+					Contexts: []string{"continuous-integration"},
+					Checks: []*RequiredStatusCheck{
+						{
+							Context: "continuous-integration",
+						},
+					},
 				},
-			},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
-			DismissStaleReviews:          true,
-			DismissalRestrictions:        nil,
-			RequireCodeOwnerReviews:      true,
-			RequiredApprovingReviewCount: 1,
-		},
-		EnforceAdmins: &AdminEnforcement{
-			URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
-			Enabled: true,
-		},
-		Restrictions: &BranchRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-		},
-	}
-	if !cmp.Equal(protection, want) {
-		t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+					DismissStaleReviews: true,
+					DismissalRestrictions: &DismissalRestrictions{
+						Users: []*User{
+							{Login: String("uu"), ID: Int64(3)},
+						},
+						Teams: []*Team{
+							{Slug: String("tt"), ID: Int64(4)},
+						},
+						Apps: []*App{
+							{Slug: String("aa"), ID: Int64(5)},
+						},
+					},
+					RequireCodeOwnerReviews: true,
+					BypassPullRequestAllowances: &BypassPullRequestAllowances{
+						Users: []*User{
+							{Login: String("uuu"), ID: Int64(10)},
+						},
+						Teams: []*Team{
+							{Slug: String("ttt"), ID: Int64(20)},
+						},
+						Apps: []*App{
+							{Slug: String("aaa"), ID: Int64(30)},
+						},
+					},
+				},
+				Restrictions: &BranchRestrictions{
+					Users: []*User{
+						{Login: String("u"), ID: Int64(1)},
+					},
+					Teams: []*Team{
+						{Slug: String("t"), ID: Int64(2)},
+					},
+					Apps: []*App{
+						{Slug: String("a"), ID: Int64(3)},
+					},
+				},
+			}
+			if !cmp.Equal(protection, want) {
+				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			}
+		})
 	}
 }
 
-func TestRepositoriesService_GetBranchProtection_branchNotProtected(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_UpdateBranchProtection_StrictNoChecks(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			input := &ProtectionRequest{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict: true,
+					Checks: []*RequiredStatusCheck{},
+				},
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
+					DismissStaleReviews: true,
+					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+						Users: &[]string{"uu"},
+						Teams: &[]string{"tt"},
+						Apps:  &[]string{"aa"},
+					},
+					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
+						Users: []string{"uuu"},
+						Teams: []string{"ttt"},
+						Apps:  []string{"aaa"},
+					},
+				},
+				Restrictions: &BranchRestrictionsRequest{
+					Users: []string{"u"},
+					Teams: []string{"t"},
+					Apps:  []string{"a"},
+				},
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(ProtectionRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
 
-		w.WriteHeader(http.StatusBadRequest)
-		fmt.Fprintf(w, `{
-			"message": %q,
-			"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
-			}`, githubBranchNotProtected)
-	})
+				testMethod(t, r, "PUT")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
+				}
 
-	ctx := context.Background()
-	protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", "b")
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				fmt.Fprintf(w, `{
+					"required_status_checks":{
+						"strict":true,
+						"contexts":[],
+						"checks": []
+					},
+					"required_pull_request_reviews":{
+						"dismissal_restrictions":{
+							"users":[{
+								"id":3,
+								"login":"uu"
+							}],
+							"teams":[{
+								"id":4,
+								"slug":"tt"
+							}],
+							"apps":[{
+								"id":5,
+								"slug":"aa"
+							}]
+						},
+						"dismiss_stale_reviews":true,
+						"require_code_owner_reviews":true,
+						"require_last_push_approval":false,
+						"bypass_pull_request_allowances": {
+							"users":[{"id":10,"login":"uuu"}],
+							"teams":[{"id":20,"slug":"ttt"}],
+							"apps":[{"id":30,"slug":"aaa"}]
+						}
+					},
+					"restrictions":{
+						"users":[{"id":1,"login":"u"}],
+						"teams":[{"id":2,"slug":"t"}],
+						"apps":[{"id":3,"slug":"a"}]
+					}
+				}`)
+			})
 
-	if protection != nil {
-		t.Errorf("Repositories.GetBranchProtection returned non-nil protection data")
-	}
+			ctx := context.Background()
+			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+			}
 
-	if err != ErrBranchNotProtected {
-		t.Errorf("Repositories.GetBranchProtection returned an invalid error: %v", err)
+			want := &Protection{
+				RequiredStatusChecks: &RequiredStatusChecks{
+					Strict:   true,
+					Contexts: []string{},
+					Checks:   []*RequiredStatusCheck{},
+				},
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+					DismissStaleReviews: true,
+					DismissalRestrictions: &DismissalRestrictions{
+						Users: []*User{
+							{Login: String("uu"), ID: Int64(3)},
+						},
+						Teams: []*Team{
+							{Slug: String("tt"), ID: Int64(4)},
+						},
+						Apps: []*App{
+							{Slug: String("aa"), ID: Int64(5)},
+						},
+					},
+					RequireCodeOwnerReviews: true,
+					BypassPullRequestAllowances: &BypassPullRequestAllowances{
+						Users: []*User{
+							{Login: String("uuu"), ID: Int64(10)},
+						},
+						Teams: []*Team{
+							{Slug: String("ttt"), ID: Int64(20)},
+						},
+						Apps: []*App{
+							{Slug: String("aaa"), ID: Int64(30)},
+						},
+					},
+				},
+				Restrictions: &BranchRestrictions{
+					Users: []*User{
+						{Login: String("u"), ID: Int64(1)},
+					},
+					Teams: []*Team{
+						{Slug: String("t"), ID: Int64(2)},
+					},
+					Apps: []*App{
+						{Slug: String("a"), ID: Int64(3)},
+					},
+				},
+			}
+			if !cmp.Equal(protection, want) {
+				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			}
+		})
 	}
 }
 
-func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	input := &ProtectionRequest{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict:   true,
-			Contexts: []string{"continuous-integration"},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
-			DismissStaleReviews: true,
-			DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
-				Users: &[]string{"uu"},
-				Teams: &[]string{"tt"},
-				Apps:  &[]string{"aa"},
-			},
-			BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
-				Users: []string{"uuu"},
-				Teams: []string{"ttt"},
-				Apps:  []string{"aaa"},
-			},
-		},
-		Restrictions: &BranchRestrictionsRequest{
-			Users: []string{"u"},
-			Teams: []string{"t"},
-			Apps:  []string{"a"},
-		},
-		BlockCreations:   Bool(true),
-		LockBranch:       Bool(true),
-		AllowForkSyncing: Bool(true),
-	}
+func TestRepositoriesService_UpdateBranchProtection_RequireLastPushApproval(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			input := &ProtectionRequest{
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
+					RequireLastPushApproval: Bool(true),
+				},
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		v := new(ProtectionRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(ProtectionRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
 
-		testMethod(t, r, "PUT")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
+				testMethod(t, r, "PUT")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
+				}
 
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-			"required_status_checks":{
-				"strict":true,
-				"contexts":["continuous-integration"],
-				"checks": [
-					{
-						"context": "continuous-integration",
-						"app_id": null
+				fmt.Fprintf(w, `{
+					"required_pull_request_reviews":{
+						"require_last_push_approval":true
 					}
-				]
-			},
-			"required_pull_request_reviews":{
-				"dismissal_restrictions":{
-					"users":[{
-						"id":3,
-						"login":"uu"
-					}],
-					"teams":[{
-						"id":4,
-						"slug":"tt"
-					}],
-					"apps":[{
-						"id":5,
-						"slug":"aa"
-					}]
+				}`)
+			})
+
+			ctx := context.Background()
+			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+			}
+
+			want := &Protection{
+				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+					RequireLastPushApproval: true,
 				},
-				"dismiss_stale_reviews":true,
-				"require_code_owner_reviews":true,
-				"bypass_pull_request_allowances": {
-					"users":[{"id":10,"login":"uuu"}],
-					"teams":[{"id":20,"slug":"ttt"}],
-					"apps":[{"id":30,"slug":"aaa"}]
-				}
-			},
-			"restrictions":{
-				"users":[{"id":1,"login":"u"}],
-				"teams":[{"id":2,"slug":"t"}],
-				"apps":[{"id":3,"slug":"a"}]
-			},
-			"block_creations": {
-				"enabled": true
-			},
-			"lock_branch": {
-				"enabled": true
-			},
-			"allow_fork_syncing": {
-				"enabled": true
 			}
-		}`)
+			if !cmp.Equal(protection, want) {
+				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			}
+		})
+	}
+}
+
+func TestRepositoriesService_RemoveBranchProtection(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				w.WriteHeader(http.StatusNoContent)
+			})
+
+			ctx := context.Background()
+			_, err := client.Repositories.RemoveBranchProtection(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err)
+			}
+
+			const methodName = "RemoveBranchProtection"
+			testBadOptions(t, methodName, func() (err error) {
+				_, err = client.Repositories.RemoveBranchProtection(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				return client.Repositories.RemoveBranchProtection(ctx, "o", "r", test.branch)
+			})
+		})
+	}
+}
+
+func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) {
+	client, _, _, teardown := setup()
+	defer teardown()
+
+	ctx := context.Background()
+	_, _, err := client.Repositories.ListLanguages(ctx, "%", "%")
+	testURLParseError(t, err)
+}
+
+func TestRepositoriesService_License(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{"name": "LICENSE", "path": "LICENSE", "license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}}`)
 	})
 
 	ctx := context.Background()
-	protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", "b", input)
+	got, _, err := client.Repositories.License(ctx, "o", "r")
 	if err != nil {
-		t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+		t.Errorf("Repositories.License returned error: %v", err)
 	}
 
-	want := &Protection{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict:   true,
-			Contexts: []string{"continuous-integration"},
-			Checks: []*RequiredStatusCheck{
-				{
-					Context: "continuous-integration",
-				},
-			},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
-			DismissStaleReviews: true,
-			DismissalRestrictions: &DismissalRestrictions{
-				Users: []*User{
-					{Login: String("uu"), ID: Int64(3)},
-				},
-				Teams: []*Team{
-					{Slug: String("tt"), ID: Int64(4)},
-				},
-				Apps: []*App{
-					{Slug: String("aa"), ID: Int64(5)},
-				},
-			},
-			RequireCodeOwnerReviews: true,
-			BypassPullRequestAllowances: &BypassPullRequestAllowances{
-				Users: []*User{
-					{Login: String("uuu"), ID: Int64(10)},
-				},
-				Teams: []*Team{
-					{Slug: String("ttt"), ID: Int64(20)},
-				},
-				Apps: []*App{
-					{Slug: String("aaa"), ID: Int64(30)},
-				},
-			},
-		},
-		Restrictions: &BranchRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-			Apps: []*App{
-				{Slug: String("a"), ID: Int64(3)},
-			},
-		},
-		BlockCreations: &BlockCreations{
-			Enabled: Bool(true),
-		},
-		LockBranch: &LockBranch{
-			Enabled: Bool(true),
-		},
-		AllowForkSyncing: &AllowForkSyncing{
-			Enabled: Bool(true),
+	want := &RepositoryLicense{
+		Name: String("LICENSE"),
+		Path: String("LICENSE"),
+		License: &License{
+			Name:     String("MIT License"),
+			Key:      String("mit"),
+			SPDXID:   String("MIT"),
+			URL:      String("https://api.github.com/licenses/mit"),
+			Featured: Bool(true),
 		},
 	}
-	if !cmp.Equal(protection, want) {
-		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+
+	if !cmp.Equal(got, want) {
+		t.Errorf("Repositories.License returned %+v, want %+v", got, want)
 	}
 
-	const methodName = "UpdateBranchProtection"
+	const methodName = "License"
 	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.UpdateBranchProtection(ctx, "\n", "\n", "\n", input)
+		_, _, err = client.Repositories.License(ctx, "\n", "\n")
 		return err
 	})
 
 	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", "b", input)
+		got, resp, err := client.Repositories.License(ctx, "o", "r")
 		if got != nil {
 			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
 		}
@@ -1498,1532 +2041,1025 @@ func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
 	})
 }
 
-func TestRepositoriesService_UpdateBranchProtection_Checks(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	input := &ProtectionRequest{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict: true,
-			Checks: []*RequiredStatusCheck{
-				{
-					Context: "continuous-integration",
-				},
-			},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
-			DismissStaleReviews: true,
-			DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
-				Users: &[]string{"uu"},
-				Teams: &[]string{"tt"},
-				Apps:  &[]string{"aa"},
-			},
-			BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
-				Users: []string{"uuu"},
-				Teams: []string{"ttt"},
-				Apps:  []string{"aaa"},
-			},
-		},
-		Restrictions: &BranchRestrictionsRequest{
-			Users: []string{"u"},
-			Teams: []string{"t"},
-			Apps:  []string{"a"},
-		},
-	}
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		v := new(ProtectionRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				fmt.Fprint(w, `{
+					"strict": true,
+					"contexts": ["x","y","z"],
+					"checks": [
+						{
+							"context": "x",
+							"app_id": null
+						},
+						{
+							"context": "y",
+							"app_id": null
+						},
+						{
+							"context": "z",
+							"app_id": null
+						}
+					]
+				}`)
+			})
 
-		testMethod(t, r, "PUT")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
+			ctx := context.Background()
+			checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err)
+			}
 
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-			"required_status_checks":{
-				"strict":true,
-				"contexts":["continuous-integration"],
-				"checks": [
+			want := &RequiredStatusChecks{
+				Strict:   true,
+				Contexts: []string{"x", "y", "z"},
+				Checks: []*RequiredStatusCheck{
 					{
-						"context": "continuous-integration",
-						"app_id": null
-					}
-				]
-			},
-			"required_pull_request_reviews":{
-				"dismissal_restrictions":{
-					"users":[{
-						"id":3,
-						"login":"uu"
-					}],
-					"teams":[{
-						"id":4,
-						"slug":"tt"
-					}],
-					"apps":[{
-						"id":5,
-						"slug":"aa"
-					}]
+						Context: "x",
+					},
+					{
+						Context: "y",
+					},
+					{
+						Context: "z",
+					},
 				},
-				"dismiss_stale_reviews":true,
-				"require_code_owner_reviews":true,
-				"bypass_pull_request_allowances": {
-					"users":[{"id":10,"login":"uuu"}],
-					"teams":[{"id":20,"slug":"ttt"}],
-					"apps":[{"id":30,"slug":"aaa"}]
-				}
-			},
-			"restrictions":{
-				"users":[{"id":1,"login":"u"}],
-				"teams":[{"id":2,"slug":"t"}],
-				"apps":[{"id":3,"slug":"a"}]
 			}
-		}`)
-	})
+			if !cmp.Equal(checks, want) {
+				t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want)
+			}
 
-	ctx := context.Background()
-	protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
-	}
+			const methodName = "GetRequiredStatusChecks"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.GetRequiredStatusChecks(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	want := &Protection{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict:   true,
-			Contexts: []string{"continuous-integration"},
-			Checks: []*RequiredStatusCheck{
-				{
-					Context: "continuous-integration",
-				},
-			},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
-			DismissStaleReviews: true,
-			DismissalRestrictions: &DismissalRestrictions{
-				Users: []*User{
-					{Login: String("uu"), ID: Int64(3)},
-				},
-				Teams: []*Team{
-					{Slug: String("tt"), ID: Int64(4)},
-				},
-				Apps: []*App{
-					{Slug: String("aa"), ID: Int64(5)},
-				},
-			},
-			RequireCodeOwnerReviews: true,
-			BypassPullRequestAllowances: &BypassPullRequestAllowances{
-				Users: []*User{
-					{Login: String("uuu"), ID: Int64(10)},
-				},
-				Teams: []*Team{
-					{Slug: String("ttt"), ID: Int64(20)},
-				},
-				Apps: []*App{
-					{Slug: String("aaa"), ID: Int64(30)},
-				},
-			},
-		},
-		Restrictions: &BranchRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-			Apps: []*App{
-				{Slug: String("a"), ID: Int64(3)},
-			},
-		},
-	}
-	if !cmp.Equal(protection, want) {
-		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
 }
 
-func TestRepositoriesService_UpdateBranchProtection_StrictNoChecks(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	input := &ProtectionRequest{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict: true,
-			Checks: []*RequiredStatusCheck{},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
-			DismissStaleReviews: true,
-			DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
-				Users: &[]string{"uu"},
-				Teams: &[]string{"tt"},
-				Apps:  &[]string{"aa"},
-			},
-			BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
-				Users: []string{"uuu"},
-				Teams: []string{"ttt"},
-				Apps:  []string{"aaa"},
-			},
-		},
-		Restrictions: &BranchRestrictionsRequest{
-			Users: []string{"u"},
-			Teams: []string{"t"},
-			Apps:  []string{"a"},
-		},
+func TestRepositoriesService_GetRequiredStatusChecks_branchNotProtected(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
 	}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		v := new(ProtectionRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
 
-		testMethod(t, r, "PUT")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
 
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-			"required_status_checks":{
-				"strict":true,
-				"contexts":[],
-				"checks": []
-			},
-			"required_pull_request_reviews":{
-				"dismissal_restrictions":{
-					"users":[{
-						"id":3,
-						"login":"uu"
-					}],
-					"teams":[{
-						"id":4,
-						"slug":"tt"
-					}],
-					"apps":[{
-						"id":5,
-						"slug":"aa"
-					}]
-				},
-				"dismiss_stale_reviews":true,
-				"require_code_owner_reviews":true,
-				"require_last_push_approval":false,
-				"bypass_pull_request_allowances": {
-					"users":[{"id":10,"login":"uuu"}],
-					"teams":[{"id":20,"slug":"ttt"}],
-					"apps":[{"id":30,"slug":"aaa"}]
-				}
-			},
-			"restrictions":{
-				"users":[{"id":1,"login":"u"}],
-				"teams":[{"id":2,"slug":"t"}],
-				"apps":[{"id":3,"slug":"a"}]
-			}
-		}`)
-	})
+				w.WriteHeader(http.StatusBadRequest)
+				fmt.Fprintf(w, `{
+			"message": %q,
+			"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
+			}`, githubBranchNotProtected)
+			})
 
-	ctx := context.Background()
-	protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
-	}
+			ctx := context.Background()
+			checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch)
 
-	want := &Protection{
-		RequiredStatusChecks: &RequiredStatusChecks{
-			Strict:   true,
-			Contexts: []string{},
-			Checks:   []*RequiredStatusCheck{},
-		},
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
-			DismissStaleReviews: true,
-			DismissalRestrictions: &DismissalRestrictions{
-				Users: []*User{
-					{Login: String("uu"), ID: Int64(3)},
-				},
-				Teams: []*Team{
-					{Slug: String("tt"), ID: Int64(4)},
-				},
-				Apps: []*App{
-					{Slug: String("aa"), ID: Int64(5)},
-				},
-			},
-			RequireCodeOwnerReviews: true,
-			BypassPullRequestAllowances: &BypassPullRequestAllowances{
-				Users: []*User{
-					{Login: String("uuu"), ID: Int64(10)},
-				},
-				Teams: []*Team{
-					{Slug: String("ttt"), ID: Int64(20)},
-				},
-				Apps: []*App{
-					{Slug: String("aaa"), ID: Int64(30)},
-				},
-			},
-		},
-		Restrictions: &BranchRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-			Apps: []*App{
-				{Slug: String("a"), ID: Int64(3)},
-			},
-		},
-	}
-	if !cmp.Equal(protection, want) {
-		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			if checks != nil {
+				t.Errorf("Repositories.GetRequiredStatusChecks returned non-nil status-checks data")
+			}
+
+			if err != ErrBranchNotProtected {
+				t.Errorf("Repositories.GetRequiredStatusChecks returned an invalid error: %v", err)
+			}
+		})
 	}
 }
 
-func TestRepositoriesService_UpdateBranchProtection_RequireLastPushApproval(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_UpdateRequiredStatusChecks_Contexts(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			input := &RequiredStatusChecksRequest{
+				Strict:   Bool(true),
+				Contexts: []string{"continuous-integration"},
+			}
 
-	input := &ProtectionRequest{
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
-			RequireLastPushApproval: Bool(true),
-		},
-	}
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(RequiredStatusChecksRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		v := new(ProtectionRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+				testMethod(t, r, "PATCH")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
+				}
+				testHeader(t, r, "Accept", mediaTypeV3)
+				fmt.Fprintf(w, `{
+					"strict":true,
+					"contexts":["continuous-integration"],
+					"checks": [
+						{
+							"context": "continuous-integration",
+							"app_id": null
+						}
+					]
+				}`)
+			})
 
-		testMethod(t, r, "PUT")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
+			ctx := context.Background()
+			statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
+			}
 
-		fmt.Fprintf(w, `{
-			"required_pull_request_reviews":{
-				"require_last_push_approval":true
+			want := &RequiredStatusChecks{
+				Strict:   true,
+				Contexts: []string{"continuous-integration"},
+				Checks: []*RequiredStatusCheck{
+					{
+						Context: "continuous-integration",
+					},
+				},
+			}
+			if !cmp.Equal(statusChecks, want) {
+				t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
 			}
-		}`)
-	})
 
-	ctx := context.Background()
-	protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
-	}
+			const methodName = "UpdateRequiredStatusChecks"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.UpdateRequiredStatusChecks(ctx, "\n", "\n", "\n", input)
+				return err
+			})
 
-	want := &Protection{
-		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
-			RequireLastPushApproval: true,
-		},
-	}
-	if !cmp.Equal(protection, want) {
-		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
 }
 
-func TestRepositoriesService_RemoveBranchProtection(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		w.WriteHeader(http.StatusNoContent)
-	})
-
-	ctx := context.Background()
-	_, err := client.Repositories.RemoveBranchProtection(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err)
-	}
+func TestRepositoriesService_UpdateRequiredStatusChecks_Checks(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			appID := int64(123)
+			noAppID := int64(-1)
+			input := &RequiredStatusChecksRequest{
+				Strict: Bool(true),
+				Checks: []*RequiredStatusCheck{
+					{
+						Context: "continuous-integration",
+					},
+					{
+						Context: "continuous-integration2",
+						AppID:   &appID,
+					},
+					{
+						Context: "continuous-integration3",
+						AppID:   &noAppID,
+					},
+				},
+			}
 
-	const methodName = "RemoveBranchProtection"
-	testBadOptions(t, methodName, func() (err error) {
-		_, err = client.Repositories.RemoveBranchProtection(ctx, "\n", "\n", "\n")
-		return err
-	})
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(RequiredStatusChecksRequest)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		return client.Repositories.RemoveBranchProtection(ctx, "o", "r", "b")
-	})
-}
+				testMethod(t, r, "PATCH")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
+				}
+				testHeader(t, r, "Accept", mediaTypeV3)
+				fmt.Fprintf(w, `{
+					"strict":true,
+					"contexts":["continuous-integration"],
+					"checks": [
+						{
+							"context": "continuous-integration",
+							"app_id": null
+						},
+						{
+							"context": "continuous-integration2",
+							"app_id": 123
+						},
+						{
+							"context": "continuous-integration3",
+							"app_id": null
+						}
+					]
+				}`)
+			})
 
-func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) {
-	client, _, _, teardown := setup()
-	defer teardown()
+			ctx := context.Background()
+			statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
+			}
 
-	ctx := context.Background()
-	_, _, err := client.Repositories.ListLanguages(ctx, "%", "%")
-	testURLParseError(t, err)
+			want := &RequiredStatusChecks{
+				Strict:   true,
+				Contexts: []string{"continuous-integration"},
+				Checks: []*RequiredStatusCheck{
+					{
+						Context: "continuous-integration",
+					},
+					{
+						Context: "continuous-integration2",
+						AppID:   &appID,
+					},
+					{
+						Context: "continuous-integration3",
+					},
+				},
+			}
+			if !cmp.Equal(statusChecks, want) {
+				t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
+			}
+		})
+	}
 }
 
-func TestRepositoriesService_License(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprint(w, `{"name": "LICENSE", "path": "LICENSE", "license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}}`)
-	})
-
-	ctx := context.Background()
-	got, _, err := client.Repositories.License(ctx, "o", "r")
-	if err != nil {
-		t.Errorf("Repositories.License returned error: %v", err)
-	}
+func TestRepositoriesService_RemoveRequiredStatusChecks(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				testHeader(t, r, "Accept", mediaTypeV3)
+				w.WriteHeader(http.StatusNoContent)
+			})
+
+			ctx := context.Background()
+			_, err := client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.RemoveRequiredStatusChecks returned error: %v", err)
+			}
 
-	want := &RepositoryLicense{
-		Name: String("LICENSE"),
-		Path: String("LICENSE"),
-		License: &License{
-			Name:     String("MIT License"),
-			Key:      String("mit"),
-			SPDXID:   String("MIT"),
-			URL:      String("https://api.github.com/licenses/mit"),
-			Featured: Bool(true),
-		},
-	}
+			const methodName = "RemoveRequiredStatusChecks"
+			testBadOptions(t, methodName, func() (err error) {
+				_, err = client.Repositories.RemoveRequiredStatusChecks(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.License returned %+v, want %+v", got, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				return client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", test.branch)
+			})
+		})
 	}
+}
 
-	const methodName = "License"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.License(ctx, "\n", "\n")
-		return err
-	})
+func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks/contexts"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks/contexts"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				fmt.Fprint(w, `["x", "y", "z"]`)
+			})
+
+			ctx := context.Background()
+			contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.License(ctx, "o", "r")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
+			want := []string{"x", "y", "z"}
+			if !cmp.Equal(contexts, want) {
+				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want)
+			}
 
-func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+			const methodName = "ListRequiredStatusChecksContexts"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ListRequiredStatusChecksContexts(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprint(w, `{
-			"strict": true,
-			"contexts": ["x","y","z"],
-			"checks": [
-				{
-					"context": "x",
-					"app_id": null
-				},
-				{
-					"context": "y",
-					"app_id": null
-				},
-				{
-					"context": "z",
-					"app_id": null
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
 				}
-			]
-		}`)
-	})
-
-	ctx := context.Background()
-	checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err)
+				return resp, err
+			})
+		})
 	}
+}
 
-	want := &RequiredStatusChecks{
-		Strict:   true,
-		Contexts: []string{"x", "y", "z"},
-		Checks: []*RequiredStatusCheck{
-			{
-				Context: "x",
-			},
-			{
-				Context: "y",
-			},
-			{
-				Context: "z",
-			},
-		},
-	}
-	if !cmp.Equal(checks, want) {
-		t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want)
+func TestRepositoriesService_ListRequiredStatusChecksContexts_branchNotProtected(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks/contexts"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks/contexts"},
 	}
 
-	const methodName = "GetRequiredStatusChecks"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetRequiredStatusChecks(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_GetRequiredStatusChecks_branchNotProtected(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
 
-		w.WriteHeader(http.StatusBadRequest)
-		fmt.Fprintf(w, `{
+				w.WriteHeader(http.StatusBadRequest)
+				fmt.Fprintf(w, `{
 			"message": %q,
 			"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
 			}`, githubBranchNotProtected)
-	})
+			})
 
-	ctx := context.Background()
-	checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", "b")
+			ctx := context.Background()
+			contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch)
 
-	if checks != nil {
-		t.Errorf("Repositories.GetRequiredStatusChecks returned non-nil status-checks data")
-	}
+			if contexts != nil {
+				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned non-nil contexts data")
+			}
 
-	if err != ErrBranchNotProtected {
-		t.Errorf("Repositories.GetRequiredStatusChecks returned an invalid error: %v", err)
+			if err != ErrBranchNotProtected {
+				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned an invalid error: %v", err)
+			}
+		})
 	}
 }
 
-func TestRepositoriesService_UpdateRequiredStatusChecks_Contexts(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				fmt.Fprintf(w, `{
+			"dismissal_restrictions":{
+				"users":[{"id":1,"login":"u"}],
+				"teams":[{"id":2,"slug":"t"}],
+				"apps":[{"id":3,"slug":"a"}]
+			},
+			"dismiss_stale_reviews":true,
+			"require_code_owner_reviews":true,
+			"required_approving_review_count":1
+		}`)
+			})
 
-	input := &RequiredStatusChecksRequest{
-		Strict:   Bool(true),
-		Contexts: []string{"continuous-integration"},
-	}
+			ctx := context.Background()
+			enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
-		v := new(RequiredStatusChecksRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
+			want := &PullRequestReviewsEnforcement{
+				DismissStaleReviews: true,
+				DismissalRestrictions: &DismissalRestrictions{
+					Users: []*User{
+						{Login: String("u"), ID: Int64(1)},
+					},
+					Teams: []*Team{
+						{Slug: String("t"), ID: Int64(2)},
+					},
+					Apps: []*App{
+						{Slug: String("a"), ID: Int64(3)},
+					},
+				},
+				RequireCodeOwnerReviews:      true,
+				RequiredApprovingReviewCount: 1,
+			}
 
-		testMethod(t, r, "PATCH")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
-		testHeader(t, r, "Accept", mediaTypeV3)
-		fmt.Fprintf(w, `{
-			"strict":true,
-			"contexts":["continuous-integration"],
-			"checks": [
-				{
-					"context": "continuous-integration",
-					"app_id": null
-				}
-			]
-		}`)
-	})
+			if !cmp.Equal(enforcement, want) {
+				t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
+			}
 
-	ctx := context.Background()
-	statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
-	}
+			const methodName = "GetPullRequestReviewEnforcement"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.GetPullRequestReviewEnforcement(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	want := &RequiredStatusChecks{
-		Strict:   true,
-		Contexts: []string{"continuous-integration"},
-		Checks: []*RequiredStatusCheck{
-			{
-				Context: "continuous-integration",
-			},
-		},
-	}
-	if !cmp.Equal(statusChecks, want) {
-		t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "UpdateRequiredStatusChecks"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.UpdateRequiredStatusChecks(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			input := &PullRequestReviewsEnforcementUpdate{
+				DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+					Users: &[]string{"u"},
+					Teams: &[]string{"t"},
+					Apps:  &[]string{"a"},
+				},
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				v := new(PullRequestReviewsEnforcementUpdate)
+				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
 
-func TestRepositoriesService_UpdateRequiredStatusChecks_Checks(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	appID := int64(123)
-	noAppID := int64(-1)
-	input := &RequiredStatusChecksRequest{
-		Strict: Bool(true),
-		Checks: []*RequiredStatusCheck{
-			{
-				Context: "continuous-integration",
-			},
-			{
-				Context: "continuous-integration2",
-				AppID:   &appID,
-			},
-			{
-				Context: "continuous-integration3",
-				AppID:   &noAppID,
-			},
-		},
-	}
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
-		v := new(RequiredStatusChecksRequest)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
-
-		testMethod(t, r, "PATCH")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
-		testHeader(t, r, "Accept", mediaTypeV3)
-		fmt.Fprintf(w, `{
-			"strict":true,
-			"contexts":["continuous-integration"],
-			"checks": [
-				{
-					"context": "continuous-integration",
-					"app_id": null
-				},
-				{
-					"context": "continuous-integration2",
-					"app_id": 123
-				},
-				{
-					"context": "continuous-integration3",
-					"app_id": null
+				testMethod(t, r, "PATCH")
+				if !cmp.Equal(v, input) {
+					t.Errorf("Request body = %+v, want %+v", v, input)
 				}
-			]
-		}`)
-	})
-
-	ctx := context.Background()
-	statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
-	}
-
-	want := &RequiredStatusChecks{
-		Strict:   true,
-		Contexts: []string{"continuous-integration"},
-		Checks: []*RequiredStatusCheck{
-			{
-				Context: "continuous-integration",
-			},
-			{
-				Context: "continuous-integration2",
-				AppID:   &appID,
-			},
-			{
-				Context: "continuous-integration3",
-			},
-		},
-	}
-	if !cmp.Equal(statusChecks, want) {
-		t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
-	}
-}
-
-func TestRepositoriesService_RemoveRequiredStatusChecks(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		testHeader(t, r, "Accept", mediaTypeV3)
-		w.WriteHeader(http.StatusNoContent)
-	})
-
-	ctx := context.Background()
-	_, err := client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.RemoveRequiredStatusChecks returned error: %v", err)
-	}
-
-	const methodName = "RemoveRequiredStatusChecks"
-	testBadOptions(t, methodName, func() (err error) {
-		_, err = client.Repositories.RemoveRequiredStatusChecks(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		return client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", "b")
-	})
-}
-
-func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks/contexts", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprint(w, `["x", "y", "z"]`)
-	})
-
-	ctx := context.Background()
-	contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err)
-	}
-
-	want := []string{"x", "y", "z"}
-	if !cmp.Equal(contexts, want) {
-		t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want)
-	}
-
-	const methodName = "ListRequiredStatusChecksContexts"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListRequiredStatusChecksContexts(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_ListRequiredStatusChecksContexts_branchNotProtected(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks/contexts", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-
-		w.WriteHeader(http.StatusBadRequest)
-		fmt.Fprintf(w, `{
-			"message": %q,
-			"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
-			}`, githubBranchNotProtected)
-	})
-
-	ctx := context.Background()
-	contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", "b")
-
-	if contexts != nil {
-		t.Errorf("Repositories.ListRequiredStatusChecksContexts returned non-nil contexts data")
-	}
-
-	if err != ErrBranchNotProtected {
-		t.Errorf("Repositories.ListRequiredStatusChecksContexts returned an invalid error: %v", err)
-	}
-}
-
-func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-			"dismissal_restrictions":{
-				"users":[{"id":1,"login":"u"}],
-				"teams":[{"id":2,"slug":"t"}],
-				"apps":[{"id":3,"slug":"a"}]
-			},
-			"dismiss_stale_reviews":true,
-			"require_code_owner_reviews":true,
-			"required_approving_review_count":1
-		}`)
-	})
-
-	ctx := context.Background()
-	enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err)
-	}
-
-	want := &PullRequestReviewsEnforcement{
-		DismissStaleReviews: true,
-		DismissalRestrictions: &DismissalRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-			Apps: []*App{
-				{Slug: String("a"), ID: Int64(3)},
-			},
-		},
-		RequireCodeOwnerReviews:      true,
-		RequiredApprovingReviewCount: 1,
-	}
-
-	if !cmp.Equal(enforcement, want) {
-		t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
-	}
-
-	const methodName = "GetPullRequestReviewEnforcement"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetPullRequestReviewEnforcement(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	input := &PullRequestReviewsEnforcementUpdate{
-		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
-			Users: &[]string{"u"},
-			Teams: &[]string{"t"},
-			Apps:  &[]string{"a"},
-		},
-	}
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
-		v := new(PullRequestReviewsEnforcementUpdate)
-		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
-
-		testMethod(t, r, "PATCH")
-		if !cmp.Equal(v, input) {
-			t.Errorf("Request body = %+v, want %+v", v, input)
-		}
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		fmt.Fprintf(w, `{
-			"dismissal_restrictions":{
-				"users":[{"id":1,"login":"u"}],
-				"teams":[{"id":2,"slug":"t"}],
-				"apps":[{"id":3,"slug":"a"}]
-			},
-			"dismiss_stale_reviews":true,
-			"require_code_owner_reviews":true,
-			"required_approving_review_count":3
-		}`)
-	})
-
-	ctx := context.Background()
-	enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err)
-	}
-
-	want := &PullRequestReviewsEnforcement{
-		DismissStaleReviews: true,
-		DismissalRestrictions: &DismissalRestrictions{
-			Users: []*User{
-				{Login: String("u"), ID: Int64(1)},
-			},
-			Teams: []*Team{
-				{Slug: String("t"), ID: Int64(2)},
-			},
-			Apps: []*App{
-				{Slug: String("a"), ID: Int64(3)},
-			},
-		},
-		RequireCodeOwnerReviews:      true,
-		RequiredApprovingReviewCount: 3,
-	}
-	if !cmp.Equal(enforcement, want) {
-		t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
-	}
-
-	const methodName = "UpdatePullRequestReviewEnforcement"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "\n", "\n", "\n", input)
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PATCH")
-		// TODO: remove custom Accept header when this API fully launches
-		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
-		testBody(t, r, `{"dismissal_restrictions":{}}`+"\n")
-		fmt.Fprintf(w, `{"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`)
-	})
-
-	ctx := context.Background()
-	enforcement, _, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err)
-	}
-
-	want := &PullRequestReviewsEnforcement{
-		DismissStaleReviews:          true,
-		DismissalRestrictions:        nil,
-		RequireCodeOwnerReviews:      true,
-		RequiredApprovingReviewCount: 1,
-	}
-	if !cmp.Equal(enforcement, want) {
-		t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want)
-	}
-
-	const methodName = "DisableDismissalRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.DisableDismissalRestrictions(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		w.WriteHeader(http.StatusNoContent)
-	})
-
-	ctx := context.Background()
-	_, err := client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err)
-	}
-
-	const methodName = "RemovePullRequestReviewEnforcement"
-	testBadOptions(t, methodName, func() (err error) {
-		_, err = client.Repositories.RemovePullRequestReviewEnforcement(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		return client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", "b")
-	})
-}
-
-func TestRepositoriesService_GetAdminEnforcement(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
-	})
-
-	ctx := context.Background()
-	enforcement, _, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err)
-	}
-
-	want := &AdminEnforcement{
-		URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
-		Enabled: true,
-	}
-
-	if !cmp.Equal(enforcement, want) {
-		t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want)
-	}
-
-	const methodName = "GetAdminEnforcement"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetAdminEnforcement(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_AddAdminEnforcement(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "POST")
-		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
-	})
-
-	ctx := context.Background()
-	enforcement, _, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err)
-	}
-
-	want := &AdminEnforcement{
-		URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
-		Enabled: true,
-	}
-	if !cmp.Equal(enforcement, want) {
-		t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want)
-	}
-
-	const methodName = "AddAdminEnforcement"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.AddAdminEnforcement(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		w.WriteHeader(http.StatusNoContent)
-	})
-
-	ctx := context.Background()
-	_, err := client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err)
-	}
-
-	const methodName = "RemoveAdminEnforcement"
-	testBadOptions(t, methodName, func() (err error) {
-		_, err = client.Repositories.RemoveAdminEnforcement(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		return client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", "b")
-	})
-}
-
-func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
-		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`)
-	})
-
-	ctx := context.Background()
-	signature, _, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err)
-	}
-
-	want := &SignaturesProtectedBranch{
-		URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
-		Enabled: Bool(false),
-	}
-
-	if !cmp.Equal(signature, want) {
-		t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want)
-	}
-
-	const methodName = "GetSignaturesProtectedBranch"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.GetSignaturesProtectedBranch(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "POST")
-		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
-		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`)
-	})
-
-	ctx := context.Background()
-	signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err)
-	}
-
-	want := &SignaturesProtectedBranch{
-		URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
-		Enabled: Bool(true),
-	}
-
-	if !cmp.Equal(signature, want) {
-		t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want)
-	}
-
-	const methodName = "RequireSignaturesOnProtectedBranch"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
-
-func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
-		w.WriteHeader(http.StatusNoContent)
-	})
-
-	ctx := context.Background()
-	_, err := client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err)
-	}
-
-	const methodName = "OptionalSignaturesOnProtectedBranch"
-	testBadOptions(t, methodName, func() (err error) {
-		_, err = client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		return client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", "b")
-	})
-}
-
-func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) {
-	req := PullRequestReviewsEnforcementRequest{}
-
-	got, err := json.Marshal(req)
-	if err != nil {
-		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
-	}
-
-	want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
-	if want != string(got) {
-		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
-	}
-
-	req = PullRequestReviewsEnforcementRequest{
-		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{},
-	}
-
-	got, err = json.Marshal(req)
-	if err != nil {
-		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
-	}
-
-	want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
-	if want != string(got) {
-		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
-	}
-
-	req = PullRequestReviewsEnforcementRequest{
-		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
-			Users: &[]string{},
-			Teams: &[]string{},
-			Apps:  &[]string{},
-		},
-		RequireLastPushApproval: Bool(true),
-	}
-
-	got, err = json.Marshal(req)
-	if err != nil {
-		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
-	}
-
-	want = `{"dismissal_restrictions":{"users":[],"teams":[],"apps":[]},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0,"require_last_push_approval":true}`
-	if want != string(got) {
-		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
-	}
-}
-
-func TestRepositoriesService_ListAllTopics(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
-		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
-	})
-
-	ctx := context.Background()
-	got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r")
-	if err != nil {
-		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
-	}
-
-	want := []string{"go", "go-github", "github"}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
-	}
-
-	const methodName = "ListAllTopics"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListAllTopics(ctx, "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListAllTopics(ctx, "o", "r")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				fmt.Fprintf(w, `{
+					"dismissal_restrictions":{
+						"users":[{"id":1,"login":"u"}],
+						"teams":[{"id":2,"slug":"t"}],
+						"apps":[{"id":3,"slug":"a"}]
+					},
+					"dismiss_stale_reviews":true,
+					"require_code_owner_reviews":true,
+					"required_approving_review_count":3
+				}`)
+			})
 
-func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+			ctx := context.Background()
+			enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err)
+			}
 
-	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
-		fmt.Fprint(w, `{"names":[]}`)
-	})
+			want := &PullRequestReviewsEnforcement{
+				DismissStaleReviews: true,
+				DismissalRestrictions: &DismissalRestrictions{
+					Users: []*User{
+						{Login: String("u"), ID: Int64(1)},
+					},
+					Teams: []*Team{
+						{Slug: String("t"), ID: Int64(2)},
+					},
+					Apps: []*App{
+						{Slug: String("a"), ID: Int64(3)},
+					},
+				},
+				RequireCodeOwnerReviews:      true,
+				RequiredApprovingReviewCount: 3,
+			}
+			if !cmp.Equal(enforcement, want) {
+				t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
+			}
 
-	ctx := context.Background()
-	got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r")
-	if err != nil {
-		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
-	}
+			const methodName = "UpdatePullRequestReviewEnforcement"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "\n", "\n", "\n", input)
+				return err
+			})
 
-	want := []string{}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
 }
 
-func TestRepositoriesService_ReplaceAllTopics(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "PATCH")
+				// TODO: remove custom Accept header when this API fully launches
+				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+				testBody(t, r, `{"dismissal_restrictions":{}}`+"\n")
+				fmt.Fprintf(w, `{"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`)
+			})
+
+			ctx := context.Background()
+			enforcement, _, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err)
+			}
 
-	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PUT")
-		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
-		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
-	})
+			want := &PullRequestReviewsEnforcement{
+				DismissStaleReviews:          true,
+				DismissalRestrictions:        nil,
+				RequireCodeOwnerReviews:      true,
+				RequiredApprovingReviewCount: 1,
+			}
+			if !cmp.Equal(enforcement, want) {
+				t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want)
+			}
 
-	ctx := context.Background()
-	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"})
-	if err != nil {
-		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
-	}
+			const methodName = "DisableDismissalRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.DisableDismissalRestrictions(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	want := []string{"go", "go-github", "github"}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "ReplaceAllTopics"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ReplaceAllTopics(ctx, "\n", "\n", []string{"\n", "\n", "\n"})
-		return err
-	})
+func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				w.WriteHeader(http.StatusNoContent)
+			})
+
+			ctx := context.Background()
+			_, err := client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"})
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			const methodName = "RemovePullRequestReviewEnforcement"
+			testBadOptions(t, methodName, func() (err error) {
+				_, err = client.Repositories.RemovePullRequestReviewEnforcement(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				return client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", test.branch)
+			})
+		})
+	}
 }
 
-func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_GetAdminEnforcement(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
+			})
+
+			ctx := context.Background()
+			enforcement, _, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err)
+			}
 
-	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PUT")
-		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
-		testBody(t, r, `{"names":[]}`+"\n")
-		fmt.Fprint(w, `{"names":[]}`)
-	})
+			want := &AdminEnforcement{
+				URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
+				Enabled: true,
+			}
 
-	ctx := context.Background()
-	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", nil)
-	if err != nil {
-		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
-	}
+			if !cmp.Equal(enforcement, want) {
+				t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want)
+			}
 
-	want := []string{}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+			const methodName = "GetAdminEnforcement"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.GetAdminEnforcement(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
 }
 
-func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_AddAdminEnforcement(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "POST")
+				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
+			})
+
+			ctx := context.Background()
+			enforcement, _, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err)
+			}
 
-	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PUT")
-		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
-		testBody(t, r, `{"names":[]}`+"\n")
-		fmt.Fprint(w, `{"names":[]}`)
-	})
+			want := &AdminEnforcement{
+				URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
+				Enabled: true,
+			}
+			if !cmp.Equal(enforcement, want) {
+				t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want)
+			}
 
-	ctx := context.Background()
-	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{})
-	if err != nil {
-		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
-	}
+			const methodName = "AddAdminEnforcement"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.AddAdminEnforcement(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	want := []string{}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
 }
 
-func TestRepositoriesService_ListAppRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				w.WriteHeader(http.StatusNoContent)
+			})
+
+			ctx := context.Background()
+			_, err := client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-	})
+			const methodName = "RemoveAdminEnforcement"
+			testBadOptions(t, methodName, func() (err error) {
+				_, err = client.Repositories.RemoveAdminEnforcement(ctx, "\n", "\n", "\n")
+				return err
+			})
 
-	ctx := context.Background()
-	_, _, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", "b")
-	if err != nil {
-		t.Errorf("Repositories.ListAppRestrictions returned error: %v", err)
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				return client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", test.branch)
+			})
+		})
 	}
+}
 
-	const methodName = "ListAppRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListAppRestrictions(ctx, "\n", "\n", "\n")
-		return err
-	})
+func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_signatures"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+				testHeader(t, r, "Accept", mediaTypeSignaturePreview)
+				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`)
+			})
+
+			ctx := context.Background()
+			signature, _, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
+			want := &SignaturesProtectedBranch{
+				URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
+				Enabled: Bool(false),
+			}
 
-func TestRepositoriesService_ReplaceAppRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+			if !cmp.Equal(signature, want) {
+				t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PUT")
-		fmt.Fprint(w, `[{
-				"name": "octocat"
-			}]`)
-	})
-	input := []string{"octocat"}
-	ctx := context.Background()
-	got, _, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.ReplaceAppRestrictions returned error: %v", err)
-	}
-	want := []*App{
-		{Name: String("octocat")},
-	}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ReplaceAppRestrictions returned %+v, want %+v", got, want)
+			const methodName = "GetSignaturesProtectedBranch"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.GetSignaturesProtectedBranch(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "ReplaceAppRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ReplaceAppRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_signatures"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "POST")
+				testHeader(t, r, "Accept", mediaTypeSignaturePreview)
+				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`)
+			})
+
+			ctx := context.Background()
+			signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
+			want := &SignaturesProtectedBranch{
+				URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
+				Enabled: Bool(true),
+			}
 
-func TestRepositoriesService_AddAppRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+			if !cmp.Equal(signature, want) {
+				t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "POST")
-		fmt.Fprint(w, `[{
-				"name": "octocat"
-			}]`)
-	})
-	input := []string{"octocat"}
-	ctx := context.Background()
-	got, _, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.AddAppRestrictions returned error: %v", err)
-	}
-	want := []*App{
-		{Name: String("octocat")},
-	}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.AddAppRestrictions returned %+v, want %+v", got, want)
+			const methodName = "RequireSignaturesOnProtectedBranch"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "AddAppRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.AddAppRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_signatures"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				testHeader(t, r, "Accept", mediaTypeSignaturePreview)
+				w.WriteHeader(http.StatusNoContent)
+			})
+
+			ctx := context.Background()
+			_, err := client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			const methodName = "OptionalSignaturesOnProtectedBranch"
+			testBadOptions(t, methodName, func() (err error) {
+				_, err = client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				return client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
+			})
+		})
+	}
 }
 
-func TestRepositoriesService_RemoveAppRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) {
+	req := PullRequestReviewsEnforcementRequest{}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		fmt.Fprint(w, `[]`)
-	})
-	input := []string{"octocat"}
-	ctx := context.Background()
-	got, _, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", "b", input)
+	got, err := json.Marshal(req)
 	if err != nil {
-		t.Errorf("Repositories.RemoveAppRestrictions returned error: %v", err)
+		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
 	}
-	want := []*App{}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.RemoveAppRestrictions returned %+v, want %+v", got, want)
+
+	want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
+	if want != string(got) {
+		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
 	}
 
-	const methodName = "RemoveAppRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.RemoveAppRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+	req = PullRequestReviewsEnforcementRequest{
+		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{},
+	}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
-}
+	got, err = json.Marshal(req)
+	if err != nil {
+		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
+	}
 
-func TestRepositoriesService_ListTeamRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+	want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
+	if want != string(got) {
+		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
+	}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/teams", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
-	})
+	req = PullRequestReviewsEnforcementRequest{
+		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+			Users: &[]string{},
+			Teams: &[]string{},
+			Apps:  &[]string{},
+		},
+		RequireLastPushApproval: Bool(true),
+	}
 
-	ctx := context.Background()
-	_, _, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", "b")
+	got, err = json.Marshal(req)
 	if err != nil {
-		t.Errorf("Repositories.ListTeamRestrictions returned error: %v", err)
+		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
 	}
 
-	const methodName = "ListTeamRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListTeamRestrictions(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+	want = `{"dismissal_restrictions":{"users":[],"teams":[],"apps":[]},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0,"require_last_push_approval":true}`
+	if want != string(got) {
+		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
+	}
 }
 
-func TestRepositoriesService_ReplaceTeamRestrictions(t *testing.T) {
+func TestRepositoriesService_ListAllTopics(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
-
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/teams", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "PUT")
-		fmt.Fprint(w, `[{
-				"name": "octocat"
-			}]`)
+
+	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
 	})
-	input := []string{"octocat"}
+
 	ctx := context.Background()
-	got, _, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", "b", input)
+	got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r")
 	if err != nil {
-		t.Errorf("Repositories.ReplaceTeamRestrictions returned error: %v", err)
-	}
-	want := []*Team{
-		{Name: String("octocat")},
+		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
 	}
+
+	want := []string{"go", "go-github", "github"}
 	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ReplaceTeamRestrictions returned %+v, want %+v", got, want)
+		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
 	}
 
-	const methodName = "ReplaceTeamRestrictions"
+	const methodName = "ListAllTopics"
 	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ReplaceTeamRestrictions(ctx, "\n", "\n", "\n", input)
+		_, _, err = client.Repositories.ListAllTopics(ctx, "\n", "\n")
 		return err
 	})
 
 	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", "b", input)
+		got, resp, err := client.Repositories.ListAllTopics(ctx, "o", "r")
 		if got != nil {
 			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
 		}
@@ -3031,71 +3067,57 @@ func TestRepositoriesService_ReplaceTeamRestrictions(t *testing.T) {
 	})
 }
 
-func TestRepositoriesService_AddTeamRestrictions(t *testing.T) {
+func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/teams", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "POST")
-		fmt.Fprint(w, `[{
-				"name": "octocat"
-			}]`)
+	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+		fmt.Fprint(w, `{"names":[]}`)
 	})
-	input := []string{"octocat"}
+
 	ctx := context.Background()
-	got, _, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", "b", input)
+	got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r")
 	if err != nil {
-		t.Errorf("Repositories.AddTeamRestrictions returned error: %v", err)
-	}
-	want := []*Team{
-		{Name: String("octocat")},
+		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
 	}
+
+	want := []string{}
 	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.AddTeamRestrictions returned %+v, want %+v", got, want)
+		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
 	}
-
-	const methodName = "AddTeamRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.AddTeamRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
 }
 
-func TestRepositoriesService_RemoveTeamRestrictions(t *testing.T) {
+func TestRepositoriesService_ReplaceAllTopics(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/teams", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		fmt.Fprint(w, `[]`)
+	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
 	})
-	input := []string{"octocat"}
+
 	ctx := context.Background()
-	got, _, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", "b", input)
+	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"})
 	if err != nil {
-		t.Errorf("Repositories.RemoveTeamRestrictions returned error: %v", err)
+		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
 	}
-	want := []*Team{}
+
+	want := []string{"go", "go-github", "github"}
 	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.RemoveTeamRestrictions returned %+v, want %+v", got, want)
+		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
 	}
 
-	const methodName = "RemoveTeamRestrictions"
+	const methodName = "ReplaceAllTopics"
 	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.RemoveTeamRestrictions(ctx, "\n", "\n", "\n", input)
+		_, _, err = client.Repositories.ReplaceAllTopics(ctx, "\n", "\n", []string{"\n", "\n", "\n"})
 		return err
 	})
 
 	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", "b", input)
+		got, resp, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"})
 		if got != nil {
 			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
 		}
@@ -3103,143 +3125,611 @@ func TestRepositoriesService_RemoveTeamRestrictions(t *testing.T) {
 	})
 }
 
-func TestRepositoriesService_ListUserRestrictions(t *testing.T) {
+func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/users", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "GET")
+	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+		testBody(t, r, `{"names":[]}`+"\n")
+		fmt.Fprint(w, `{"names":[]}`)
 	})
 
 	ctx := context.Background()
-	_, _, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", "b")
+	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", nil)
 	if err != nil {
-		t.Errorf("Repositories.ListUserRestrictions returned error: %v", err)
+		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
 	}
 
-	const methodName = "ListUserRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListUserRestrictions(ctx, "\n", "\n", "\n")
-		return err
-	})
-
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", "b")
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+	want := []string{}
+	if !cmp.Equal(got, want) {
+		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
+	}
 }
 
-func TestRepositoriesService_ReplaceUserRestrictions(t *testing.T) {
+func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/users", func(w http.ResponseWriter, r *http.Request) {
+	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
 		testMethod(t, r, "PUT")
-		fmt.Fprint(w, `[{
-				"name": "octocat"
-			}]`)
+		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
+		testBody(t, r, `{"names":[]}`+"\n")
+		fmt.Fprint(w, `{"names":[]}`)
 	})
-	input := []string{"octocat"}
+
 	ctx := context.Background()
-	got, _, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", "b", input)
+	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{})
 	if err != nil {
-		t.Errorf("Repositories.ReplaceUserRestrictions returned error: %v", err)
-	}
-	want := []*User{
-		{Name: String("octocat")},
+		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
 	}
+
+	want := []string{}
 	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.ReplaceUserRestrictions returned %+v, want %+v", got, want)
+		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
 	}
+}
 
-	const methodName = "ReplaceUserRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ReplaceUserRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+func TestRepositoriesService_ListAppRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+			})
+
+			ctx := context.Background()
+			_, _, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.ListAppRestrictions returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			const methodName = "ListAppRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ListAppRestrictions(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
 }
 
-func TestRepositoriesService_AddUserRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_ReplaceAppRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "PUT")
+				fmt.Fprint(w, `[{
+				"name": "octocat"
+			}]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.ReplaceAppRestrictions returned error: %v", err)
+			}
+			want := []*App{
+				{Name: String("octocat")},
+			}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.ReplaceAppRestrictions returned %+v, want %+v", got, want)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/users", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "POST")
-		fmt.Fprint(w, `[{
+			const methodName = "ReplaceAppRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ReplaceAppRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestRepositoriesService_AddAppRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "POST")
+				fmt.Fprint(w, `[{
 				"name": "octocat"
 			}]`)
-	})
-	input := []string{"octocat"}
-	ctx := context.Background()
-	got, _, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.AddUserRestrictions returned error: %v", err)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.AddAppRestrictions returned error: %v", err)
+			}
+			want := []*App{
+				{Name: String("octocat")},
+			}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.AddAppRestrictions returned %+v, want %+v", got, want)
+			}
+
+			const methodName = "AddAppRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.AddAppRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
-	want := []*User{
-		{Name: String("octocat")},
+}
+
+func TestRepositoriesService_RemoveAppRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				fmt.Fprint(w, `[]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.RemoveAppRestrictions returned error: %v", err)
+			}
+			want := []*App{}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.RemoveAppRestrictions returned %+v, want %+v", got, want)
+			}
+
+			const methodName = "RemoveAppRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.RemoveAppRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.AddUserRestrictions returned %+v, want %+v", got, want)
+}
+
+func TestRepositoriesService_ListTeamRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+			})
+
+			ctx := context.Background()
+			_, _, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.ListTeamRestrictions returned error: %v", err)
+			}
+
+			const methodName = "ListTeamRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ListTeamRestrictions(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "AddUserRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.AddUserRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+func TestRepositoriesService_ReplaceTeamRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "PUT")
+				fmt.Fprint(w, `[{
+				"name": "octocat"
+			}]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.ReplaceTeamRestrictions returned error: %v", err)
+			}
+			want := []*Team{
+				{Name: String("octocat")},
+			}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.ReplaceTeamRestrictions returned %+v, want %+v", got, want)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			const methodName = "ReplaceTeamRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ReplaceTeamRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
 }
 
-func TestRepositoriesService_RemoveUserRestrictions(t *testing.T) {
-	client, mux, _, teardown := setup()
-	defer teardown()
+func TestRepositoriesService_AddTeamRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "POST")
+				fmt.Fprint(w, `[{
+				"name": "octocat"
+			}]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.AddTeamRestrictions returned error: %v", err)
+			}
+			want := []*Team{
+				{Name: String("octocat")},
+			}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.AddTeamRestrictions returned %+v, want %+v", got, want)
+			}
 
-	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/users", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, "DELETE")
-		fmt.Fprint(w, `[]`)
-	})
-	input := []string{"octocat"}
-	ctx := context.Background()
-	got, _, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", "b", input)
-	if err != nil {
-		t.Errorf("Repositories.RemoveUserRestrictions returned error: %v", err)
+			const methodName = "AddTeamRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.AddTeamRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
-	want := []*User{}
-	if !cmp.Equal(got, want) {
-		t.Errorf("Repositories.RemoveUserRestrictions returned %+v, want %+v", got, want)
+}
+
+func TestRepositoriesService_RemoveTeamRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				fmt.Fprint(w, `[]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.RemoveTeamRestrictions returned error: %v", err)
+			}
+			want := []*Team{}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.RemoveTeamRestrictions returned %+v, want %+v", got, want)
+			}
+
+			const methodName = "RemoveTeamRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.RemoveTeamRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
 	}
+}
 
-	const methodName = "RemoveUserRestrictions"
-	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.RemoveUserRestrictions(ctx, "\n", "\n", "\n", input)
-		return err
-	})
+func TestRepositoriesService_ListUserRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "GET")
+			})
+
+			ctx := context.Background()
+			_, _, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", test.branch)
+			if err != nil {
+				t.Errorf("Repositories.ListUserRestrictions returned error: %v", err)
+			}
 
-	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", "b", input)
-		if got != nil {
-			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
-		}
-		return resp, err
-	})
+			const methodName = "ListUserRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ListUserRestrictions(ctx, "\n", "\n", "\n")
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", test.branch)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestRepositoriesService_ReplaceUserRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "PUT")
+				fmt.Fprint(w, `[{
+				"name": "octocat"
+			}]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.ReplaceUserRestrictions returned error: %v", err)
+			}
+			want := []*User{
+				{Name: String("octocat")},
+			}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.ReplaceUserRestrictions returned %+v, want %+v", got, want)
+			}
+
+			const methodName = "ReplaceUserRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.ReplaceUserRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestRepositoriesService_AddUserRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "POST")
+				fmt.Fprint(w, `[{
+				"name": "octocat"
+			}]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.AddUserRestrictions returned error: %v", err)
+			}
+			want := []*User{
+				{Name: String("octocat")},
+			}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.AddUserRestrictions returned %+v, want %+v", got, want)
+			}
+
+			const methodName = "AddUserRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.AddUserRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestRepositoriesService_RemoveUserRestrictions(t *testing.T) {
+	tests := []struct {
+		branch  string
+		urlPath string
+	}{
+		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
+		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
+	}
+
+	for _, test := range tests {
+		t.Run(test.branch, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
+				testMethod(t, r, "DELETE")
+				fmt.Fprint(w, `[]`)
+			})
+			input := []string{"octocat"}
+			ctx := context.Background()
+			got, _, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", test.branch, input)
+			if err != nil {
+				t.Errorf("Repositories.RemoveUserRestrictions returned error: %v", err)
+			}
+			want := []*User{}
+			if !cmp.Equal(got, want) {
+				t.Errorf("Repositories.RemoveUserRestrictions returned %+v, want %+v", got, want)
+			}
+
+			const methodName = "RemoveUserRestrictions"
+			testBadOptions(t, methodName, func() (err error) {
+				_, _, err = client.Repositories.RemoveUserRestrictions(ctx, "\n", "\n", "\n", input)
+				return err
+			})
+
+			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+				got, resp, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", test.branch, input)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
 }
 
 func TestRepositoriesService_Transfer(t *testing.T) {