public async Task EnsuresNonNullArguments()
            {
                var connection = Substitute.For <IApiConnection>();
                var client     = new GitHubAppsClient(connection);

                Assert.ThrowsAsync <ArgumentNullException>(() => client.GetAllInstallationsForCurrent(null));
            }
            public async Task RequestsCorrectUrl()
            {
                var connection = Substitute.For <IApiConnection>();
                var client     = new GitHubAppsClient(connection);

                client.GetAllInstallationsForCurrent();

                connection.Received().GetAll <Installation>(Arg.Is <Uri>(u => u.ToString() == "app/installations"), null, "application/vnd.github.machine-man-preview+json");
            }
        public async Task <long> GetInstallationId(string repositoryUrl)
        {
            string[] segments = new Uri(repositoryUrl, UriKind.Absolute).Segments;
            string   org      = segments[segments.Length - 2].TrimEnd('/');

            if (HasCachedValue(org, out long installation))
            {
                return(installation);
            }

            await _sem.WaitAsync();

            try
            {
                if (HasCachedValue(org, out installation))
                {
                    return(installation);
                }

                ImmutableDictionary <string, long> .Builder newCache = ImmutableDictionary.CreateBuilder <string, long>();
                string appToken = _tokens.GetAppToken();
                var    client   = new GitHubAppsClient(
                    new ApiConnection(
                        new Connection(_options.Value.ProductHeader)
                {
                    Credentials = new Credentials(appToken, AuthenticationType.Bearer)
                }
                        )
                    );

                foreach (Installation i in await client.GetAllInstallationsForCurrent())
                {
                    newCache.Add(org, i.Id);
                }

                foreach (string key in _cache.Keys)
                {
                    // Anything we had before but don't have now has been uninstalled, remove it
                    newCache.TryAdd(key, 0);
                }

                // If the current thing wasn't in this list, it's not installed, record that so when they ask again in
                // a few seconds, we don't have to re-query GitHub
                newCache.TryAdd(org, 0);

                Interlocked.Exchange(ref _cache, newCache.ToImmutable());
                _lastCached = DateTimeOffset.UtcNow;

                return(_cache[org]);
            }
            finally
            {
                _sem.Release();
            }
        }
            public void RequestsTheCorrectUrlWithApiOptions()
            {
                var connection = Substitute.For <IApiConnection>();
                var client     = new GitHubAppsClient(connection);

                var options = new ApiOptions
                {
                    PageSize  = 1,
                    PageCount = 1,
                    StartPage = 1
                };

                client.GetAllInstallationsForCurrent(options);

                connection.Received().GetAll <Installation>(Arg.Is <Uri>(u => u.ToString() == "app/installations"), null, "application/vnd.github.machine-man-preview+json", options);
            }