Inheritance: IPullRequestService
        public async void ShouldCheckoutExistingBranch()
        {
            var gitClient = Substitute.For<IGitClient>();
            var service = new PullRequestService(
                gitClient,
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            var pr = Substitute.For<IPullRequestModel>();

            await service.Checkout(localRepo, pr, "pr/123-foo1");

            gitClient.Received().Checkout(Arg.Any<IRepository>(), "pr/123-foo1").Forget();
            Assert.Equal(1, gitClient.ReceivedCalls().Count());
        }
    public void CreatePullRequestAllArgsMandatory()
    {
        var serviceProvider = Substitutes.ServiceProvider;
        var service = new PullRequestService(Substitute.For<IGitClient>(), serviceProvider.GetGitService(), serviceProvider.GetOperatingSystem(), Substitute.For<IUsageTracker>());

        IRepositoryHost host = null;
        ILocalRepositoryModel sourceRepo = null;
        ILocalRepositoryModel targetRepo = null;
        string title = null;
        string body = null;
        IBranch source = null;
        IBranch target = null;

        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        host = serviceProvider.GetRepositoryHosts().GitHubHost;
        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        sourceRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path");
        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        targetRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path");
        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        title = "a title";
        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        body = "a body";
        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        source = new BranchModel("source", sourceRepo);
        Assert.Throws<ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body));

        target = new BranchModel("target", targetRepo);
        var pr = service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body);

        Assert.NotNull(pr);
    }
        public async void ShouldCheckoutLocalBranch()
        {
            var gitClient = Substitute.For<IGitClient>();
            var service = new PullRequestService(
                gitClient,
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo"));

            var pr = Substitute.For<IPullRequestModel>();
            pr.Number.Returns(5);
            pr.Head.Returns(new GitReferenceModel("source", "owner:local", "123", "https://foo.bar/owner/repo"));

            await service.Checkout(localRepo, pr, "local");

            gitClient.Received().Fetch(Arg.Any<IRepository>(), "origin").Forget();
            gitClient.Received().Checkout(Arg.Any<IRepository>(), "local").Forget();
            Assert.Equal(2, gitClient.ReceivedCalls().Count());
        }
        public async Task ShouldRemoveUnusedRemote()
        {
            var gitClient = Substitute.For<IGitClient>();
            var gitService = MockGitService();
            var service = new PullRequestService(
                gitClient,
                gitService,
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar"));

            var repo = gitService.GetRepository(localRepo.CloneUrl);
            var remote1 = Substitute.For<Remote>();
            var remote2 = Substitute.For<Remote>();
            var remote3 = Substitute.For<Remote>();
            var remotes = new List<Remote> { remote1, remote2, remote3 };
            var remoteCollection = Substitute.For<RemoteCollection>();
            remote1.Name.Returns("remote1");
            remote2.Name.Returns("remote2");
            remote3.Name.Returns("remote3");
            remoteCollection.GetEnumerator().Returns(_ => remotes.GetEnumerator());
            repo.Network.Remotes.Returns(remoteCollection);

            var branch1 = Substitute.For<LibGit2Sharp.Branch>();
            var branch2 = Substitute.For<LibGit2Sharp.Branch>();
            var branches = new List<LibGit2Sharp.Branch> { branch1, branch2 };
            var branchCollection = Substitute.For<BranchCollection>();
            branch1.Remote.Returns(remote1);
            branch2.Remote.Returns(remote1);
            branchCollection.GetEnumerator().Returns(_ => branches.GetEnumerator());
            repo.Branches.Returns(branchCollection);

            gitClient.GetConfig<bool>(Arg.Any<IRepository>(), "remote.remote1.created-by-ghfvs").Returns(Task.FromResult(true));
            gitClient.GetConfig<bool>(Arg.Any<IRepository>(), "remote.remote2.created-by-ghfvs").Returns(Task.FromResult(true));

            await service.RemoveUnusedRemotes(localRepo);

            remoteCollection.DidNotReceive().Remove("remote1");
            remoteCollection.Received().Remove("remote2");
            remoteCollection.DidNotReceive().Remove("remote3");
        }
        public async Task ShouldReturnMarkedBranchForPullRequestFromFork()
        {
            var repo = Substitute.For<IRepository>();
            var config = Substitute.For<Configuration>();

            var configEntry1 = Substitute.For<ConfigurationEntry<string>>();
            configEntry1.Key.Returns("branch.pr/1-foo.ghfvs-pr");
            configEntry1.Value.Returns("1");
            var configEntry2 = Substitute.For<ConfigurationEntry<string>>();
            configEntry2.Key.Returns("branch.pr/2-bar.ghfvs-pr");
            configEntry2.Value.Returns("2");

            config.GetEnumerator().Returns(new List<ConfigurationEntry<string>>
            {
                configEntry1,
                configEntry2,
            }.GetEnumerator());

            repo.Config.Returns(config);

            var service = new PullRequestService(
                Substitute.For<IGitClient>(),
                MockGitService(repo),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            localRepo.CloneUrl.Returns(new UriString("https://github.com/baz/bar"));

            var result = await service.GetLocalBranches(localRepo, CreatePullRequest());

            Assert.Equal("pr/1-foo", result.Name);
        }
        public async Task ShouldReturnPullRequestBranchForPullRequestFromSameRepository()
        {
            var service = new PullRequestService(
                Substitute.For<IGitClient>(),
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            localRepo.CloneUrl.Returns(new UriString("https://github.com/foo/bar"));

            var result = await service.GetLocalBranches(localRepo, CreatePullRequest());

            Assert.Equal("source", result.Name);
        }
        public async Task DefaultLocalBranchNameShouldNotClashWithExistingBranchNames()
        {
            var service = new PullRequestService(
                Substitute.For<IGitClient>(),
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            var result = await service.GetDefaultLocalBranchName(localRepo, 123, "foo1");
            Assert.Equal("pr/123-foo1-3", result);
        }
        public async Task ShouldReturnCorrectDefaultLocalBranchNameForPullRequestsWithNonLatinChars()
        {
            var service = new PullRequestService(
                Substitute.For<IGitClient>(),
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            var result = await service.GetDefaultLocalBranchName(localRepo, 123, "コードをレビューする準備ができたこと");
            Assert.Equal("pr/123", result);
        }
        public async Task ShouldReturnCorrectDefaultLocalBranchName()
        {
            var service = new PullRequestService(
                Substitute.For<IGitClient>(),
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            var result = await service.GetDefaultLocalBranchName(localRepo, 123, "Pull requests can be \"named\" all sorts of thing's (sic)");
            Assert.Equal("pr/123-pull-requests-can-be-named-all-sorts-of-thing-s-sic", result);
        }
        public async void ShouldUseUniquelyNamedRemoteForFork()
        {
            var gitClient = Substitute.For<IGitClient>();
            var gitService = MockGitService();
            var service = new PullRequestService(
                gitClient,
                gitService,
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo"));

            var repo = gitService.GetRepository(localRepo.CloneUrl);
            var remote = Substitute.For<Remote>();
            var remoteCollection = Substitute.For<RemoteCollection>();
            remoteCollection["fork"].Returns(remote);
            repo.Network.Remotes.Returns(remoteCollection);

            var pr = Substitute.For<IPullRequestModel>();
            pr.Number.Returns(5);
            pr.Head.Returns(new GitReferenceModel("source", "owner:local", "123", "https://foo.bar/fork/repo.git"));

            await service.Checkout(localRepo, pr, "pr/5-fork-branch");

            gitClient.Received().SetRemote(Arg.Any<IRepository>(), "fork1", new Uri("https://foo.bar/fork/repo.git")).Forget();
            gitClient.Received().SetConfig(Arg.Any<IRepository>(), "remote.fork1.created-by-ghfvs", "true").Forget();
        }
        public async void ShouldCheckoutBranchFromFork()
        {
            var gitClient = Substitute.For<IGitClient>();
            var service = new PullRequestService(
                gitClient,
                MockGitService(),
                Substitute.For<IOperatingSystem>(),
                Substitute.For<IUsageTracker>());

            var localRepo = Substitute.For<ILocalRepositoryModel>();
            localRepo.CloneUrl.Returns(new UriString("https://foo.bar/owner/repo"));

            var pr = Substitute.For<IPullRequestModel>();
            pr.Number.Returns(5);
            pr.Head.Returns(new GitReferenceModel("source", "owner:local", "123", "https://foo.bar/fork/repo.git"));

            await service.Checkout(localRepo, pr, "pr/5-fork-branch");

            gitClient.Received().SetRemote(Arg.Any<IRepository>(), "fork", new Uri("https://foo.bar/fork/repo.git")).Forget();
            gitClient.Received().SetConfig(Arg.Any<IRepository>(), "remote.fork.created-by-ghfvs", "true").Forget();
            gitClient.Received().Fetch(Arg.Any<IRepository>(), "fork").Forget();
            gitClient.Received().Fetch(Arg.Any<IRepository>(), "fork", "source:pr/5-fork-branch").Forget();
            gitClient.Received().Checkout(Arg.Any<IRepository>(), "pr/5-fork-branch").Forget();
            gitClient.Received().SetTrackingBranch(Arg.Any<IRepository>(), "pr/5-fork-branch", "refs/remotes/fork/source").Forget();
            gitClient.Received().SetConfig(Arg.Any<IRepository>(), "branch.pr/5-fork-branch.ghfvs-pr", "5").Forget();
            Assert.Equal(7, gitClient.ReceivedCalls().Count());
        }
    public async Task CreatingPRs(int testId,
        string repoName, string sourceRepoOwner, string sourceBranchName,
        bool repoIsFork, bool sourceBranchIsTracking,
        string targetRepoOwner, string targetBranchName,
        string title, string body)
    {
        var remote = "origin";
        var data = PrepareTestData(repoName, sourceRepoOwner, sourceBranchName, targetRepoOwner, targetBranchName, "origin",
            repoIsFork, sourceBranchIsTracking);

        var targetRepo = data.TargetRepo;
        var gitClient = data.GitClient;
        var l2repo = data.L2Repo;
        var activeRepo = data.ActiveRepo;
        var sourceBranch = data.SourceBranch;
        var targetBranch = data.TargetBranch;
        var ms = data.ModelService;

        var prservice = new PullRequestService(data.GitClient, data.GitService, data.ServiceProvider.GetOperatingSystem(), Substitute.For<IUsageTracker>());
        var vm = new PullRequestCreationViewModel(data.RepositoryHost, data.ActiveRepo, prservice, data.NotificationService);

        vm.Initialize();

        // the user has to input this
        vm.PRTitle = title;

        // this is optional
        if (body != null)
            vm.Description = body;

        // the TargetBranch property gets set to whatever the repo default is (we assume master here),
        // so we only set it manually to emulate the user selecting a different target branch
        if (targetBranchName != "master")
            vm.TargetBranch = new BranchModel(targetBranchName, targetRepo);

        await vm.CreatePullRequest.ExecuteAsync();

        var unused2 = gitClient.Received().Push(l2repo, sourceBranchName, remote);
        if (!sourceBranchIsTracking)
            unused2 = gitClient.Received().SetTrackingBranch(l2repo, sourceBranchName, remote);
        else
            unused2 = gitClient.DidNotReceiveWithAnyArgs().SetTrackingBranch(Args.LibGit2Repo, Args.String, Args.String);
        var unused = ms.Received().CreatePullRequest(activeRepo, targetRepo, sourceBranch, targetBranch, title, body ?? String.Empty);
    }
 public void TargetBranchDisplayNameIncludesRepoOwnerWhenFork()
 {
     var data = PrepareTestData("octokit.net", "shana", "master", "octokit", "master", "origin", true, true);
     var prservice = new PullRequestService(data.GitClient, data.GitService, data.ServiceProvider.GetOperatingSystem(), Substitute.For<IUsageTracker>());
     prservice.GetPullRequestTemplate(data.ActiveRepo).Returns(Observable.Empty<string>());
     var vm = new PullRequestCreationViewModel(data.RepositoryHost, data.ActiveRepo, prservice, data.NotificationService);
     Assert.Equal("octokit/master", vm.TargetBranch.DisplayName);
 }