@@ -335,4 +335,92 @@ private function assertAddressObject(ReferenceType $address, bool $required): vo
335335
336336 $ this ->assertSame (['namespace ' => 'Address ' ], $ streetAddress ->custom ());
337337 }
338+
339+ /**
340+ * @test
341+ */
342+ public function it_supports_definition_of_objects_shorthand_nested_ns (): void
343+ {
344+ $ json = \file_get_contents (__DIR__ . DIRECTORY_SEPARATOR . '_files ' . DIRECTORY_SEPARATOR . 'schema_with_objects_shorthand_nested_ns.json ' );
345+ $ decodedJson = \json_decode ($ json , true , 512 , \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR );
346+
347+ $ typeSet = Type::fromShorthand ($ decodedJson , 'checkout ' , '/Order ' , '/Shipping ' );
348+
349+ $ this ->assertCount (1 , $ typeSet );
350+
351+ /** @var ObjectType $type */
352+ $ type = $ typeSet ->first ();
353+ $ this ->assertInstanceOf (ObjectType::class, $ type );
354+ $ this ->assertFalse ($ type ->additionalProperties ());
355+
356+ $ required = $ type ->required ();
357+ $ this ->assertCount (4 , $ required );
358+ $ this ->assertContains ('order ' , $ required );
359+ $ this ->assertContains ('salutation ' , $ required );
360+ $ this ->assertContains ('name ' , $ required );
361+ $ this ->assertContains ('items ' , $ required );
362+
363+ $ properties = $ type ->properties ();
364+ $ this ->assertCount (4 , $ properties );
365+ $ this ->assertArrayHasKey ('order ' , $ properties );
366+ $ this ->assertArrayHasKey ('salutation ' , $ properties );
367+ $ this ->assertArrayHasKey ('name ' , $ properties );
368+ $ this ->assertArrayHasKey ('items ' , $ properties );
369+
370+ /** @var ObjectType $order */
371+ $ order = $ properties ['order ' ]->first ();
372+ $ this ->assertInstanceOf (ObjectType::class, $ order );
373+ // implicit object Order is in namespace /Shipping and value objects with no namespace also in /Shipping
374+ $ this ->assertSame (['namespace ' => '/Shipping ' , 'voNamespace ' => '/Shipping ' ], $ order ->custom ());
375+
376+ $ subProperties = $ order ->properties ();
377+ $ this ->assertCount (3 , $ subProperties );
378+ $ this ->assertArrayHasKey ('billing_address ' , $ subProperties );
379+ $ this ->assertArrayHasKey ('shipping_address ' , $ subProperties );
380+ $ this ->assertArrayHasKey ('payment_address ' , $ subProperties );
381+
382+ /** @var StringType $paymentAddress */
383+ $ paymentAddress = $ subProperties ['payment_address ' ]->first ();
384+ $ this ->assertInstanceOf (StringType::class, $ paymentAddress );
385+ // value object defines it's own namespace
386+ $ this ->assertSame (['namespace ' => 'Payment ' ], $ paymentAddress ->custom ());
387+
388+ /** @var ReferenceType $billingAddress */
389+ $ billingAddress = $ subProperties ['billing_address ' ]->first ();
390+ $ this ->assertInstanceOf (ReferenceType::class, $ billingAddress );
391+ // reference value object use defined voNamespace because of missing namespace definition
392+ $ this ->assertSame (['namespace ' => '/Shipping ' ], $ billingAddress ->custom ());
393+ $ this ->assertSame ('#/definitions/Shipping/Address ' , $ billingAddress ->ref ());
394+
395+ /** @var ArrayType $shippingAddress */
396+ $ shippingAddress = $ subProperties ['shipping_address ' ]->first ();
397+ $ this ->assertInstanceOf (ArrayType::class, $ shippingAddress );
398+ // implicit array value object uses defined voNamespace
399+ $ this ->assertSame (['namespace ' => '/Shipping ' ], $ shippingAddress ->custom ());
400+
401+ /** @var ReferenceType $items */
402+ $ items = $ shippingAddress ->items ()[0 ]->first ();
403+ $ this ->assertInstanceOf (ReferenceType::class, $ items );
404+ // item defines it's own namespace
405+ $ this ->assertSame (['namespace ' => '/Order ' ], $ items ->custom ());
406+ $ this ->assertSame ('#/definitions/Order/Address ' , $ items ->ref ());
407+
408+ /** @var StringType $salutation */
409+ $ salutation = $ properties ['salutation ' ]->first ();
410+ $ this ->assertInstanceOf (StringType::class, $ salutation );
411+ $ this ->assertSame (['MR ' , 'MRS ' ], $ salutation ->enum ());
412+ $ this ->assertSame (['namespace ' => '/Contact ' ], $ salutation ->custom ());
413+
414+ /** @var StringType $name */
415+ $ name = $ properties ['name ' ]->first ();
416+ $ this ->assertInstanceOf (StringType::class, $ name );
417+ // value objects with no namespace are in voNamespace /Shipping
418+ $ this ->assertSame (['namespace ' => '/Shipping ' ], $ name ->custom ());
419+
420+ /** @var ArrayType $items */
421+ $ items = $ properties ['items ' ]->first ();
422+ $ this ->assertInstanceOf (ArrayType::class, $ items );
423+ // implicit array value object uses defined voNamespace
424+ $ this ->assertSame (['namespace ' => '/Shipping ' ], $ items ->custom ());
425+ }
338426}
0 commit comments