You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make BiDi transport factories composable via decorator-style UseTransport
✨ Enhancement🧪 Tests🕐 20-40 Minutes
AI Description
• Allow composing BiDi transport factories by exposing a next factory delegate.
• Enforce non-null ITransport results from the configured transport factory.
• Update BiDi session unit tests to use the new composable factory API.
Diagram
graph TD
U(("Caller")) --> C["BiDi.ConnectAsync"] --> B["BiDiOptionsBuilder"] --> P[["Transport factory chain"]] --> WS["WebSocketTransport.ConnectAsync"] --> T[("ITransport")] --> S["BiDi session"]
B --> D["UseTransport(next)"] -."decorates".-> P
subgraph Legend
direction LR
_a(("Caller")) ~~~ _p["API method"] ~~~ _s[["Composable step"]] ~~~ _t[("Transport")]
end
Loading
High-Level Assessment
The following are alternative approaches to this PR:
1. Add a new decorator API while keeping the old UseTransport(Func) overload
➕ Avoids breaking existing consumers that pass a simple factory
➕ Provides an easy on-ramp (simple factory) and an advanced on-ramp (decorator)
➖ Slightly larger surface area to maintain
➖ Requires deciding composition order semantics when both overload styles are used
2. Introduce an ITransportFactory interface (or ITransportFactoryDecorator) instead of delegates
➕ More discoverable and self-documenting than nested delegates
➕ Easier to unit test and mock in isolation; enables DI-friendly patterns
➖ More types/boilerplate for a simple extension point
➖ Potentially heavier API change than the current delegate approach
3. Model composition as an ordered middleware list (pipeline builder)
➕ Very clear composition ordering and behavior (middleware-style)
➕ Allows multiple decorators without nesting delegate signatures
➖ More implementation complexity than the current single-delegate approach
➖ May be overkill if only a few advanced users need this
Recommendation: The decorator-style UseTransport(next) is a good fit for enabling interception/logging without redesigning the transport layer. Consider adding back a convenience overload for simple factories (or a small helper) to reduce friction and limit breaking changes, while keeping next as the advanced composition mechanism.
Files changed (3) +19 / -23
Enhancement (1) +15 / -21
BiDiOptionsBuilder.csReplace single factory setter with composable transport factory decorator+15/-21
Replace single factory setter with composable transport factory decorator
• Introduces a default transport factory and changes UseTransport to accept a decorator callback that composes the current factory into a chain. Updates UseWebSocket to directly set the transport factory and clarifies XML docs around ownership and composition semantics.
BiDi.csValidate non-null transport from the configured factory+2/-1
Validate non-null transport from the configured factory
• Adds a null-guard after invoking the configured TransportFactory. ConnectAsync now throws a clear InvalidOperationException if the factory returns null.
SessionUnitTests.csAdapt tests to new composable UseTransport signature+2/-1
Adapt tests to new composable UseTransport signature
• Updates test setup to provide a decorated transport factory that returns the FakeTransport via Task.FromResult. Keeps existing test behavior while exercising the new API shape.
1. Missing null transport tests✗ Dismissed📘 Rule violation▣ Testability⭐ New
Description
The new null-guard behavior in ConnectAsync is a bug fix/behavioral change but no regression test
covers the null task/transport scenarios. Add tests that assert InvalidOperationException (and
ideally the message) for these invalid factory returns.
+ var transportFactoryTask = builder.TransportFactory(url, cancellationToken)+ ?? throw new InvalidOperationException("The transport factory must return a non-null Task<ITransport> instance.");++ var transport = await transportFactoryTask.ConfigureAwait(false)
Evidence
The checklist requires tests for new functionality and bug fixes. The diff adds new error-handling
behavior in ConnectAsync, and the current BiDi unit tests only cover successful connection setup
without asserting the new null-return guard paths.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`BiDi.ConnectAsync` now checks for `null` transport factory task and `null` transport results, but there are no tests asserting these error paths. This risks regressions where the behavior/message changes unintentionally.
## Issue Context
Existing BiDi tests exercise the happy-path `ConnectAsync` setup, but do not validate the new guard behavior.
## Fix Focus Areas
- dotnet/src/webdriver/BiDi/BiDi.cs[63-66]
- dotnet/test/webdriver/BiDi/SessionUnitTests.cs[33-40] (or add a new test file under dotnet/test/webdriver/BiDi/)
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
2. ConnectAsync adds new exception✗ Dismissed📘 Rule violation≡ Correctness⭐ New
Description
BiDi.ConnectAsync now throws InvalidOperationException with new user-visible messages when a
transport factory returns null task/transport. Per the cross-language consistency rule, this
behavior/message change should be compared with at least one other binding (or documented as an
intentional divergence).
+ var transportFactoryTask = builder.TransportFactory(url, cancellationToken)+ ?? throw new InvalidOperationException("The transport factory must return a non-null Task<ITransport> instance.");++ var transport = await transportFactoryTask.ConfigureAwait(false)
Evidence
The checklist requires cross-language comparison when changing user-visible behavior/messages. The
diff adds explicit exception messages in ConnectAsync for null-returning transport factories,
which is a user-visible behavior change.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`BiDi.ConnectAsync` now has new user-visible failure behavior/messages when the transport factory returns `null` (task or transport). The compliance checklist requires comparing such user-visible behavior changes across at least one other language binding (or documenting an intentional divergence).
## Issue Context
The new behavior is introduced by explicit null-guards with specific exception messages.
## Fix Focus Areas
- dotnet/src/webdriver/BiDi/BiDi.cs[63-66]
- (Add documentation/comment near the change OR update PR documentation to reference the other binding compared)
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
3. Null transport task NRE✓ Resolved🐞 Bug☼ Reliability
Description
BiDi.ConnectAsync awaits the Task returned from TransportFactory directly; if a user-supplied
factory returns null instead of a Task, the await throws NullReferenceException before the intended
InvalidOperationException. Validate the returned task before awaiting so malformed factories fail
with a clear, actionable exception.
+ var transport = await builder.TransportFactory(url, cancellationToken).ConfigureAwait(false)+ ?? throw new InvalidOperationException("The transport factory must return a non-null ITransport instance.");
Evidence
ConnectAsync awaits the TransportFactory invocation inline and only checks the *result* for null
afterward, so a null Task will fail earlier with a NullReferenceException. Because TransportFactory
is user-composable via UseTransport, a malformed decorator can create such a factory.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
`BiDi.ConnectAsync` added a null check for the awaited transport result, but a malformed transport factory can still return a `null` *task*, causing a `NullReferenceException` at the `await` expression before the intended validation runs.
### Issue Context
With the new composable transport factory API, consumers are more likely to create custom factories/decorators. A clearer exception message when a factory returns `null` helps diagnose misconfigurations quickly.
### Fix Focus Areas
- Assign the result of `TransportFactory(url, cancellationToken)` to a local variable and check it for null before awaiting.
- Throw a targeted `InvalidOperationException` (or `ArgumentException`) when the returned task is null.
- dotnet/src/webdriver/BiDi/BiDi.cs[56-65]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new transport-factory composition behavior is new functionality, but there is no test verifying
that multiple UseTransport(next) calls compose correctly (order, invocation, and disposal
expectations). This increases the risk of regressions in an API intended for advanced customization.
+ var factory = next(TransportFactory)+ ?? throw new InvalidOperationException("The transport factory decorator must return a non-null factory.");- return Task.FromResult(transport);- });- }-- private BiDiOptionsBuilder UseTransport(Func<Uri, CancellationToken, Task<ITransport>> factory)- {
TransportFactory = factory;
return this;
Evidence
The checklist requires tests for new functionality. The production code now composes a new transport
factory from the existing one via next(TransportFactory) and assigns it back, but the test changes
only update a single injection call site to the new signature and do not assert the new composition
semantics.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The new composable `UseTransport(next)` pipeline behavior is not covered by tests.
## Issue Context
This PR changes the transport customization model to a decorator chain. Without tests, ordering and chaining semantics (including non-null enforcement) can easily regress.
## Fix Focus Areas
- dotnet/src/webdriver/BiDi/BiDiOptionsBuilder.cs[62-70]
- dotnet/test/webdriver/BiDi/SessionUnitTests.cs[33-63]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
BiDiOptionsBuilder.UseTransport has been changed from its prior factory-delegate shape to a
decorator (next => ...) signature, which is a breaking public API/ABI change for existing
Selenium.WebDriver consumers and forces call-site updates. The previous API is not retained as an
overload or deprecated with guidance, and the change also risks losing the prior early-cancellation
behavior for simple/synchronous factories if the composed pipeline ignores the cancellation token.
+ public BiDiOptionsBuilder UseTransport(Func<Func<Uri, CancellationToken, Task<ITransport>>, Func<Uri, CancellationToken, Task<ITransport>>> next)
Evidence
The compliance requirements called out in the preferred evidence emphasize preserving
backward-compatible public API/ABI and using guided deprecation before removal; however, the PR
modifies the public UseTransport(...) surface to a new decorator-based form without keeping the
previous overload or adding an [Obsolete("Use ... instead.")] transition path. The duplicate
evidence further supports this by noting that the only public overload now requires a nested-Func
decorator and that tests were rewritten to pass a decorator-shaped factory, demonstrating that
existing call sites no longer compile and that this is a consumer-visible breaking change in the
Selenium.WebDriver v4.0.0 package.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`BiDiOptionsBuilder.UseTransport` is a public API and its signature was changed to a decorator-based callback, which breaks existing callers (and potentially compiled consumers expecting the old overloads). The prior factory-shaped API should be restored (at least temporarily) as backward-compatible overload(s) and deprecated with clear replacement guidance, while also preserving the earlier early-cancellation behavior for simple/synchronous factories.
## Issue Context
The current implementation exposes a composable decorator pipeline (`UseTransport(next => ...)`), but callers using the previous `UseTransport(() => transport)`-style pattern will fail to compile. This repository ships the `Selenium.WebDriver` package (version 4.0.0), so removing/changing public methods is a consumer-visible breaking change; additionally, the earlier simple factory overload provided an early-cancellation guard (returning a canceled task before invoking the factory) that can be lost if the composed factory ignores the token.
## Fix Focus Areas
- dotnet/src/webdriver/BiDi/BiDiOptionsBuilder.cs[28-71]
- dotnet/test/webdriver/BiDi/SessionUnitTests.cs[33-39]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
1. Null transport task NRE✓ Resolved🐞 Bug☼ Reliability
Description
BiDi.ConnectAsync awaits the Task returned from TransportFactory directly; if a user-supplied
factory returns null instead of a Task, the await throws NullReferenceException before the intended
InvalidOperationException. Validate the returned task before awaiting so malformed factories fail
with a clear, actionable exception.
+ var transport = await builder.TransportFactory(url, cancellationToken).ConfigureAwait(false)+ ?? throw new InvalidOperationException("The transport factory must return a non-null ITransport instance.");
Evidence
ConnectAsync awaits the TransportFactory invocation inline and only checks the *result* for null
afterward, so a null Task will fail earlier with a NullReferenceException. Because TransportFactory
is user-composable via UseTransport, a malformed decorator can create such a factory.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
`BiDi.ConnectAsync` added a null check for the awaited transport result, but a malformed transport factory can still return a `null` *task*, causing a `NullReferenceException` at the `await` expression before the intended validation runs.
### Issue Context
With the new composable transport factory API, consumers are more likely to create custom factories/decorators. A clearer exception message when a factory returns `null` helps diagnose misconfigurations quickly.
### Fix Focus Areas
- Assign the result of `TransportFactory(url, cancellationToken)` to a local variable and check it for null before awaiting.
- Throw a targeted `InvalidOperationException` (or `ArgumentException`) when the returned task is null.
- dotnet/src/webdriver/BiDi/BiDi.cs[56-65]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
The new transport-factory composition behavior is new functionality, but there is no test verifying
that multiple UseTransport(next) calls compose correctly (order, invocation, and disposal
expectations). This increases the risk of regressions in an API intended for advanced customization.
+ var factory = next(TransportFactory)+ ?? throw new InvalidOperationException("The transport factory decorator must return a non-null factory.");- return Task.FromResult(transport);- });- }-- private BiDiOptionsBuilder UseTransport(Func<Uri, CancellationToken, Task<ITransport>> factory)- {
TransportFactory = factory;
return this;
Evidence
The checklist requires tests for new functionality. The production code now composes a new transport
factory from the existing one via next(TransportFactory) and assigns it back, but the test changes
only update a single injection call site to the new signature and do not assert the new composition
semantics.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The new composable `UseTransport(next)` pipeline behavior is not covered by tests.
## Issue Context
This PR changes the transport customization model to a decorator chain. Without tests, ordering and chaining semantics (including non-null enforcement) can easily regress.
## Fix Focus Areas
- dotnet/src/webdriver/BiDi/BiDiOptionsBuilder.cs[62-70]
- dotnet/test/webdriver/BiDi/SessionUnitTests.cs[33-63]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
BiDiOptionsBuilder.UseTransport has been changed from its prior factory-delegate shape to a
decorator (next => ...) signature, which is a breaking public API/ABI change for existing
Selenium.WebDriver consumers and forces call-site updates. The previous API is not retained as an
overload or deprecated with guidance, and the change also risks losing the prior early-cancellation
behavior for simple/synchronous factories if the composed pipeline ignores the cancellation token.
+ public BiDiOptionsBuilder UseTransport(Func<Func<Uri, CancellationToken, Task<ITransport>>, Func<Uri, CancellationToken, Task<ITransport>>> next)
Evidence
The compliance requirements called out in the preferred evidence emphasize preserving
backward-compatible public API/ABI and using guided deprecation before removal; however, the PR
modifies the public UseTransport(...) surface to a new decorator-based form without keeping the
previous overload or adding an [Obsolete("Use ... instead.")] transition path. The duplicate
evidence further supports this by noting that the only public overload now requires a nested-Func
decorator and that tests were rewritten to pass a decorator-shaped factory, demonstrating that
existing call sites no longer compile and that this is a consumer-visible breaking change in the
Selenium.WebDriver v4.0.0 package.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`BiDiOptionsBuilder.UseTransport` is a public API and its signature was changed to a decorator-based callback, which breaks existing callers (and potentially compiled consumers expecting the old overloads). The prior factory-shaped API should be restored (at least temporarily) as backward-compatible overload(s) and deprecated with clear replacement guidance, while also preserving the earlier early-cancellation behavior for simple/synchronous factories.
## Issue Context
The current implementation exposes a composable decorator pipeline (`UseTransport(next => ...)`), but callers using the previous `UseTransport(() => transport)`-style pattern will fail to compile. This repository ships the `Selenium.WebDriver` package (version 4.0.0), so removing/changing public methods is a consumer-visible breaking change; additionally, the earlier simple factory overload provided an early-cancellation guard (returning a canceled task before invoking the factory) that can be lost if the composed factory ignores the token.
## Fix Focus Areas
- dotnet/src/webdriver/BiDi/BiDiOptionsBuilder.cs[28-71]
- dotnet/test/webdriver/BiDi/SessionUnitTests.cs[33-39]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Advanced users now can add additional layer over default low-level transport. Examples: listeners, interceptions, diagnostics, logging...
🔧 Implementation Notes
Only one change: Now bidi options expose
nextdelegate.Examples
Note: Could be tuned later, but for now it is great opportunity for hackers.
1. Default behavior
2. Customize WebSocket options only
3. Replace transport completely
4. Customize WebSocket options and wrap transport
5. Chain multiple wrappers
🤖 AI assistance
🔄 Types of changes