createSchema()); $params = $this->paramsOf($request); $this->assertArrayNotHasKey('mode', $params); $this->assertArrayHasKey('requestedSchema', $params); $this->assertSame(ElicitationMode::Form, $request->mode); } #[TestDox('url elicitation carries mode and url, and no schema')] public function testUrlCarriesModeAndUrl(): void { $request = ElicitRequest::forUrl('Finish setup', 'https://example.com/setup'); $params = $this->paramsOf($request); $this->assertSame('url', $params['mode']); $this->assertSame('https://example.com/setup', $params['url']); $this->assertArrayNotHasKey('requestedSchema', $params); $this->assertNull($request->requestedSchema); } #[TestDox('a request without mode is still read as form elicitation')] public function testAbsentModeDefaultsToForm(): void { $request = $this->requestFromParams([ 'message' => 'Your name?', 'requestedSchema' => [ 'type' => 'object', 'properties' => ['name' => ['type' => 'string', 'title' => 'Name']], ], ]); $this->assertSame(ElicitationMode::Form, $request->mode); $this->assertNotNull($request->requestedSchema); } #[TestDox('parses an explicit url-mode request')] public function testParsesUrlMode(): void { $request = $this->requestFromParams([ 'message' => 'Finish setup', 'mode' => 'url', 'url' => 'https://example.com/setup', ]); $this->assertSame(ElicitationMode::Url, $request->mode); $this->assertSame('https://example.com/setup', $request->url); } #[TestDox('url mode without a url is rejected')] public function testUrlModeRequiresUrl(): void { $this->expectException(InvalidArgumentException::class); $this->requestFromParams(['message' => 'Finish setup', 'mode' => 'url']); } #[TestDox('form mode without a schema is rejected')] public function testFormModeRequiresSchema(): void { $this->expectException(InvalidArgumentException::class); $this->requestFromParams(['message' => 'Your name?']); } #[TestDox('an unknown mode is rejected rather than silently treated as a form')] public function testUnknownModeRejected(): void { $this->expectException(InvalidArgumentException::class); $this->requestFromParams(['message' => 'hi', 'mode' => 'telepathy']); } #[TestDox('an explicit null mode is rejected rather than defaulting to form')] public function testNullModeRejected(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid "mode" parameter'); $this->requestFromParams([ 'message' => 'Your name?', 'mode' => null, 'requestedSchema' => [ 'type' => 'object', 'properties' => ['name' => ['type' => 'string', 'title' => 'Name']], ], ]); } private function createSchema(): ElicitationSchema { return new ElicitationSchema(['name' => new StringSchemaDefinition('Name')], ['name']); } /** * @param array $params */ private function requestFromParams(array $params): ElicitRequest { return ElicitRequest::fromArray([ 'jsonrpc' => MessageInterface::JSONRPC_VERSION, 'id' => 'request-1', 'method' => ElicitRequest::getMethod(), 'params' => $params, ]); } /** * @return array */ private function paramsOf(ElicitRequest $request): array { /** @var array{params?: array} $encoded */ $encoded = json_decode(json_encode($request->withId('request-1')) ?: '', true); return $encoded['params'] ?? []; } }