diff --git a/rb/lib/selenium/webdriver/bidi/serialization/union.rb b/rb/lib/selenium/webdriver/bidi/serialization/union.rb index 7eb19754f9682..cd4821105f4c8 100644 --- a/rb/lib/selenium/webdriver/bidi/serialization/union.rb +++ b/rb/lib/selenium/webdriver/bidi/serialization/union.rb @@ -53,14 +53,18 @@ def object_only = @object_only = true # An outbound scalar outside that set matches no arm, so it is a caller error. def scalar_values(*values) = @scalar_values = values - # A non-Hash payload is a bare scalar arm (e.g. input.Origin's "viewport") with no - # object to dispatch on, so it is returned unchanged — unless every arm is an object - # (object_only), where a non-Hash cannot match any variant and is a wire error. + # A non-Hash payload is a bare scalar arm (e.g. input.Origin's "viewport"), valid only + # as a literal the schema pins; under object_only it cannot match any variant at all. def from_json(json_payload) unless json_payload.is_a?(::Hash) - return json_payload unless @object_only + if @object_only + raise Error::SerializationError, + "#{name} expected an object on the wire, got #{json_payload.inspect}" + end + return json_payload if scalar_arm?(json_payload) - raise Error::SerializationError, "#{name} expected an object on the wire, got #{json_payload.inspect}" + raise Error::SerializationError, + "#{name} received a scalar not in this Selenium's BiDi schema: #{json_payload.inspect}" end variant = select(json_payload) diff --git a/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb b/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb index b3425197c6298..73eeb893aa762 100644 --- a/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb +++ b/rb/spec/unit/selenium/webdriver/bidi/serialization_spec.rb @@ -87,10 +87,15 @@ def valid_cookie_attrs .to raise_error(Error::SerializationError, /RemoteValue expected an object/) end - it 'passes a bare scalar through a union that has a scalar arm (input.Origin)' do + it 'passes a declared bare scalar through a union that has a scalar arm (input.Origin)' do expect(Input::Origin.from_json('viewport')).to eq('viewport') end + it 'raises when a bare scalar is not one of the union scalar arms' do + expect { Input::Origin.from_json('banana') } + .to raise_error(Error::SerializationError, /Origin received a scalar not in this Selenium/) + end + it 'keeps a map string key while typing its object value (object-only value union)' do parsed = Script::ObjectRemoteValue.from_json( 'type' => 'object', 'value' => [['k', {'type' => 'number', 'value' => 2}]]