@@ -302,14 +302,15 @@ public virtual async Task<ICollection<Browser>> GetBrowsersAsync(CancellationTok
302302 /// A <see cref="Task{TResult}"/> representing the asynchronous operation to get the builds.
303303 /// </returns>
304304 public virtual Task < ICollection < Build > > GetBuildsAsync ( CancellationToken cancellationToken )
305- => GetBuildsAsync ( null , null , null , cancellationToken ) ;
305+ => GetBuildsAsync ( null , null , null , null , cancellationToken ) ;
306306
307307 /// <summary>
308308 /// Gets the builds as an asynchronous operation.
309309 /// </summary>
310310 /// <param name="limit">The optional number of builds to return. The default value is 10.</param>
311311 /// <param name="offset">The optional offset for builds to return. The default value is 0.</param>
312312 /// <param name="status">The optional status to filter builds to.</param>
313+ /// <param name="projectId">The optional project Id to filter builds to, if any.</param>
313314 /// <param name="cancellationToken">The optional cancellation token to use.</param>
314315 /// <returns>
315316 /// A <see cref="Task{TResult}"/> representing the asynchronous operation to get the builds.
@@ -318,9 +319,10 @@ public virtual async Task<ICollection<Build>> GetBuildsAsync(
318319 int ? limit = default ,
319320 int ? offset = default ,
320321 string ? status = default ,
322+ int ? projectId = default ,
321323 CancellationToken cancellationToken = default )
322324 {
323- string relativeUri = AppendQuery ( "builds.json" , limit , offset , status ) ;
325+ string relativeUri = AppendQuery ( "builds.json" , limit , offset , status , projectId ) ;
324326
325327 var builds = await GetJsonAsync (
326328 relativeUri ,
@@ -350,6 +352,30 @@ public virtual async Task<ProjectDetailItem> GetProjectAsync(int projectId, Canc
350352 return item ! ;
351353 }
352354
355+ /// <summary>
356+ /// Gets the badge for the project with the specified Id as an asynchronous operation.
357+ /// </summary>
358+ /// <param name="projectId">The Id of the project to get the status badge for.</param>
359+ /// <param name="cancellationToken">The optional cancellation token to use.</param>
360+ /// <returns>
361+ /// A <see cref="Task{TResult}"/> representing the asynchronous operation to get the
362+ /// key for the status badge for the project with the specified Id.
363+ /// </returns>
364+ public virtual async Task < string > GetProjectStatusBadgeAsync ( int projectId , CancellationToken cancellationToken = default )
365+ {
366+ using var response = await _client . GetAsync (
367+ FormattableString . Invariant ( $ "projects/{ projectId } /badge_key") ,
368+ cancellationToken ) . ConfigureAwait ( false ) ;
369+
370+ await EnsureSuccessAsync ( response , cancellationToken ) . ConfigureAwait ( false ) ;
371+
372+ #if NET8_0_OR_GREATER
373+ return await response . Content . ReadAsStringAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
374+ #else
375+ return await response . Content . ReadAsStringAsync ( ) . ConfigureAwait ( false ) ;
376+ #endif
377+ }
378+
353379 /// <summary>
354380 /// Gets the projects as an asynchronous operation.
355381 /// </summary>
@@ -371,7 +397,7 @@ public virtual async Task<ICollection<Project>> GetProjectsAsync(CancellationTok
371397 /// <exception cref="ArgumentException">
372398 /// <paramref name="sessionId"/> is <see langword="null"/> or white space.
373399 /// </exception>
374- public virtual async Task < SessionDetail ? > GetSessionAsync ( string sessionId , CancellationToken cancellationToken = default )
400+ public virtual async Task < Session ? > GetSessionAsync ( string sessionId , CancellationToken cancellationToken = default )
375401 {
376402 if ( string . IsNullOrWhiteSpace ( sessionId ) )
377403 {
@@ -450,6 +476,38 @@ public virtual Task<string> GetSessionConsoleLogsAsync(string buildId, string se
450476 public virtual Task < string > GetSessionNetworkLogsAsync ( string buildId , string sessionId , CancellationToken cancellationToken = default )
451477 => GetLogsAsync ( buildId , sessionId , "networklogs" , cancellationToken ) ;
452478
479+ /// <summary>
480+ /// Gets the session Selenium logs associated with the specified build and session Id as an asynchronous operation.
481+ /// </summary>
482+ /// <param name="buildId">The build Id to return the logs for.</param>
483+ /// <param name="sessionId">The session Id to return the logs for.</param>
484+ /// <param name="cancellationToken">The optional cancellation token to use.</param>
485+ /// <returns>
486+ /// A <see cref="Task{TResult}"/> representing the asynchronous operation to get the logs for the build and session
487+ /// with the specified Ids as a string.
488+ /// </returns>
489+ /// <exception cref="ArgumentException">
490+ /// <paramref name="buildId"/> or <paramref name="sessionId"/> is <see langword="null"/> or white space.
491+ /// </exception>
492+ public virtual Task < string > GetSessionSeleniumLogsAsync ( string buildId , string sessionId , CancellationToken cancellationToken = default )
493+ => GetLogsAsync ( buildId , sessionId , "seleniumlogs" , cancellationToken ) ;
494+
495+ /// <summary>
496+ /// Gets the session Selenium 4 telemetry logs associated with the specified build and session Id as an asynchronous operation.
497+ /// </summary>
498+ /// <param name="buildId">The build Id to return the logs for.</param>
499+ /// <param name="sessionId">The session Id to return the logs for.</param>
500+ /// <param name="cancellationToken">The optional cancellation token to use.</param>
501+ /// <returns>
502+ /// A <see cref="Task{TResult}"/> representing the asynchronous operation to get the logs for the build and session
503+ /// with the specified Ids as a string.
504+ /// </returns>
505+ /// <exception cref="ArgumentException">
506+ /// <paramref name="buildId"/> or <paramref name="sessionId"/> is <see langword="null"/> or white space.
507+ /// </exception>
508+ public virtual Task < string > GetSessionTelemetryLogsAsync ( string buildId , string sessionId , CancellationToken cancellationToken = default )
509+ => GetLogsAsync ( buildId , sessionId , "telemetrylogs" , cancellationToken ) ;
510+
453511 /// <summary>
454512 /// Gets the sessions associated with the specified build Id as an asynchronous operation.
455513 /// </summary>
@@ -540,30 +598,33 @@ public virtual async Task<ICollection<Session>> GetSessionsAsync(
540598 }
541599
542600 /// <summary>
543- /// Sets the name of the build with the specified Id as an asynchronous operation.
601+ /// Sets a tag of the build with the specified Id as an asynchronous operation.
544602 /// </summary>
545- /// <param name="buildId">The build Id to set the name of .</param>
546- /// <param name="name ">The new name .</param>
603+ /// <param name="buildId">The build Id to set the tag for .</param>
604+ /// <param name="tag ">The new build tag to set .</param>
547605 /// <param name="cancellationToken">The optional cancellation token to use.</param>
548606 /// <returns>
549607 /// A <see cref="Task{TResult}"/> representing the asynchronous operation to set the name for the specified build Id.
550608 /// </returns>
551609 /// <exception cref="ArgumentException">
552- /// <paramref name="name "/> is <see langword="null"/> or white space.
610+ /// <paramref name="tag "/> is <see langword="null"/> or white space.
553611 /// </exception>
554- public virtual Task < Build ? > SetBuildNameAsync (
612+ public virtual Task < Build ? > SetBuildTagAsync (
555613 int buildId ,
556- string name ,
614+ string tag ,
557615 CancellationToken cancellationToken = default )
558616 {
559- if ( string . IsNullOrWhiteSpace ( name ) )
617+ if ( string . IsNullOrWhiteSpace ( tag ) )
560618 {
561- throw new ArgumentException ( "No name specified." , nameof ( name ) ) ;
619+ throw new ArgumentException ( "No tag specified." , nameof ( tag ) ) ;
562620 }
563621
564- return SetNameAsync (
622+ var request = new SetBuildTagRequest ( ) { BuildTag = tag } ;
623+
624+ return PutJsonAsync (
565625 FormattableString . Invariant ( $ "builds/{ buildId } .json") ,
566- name ,
626+ request ,
627+ AppJsonSerializerContext . Default . SetBuildTagRequest ,
567628 AppJsonSerializerContext . Default . Build ,
568629 cancellationToken ) ;
569630 }
@@ -698,10 +759,16 @@ protected virtual void Dispose(bool disposing)
698759 /// <param name="limit">The limit to use, if any.</param>
699760 /// <param name="offset">The offset to use, if any.</param>
700761 /// <param name="status">The status to filter to, if any.</param>
762+ /// <param name="projectId">The project Id to filter to, if any.</param>
701763 /// <returns>
702764 /// The query string to use, if any.
703765 /// </returns>
704- private static string AppendQuery ( string relativeUri , int ? limit , int ? offset , string ? status )
766+ private static string AppendQuery (
767+ string relativeUri ,
768+ int ? limit ,
769+ int ? offset ,
770+ string ? status ,
771+ int ? projectId = null )
705772 {
706773 var parameters = new Dictionary < string , string ? > ( 3 ) ;
707774
@@ -730,6 +797,16 @@ private static string AppendQuery(string relativeUri, int? limit, int? offset, s
730797 parameters [ "status" ] = status ;
731798 }
732799
800+ if ( projectId . HasValue )
801+ {
802+ if ( projectId < 1 )
803+ {
804+ throw new ArgumentOutOfRangeException ( nameof ( projectId ) , projectId . Value , "The projectId value cannot be less than one." ) ;
805+ }
806+
807+ parameters [ "projectId" ] = projectId . Value . ToString ( CultureInfo . InvariantCulture ) ;
808+ }
809+
733810 if ( parameters . Count > 0 )
734811 {
735812 relativeUri = QueryHelpers . AddQueryString ( relativeUri , parameters ) ;
0 commit comments