resetRoutes(); foreach ($routes as $route) { $collection->{$route[0]}($route[1], $route[2]); } } $this->routes = $collection; return $this; } /** * Sets any values that should exist during this session. * * @param array $values * * @return $this */ public function withSession(array $values) { $this->session = $values; return $this; } /** * Don't run any events while running this test. * * @return $this */ public function skipEvents() { Events::simulate(true); return $this; } /** * Calls a single URI, executes it, and returns a FeatureResponse * instance that can be used to run many assertions against. * * @param string $method * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function call(string $method, string $path, array $params = null) { // Simulate having a blank session $_SESSION = []; $_SERVER['REQUEST_METHOD'] = $method; $request = $this->setupRequest($method, $path, $params); $request = $this->populateGlobals($method, $request, $params); // Make sure the RouteCollection knows what method we're using... if (! empty($this->routes)) { $this->routes->setHTTPVerb($method); } // Make sure any other classes that might call the request // instance get the right one. Services::injectMock('request', $request); $response = $this->app ->setRequest($request) ->run($this->routes, true); $output = ob_get_contents(); if (empty($response->getBody()) && ! empty($output)) { $response->setBody($output); } // Clean up any open output buffers // not relevant to unit testing // @codeCoverageIgnoreStart if (ob_get_level() > 0 && $this->clean) { ob_end_clean(); } // @codeCoverageIgnoreEnd $featureResponse = new FeatureResponse($response); return $featureResponse; } /** * Performs a GET request. * * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function get(string $path, array $params = null) { return $this->call('get', $path, $params); } /** * Performs a POST request. * * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function post(string $path, array $params = null) { return $this->call('post', $path, $params); } /** * Performs a PUT request * * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function put(string $path, array $params = null) { return $this->call('put', $path, $params); } /** * Performss a PATCH request * * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function patch(string $path, array $params = null) { return $this->call('patch', $path, $params); } /** * Performs a DELETE request. * * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function delete(string $path, array $params = null) { return $this->call('delete', $path, $params); } /** * Performs an OPTIONS request. * * @param string $path * @param array|null $params * * @return \CodeIgniter\Test\FeatureResponse * @throws \CodeIgniter\Router\Exceptions\RedirectException * @throws \Exception */ public function options(string $path, array $params = null) { return $this->call('options', $path, $params); } /** * Setup a Request object to use so that CodeIgniter * won't try to auto-populate some of the items. * * @param string $method * @param string|null $path * @param array|null $params * * @return \CodeIgniter\HTTP\IncomingRequest */ protected function setupRequest(string $method, string $path = null, array $params = null): IncomingRequest { $config = config(App::class); $uri = new URI($config->baseURL . '/' . trim($path, '/ ')); $request = new IncomingRequest($config, clone($uri), $params, new UserAgent()); $request->uri = $uri; $request->setMethod($method); $request->setProtocolVersion('1.1'); return $request; } /** * Populates the data of our Request with "global" data * relevant to the request, like $_POST data. * * Always populate the GET vars based on the URI. * * @param string $method * @param \CodeIgniter\HTTP\Request $request * @param array|null $params * * @return \CodeIgniter\HTTP\Request * @throws \ReflectionException */ protected function populateGlobals(string $method, Request $request, array $params = null) { $request->setGlobal('get', $this->getPrivateProperty($request->uri, 'query')); if ($method !== 'get') { $request->setGlobal($method, $params); } $_SESSION = $this->session; return $request; } }