@@ -90,4 +90,46 @@ public function resolvesBinaryOperationToResultingType(string $binaryOperationAs
9090 sprintf ('Expected %s, got %s ' , $ expectedType ::class, $ actualType ::class)
9191 );
9292 }
93+
94+
95+ /**
96+ * @return array<string,mixed>
97+ */
98+ public static function faultyArithmeticOperationExamples (): array
99+ {
100+ return [
101+ '1 + false ' => ['1 + false ' ],
102+ '1 + "foo" ' => ['1 + "foo" ' ],
103+ '1 + null ' => ['1 + null ' ],
104+ '1 + <img/> ' => ['1 + <img/> ' ],
105+ 'true + 1 ' => ['true + 1 ' ],
106+ '"bar" + 1 ' => ['"bar" + 1 ' ],
107+ 'null + 1 ' => ['null + 1 ' ],
108+ '<input/> + 1 ' => ['<input/> + 1 ' ],
109+ 'true + false ' => ['true + false ' ],
110+ 'true + null ' => ['true + null ' ],
111+ 'null + "foobar" ' => ['null + "foobar" ' ],
112+ '"foobar" + <link rel="barfoo"/> ' => ['"foobar" + <link rel="barfoo"/> ' ],
113+ ];
114+ }
115+
116+ /**
117+ * @dataProvider faultyArithmeticOperationExamples
118+ * @test
119+ * @param string $faultyArithmeticOperationAsString
120+ * @return void
121+ */
122+ public function throwsIfBinaryOperationIsArithmeticButOperandsAreNotOfTypeNumber (string $ faultyArithmeticOperationAsString ): void
123+ {
124+ $ scope = new DummyScope ();
125+ $ binaryOperationTypeResolver = new BinaryOperationTypeResolver (
126+ scope: $ scope
127+ );
128+ $ arithmeticOperationNode = ExpressionNode::fromString ($ faultyArithmeticOperationAsString )->root ;
129+ assert ($ arithmeticOperationNode instanceof BinaryOperationNode);
130+
131+ $ this ->expectExceptionMessageMatches ('/number/i ' );
132+
133+ $ binaryOperationTypeResolver ->resolveTypeOf ($ arithmeticOperationNode );
134+ }
93135}
0 commit comments