# 测试响应

`TestResponse` 类提供了一系列实用方法，用于解析并验证测试用例返回的响应。通常，在进行 控制器测试 或 HTTP 功能测试 时会自动生成该对象，但也可以使用任何 `ResponseInterface` 实例直接创建：

    $result = new \CodeIgniter\Test\TestResponse($response);
    $result->assertOK();

## 测试响应

无论是通过测试获取还是手动创建的 `TestResponse`，都提供了一系列断言方法供测试使用。

### 访问请求/响应

#### request()

如果测试期间设置了 Request 对象，可直接进行访问：

    $request = $results->request();

#### response()

用于直接访问 Response 对象：

    $response = $results->response();

### 检查响应状态

#### isOK()

根据响应是否正常返回布尔值。判断标准主要是状态码是否在 200 或 300 范围内。除非是重定向，否则空的响应体会被视为无效。

    if ($result->isOK()) {
        // ...
    }

#### assertOK()

此断言使用 `isOK()` 方法测试响应。`assertNotOK()` 是其反向断言。

    $result->assertOK();

#### isRedirect()

根据响应是否为重定向返回布尔值。

    if ($result->isRedirect()) {
        // ...
    }

#### assertRedirect()

断言响应为 RedirectResponse 实例。`assertNotRedirect()` 是其反向断言。

    $result->assertRedirect();

#### assertRedirectTo()

断言响应为 RedirectResponse 实例，且目标地址与指定的 URI 匹配。

    $result->assertRedirectTo('foo/bar');

#### getRedirectUrl()

返回 RedirectResponse 设置的 URL，失败时返回 null。

    $url = $result->getRedirectUrl();
    $this->assertEquals(site_url('foo/bar'), $url);

#### assertStatus(int $code)

断言返回的 HTTP 状态码与 $code 匹配。

    $result->assertStatus(403);

### Session 断言

#### assertSessionHas(string $key, $value = null)

断言最终的 Session 中存在指定键值。如果传入 $value，还会断言该变量的值与预期一致。

    $result->assertSessionHas('logged_in', 123);

#### assertSessionMissing(string $key)

断言最终的 Session 中不包含指定的 $key。

    $result->assertSessionMissing('logged_in');

### HTTP 标头断言

#### assertHeader(string $key, $value = null)

断言响应中存在名为 `$key` 的 HTTP 标头。如果 `$value` 不为空，还将断言其值是否匹配。

    $result->assertHeader('Content-Type', 'text/html');

#### assertHeaderMissing(string $key)

断言响应中不存在名为 `$key` 的 HTTP 标头。

    $result->assertHeader('Accepts');

### Cookie 断言

#### assertCookie(string $key, $value = null, string $prefix = '')

断言响应中存在名为 `$key` 的 Cookie。如果 `$value` 不为空，还将断言其值是否匹配。如有需要，可通过第三个参数设置 Cookie 前缀。

    $result->assertCookie('foo', 'bar');

#### assertCookieMissing(string $key)

断言响应中不存在名为 `$key` 的 Cookie。

    $result->assertCookieMissing('ci_session');

#### assertCookieExpired(string $key, string $prefix = '')

断言名为 `$key` 的 Cookie 存在但已过期。如有需要，可通过第二个参数设置 Cookie 前缀。

    $result->assertCookieExpired('foo');

### DOM 辅助方法

Response 对象包含多个辅助方法，用于检查响应中的 HTML 输出。这些方法在执行测试断言时非常有用。

#### see()

根据页面上是否存在指定文本返回布尔值。支持直接查找文本，或根据类型、class、id 在特定标签内查找：

    // Check that "Hello World" is on the page
    if ($results->see('Hello World')) {
        // ...
    }

    // Check that "Hello World" is within an h1 tag
    if ($results->see('Hello World', 'h1')) {
        // ...
    }

    // Check that "Hello World" is within an element with the "notice" class
    if ($results->see('Hello World', '.notice')) {
        // ...
    }

    // Check that "Hello World" is within an element with id of "title"
    if ($results->see('Hello World', '#title')) {
        // ...
    }

`dontSee()` 方法的效果则完全相反：

    // Checks that "Hello World" does NOT exist on the page
    if ($results->dontSee('Hello World')) {
        // ...
    }

    // Checks that "Hellow World" does NOT exist within any h1 tag
    if ($results->dontSee('Hello World', 'h1')) {
        // ...
    }

#### seeElement()

`seeElement()` 和 `dontSeeElement()` 与前述方法类似，但它们不比对元素的值，而仅检查元素是否存在于页面上：

    // Check that an element with class 'notice' exists
    if ($results->seeElement('.notice')) {
        // ...
    }

    // Check that an element with id 'title' exists
    if ($results->seeElement('#title')) {
        // ...
    }

    // Verify that an element with id 'title' does NOT exist
    if ($results->dontSeeElement('#title')) {
        // ...
    }

#### seeLink()

使用 `seeLink()` 确保页面上出现了包含指定文本的链接：

    // Check that a link exists with 'Upgrade Account' as the text::
    if ($results->seeLink('Upgrade Account')) {
        // ...
    }

    // Check that a link exists with 'Upgrade Account' as the text, AND a class of 'upsell'
    if ($results->seeLink('Upgrade Account', '.upsell')) {
        // ...
    }

#### seeInField()

`seeInField()` 方法用于检查是否存在具有指定 name 和 value 的 input 标签：

    // Check that an input exists named 'user' with the value 'John Snow'
    if ($results->seeInField('user', 'John Snow')) {
        // ...
    }

    // Check a multi-dimensional input
    if ($results->seeInField('user[name]', 'John Snow')) {
        // ...
    }

#### seeCheckboxIsChecked()

使用 `seeCheckboxIsChecked()` 方法检查复选框是否存在且已被选中：

    // Check if checkbox is checked with class of 'foo'
    if ($results->seeCheckboxIsChecked('.foo')) {
        // ...
    }

    // Check if checkbox with id of 'bar' is checked
    if ($results->seeCheckboxIsChecked('#bar')) {
        // ...
    }

#### seeXPath()

Added in version 4.5.0.

使用 `seeXPath()` 可发挥 XPath 的强大功能。此方法面向高级用户，支持直接利用 DOMXPath 对象编写复杂的表达式：

    // Check that h1 element which contains class "heading" is on the page
    if ($results->seeXPath('//h1[contains(@class, "heading")]')) {
        // ...
    }

    // Check that h1 element which contains class "heading" have a text "Hello World"
    if ($results->seeXPath('//h1[contains(@class, "heading")][contains(.,"Hello world")]')) {
        // ...
    }

`dontSeeXPath()` 方法的效果则完全相反：

    // Check that h1 element which contains class "heading" does NOT exist on the page
    if ($results->dontSeeXPath('//h1[contains(@class, "heading")]')) {
        // ...
    }

    // Check that h1 element which contains class "heading" and text "Hello World" does NOT exist on the page
    if ($results->dontSeeXPath('//h1[contains(@class, "heading")][contains(.,"Hello world")]')) {
        // ...
    }

### DOM 断言

可使用下列断言测试响应正文中是否存在特定的元素或文本。

#### assertSee(string $search = null, string $element = null)

断言页面上存在特定的文本或 HTML。支持直接查找，或根据类型、class、id 在特定标签内查找：

    // Verify that "Hello World" is on the page
    $result->assertSee('Hello World');

    // Verify that "Hello World" is within an h1 tag
    $result->assertSee('Hello World', 'h1');

    // Verify that "Hello World" is within an element with the "notice" class
    $result->assertSee('Hello World', '.notice');

    // Verify that "Hello World" is within an element with id of "title"
    $result->assertSee('Hello World', '#title');

#### assertDontSee(string $search = null, string $element = null)

断言效果与 `assertSee()` 方法完全相反：

    // Verify that "Hello World" does NOT exist on the page
    $results->assertDontSee('Hello World');

    // Verify that "Hello World" does NOT exist within any h1 tag
    $results->assertDontSee('Hello World', 'h1');

#### assertSeeElement(string $search)

与 `assertSee()` 类似，但仅检查元素是否存在，不检查具体的文本内容：

    // Verify that an element with class 'notice' exists
    $results->assertSeeElement('.notice');

    // Verify that an element with id 'title' exists
    $results->assertSeeElement('#title');

#### assertDontSeeElement(string $search)

与 `assertSee()` 类似，但仅检查指定的元素是否不存在，不检查具体的文本内容：

    // Verify that an element with id 'title' does NOT exist
    $results->assertDontSeeElement('#title');

#### assertSeeLink(string $text, string $details = null)

断言存在一个以 `$text` 作为正文的 a 标签：

    // Verify that a link exists with 'Upgrade Account' as the text::
    $results->assertSeeLink('Upgrade Account');

    // Verify that a link exists with 'Upgrade Account' as the text, AND a class of 'upsell'
    $results->assertSeeLink('Upgrade Account', '.upsell');

#### assertSeeInField(string $field, string $value = null)

断言存在具有指定 name 和 value 的 input 标签：

    // Verify that an input exists named 'user' with the value 'John Snow'
    $results->assertSeeInField('user', 'John Snow');

    // Verify a multi-dimensional input
    $results->assertSeeInField('user[name]', 'John Snow');

### 处理 JSON

API 接口通常会返回 JSON 响应。下列方法可用于测试此类响应。

#### getJSON()

以 JSON 字符串形式返回响应正文：

    /*
     * Response body is this:
     * ['foo' => 'bar']
     */

    $json = $result->getJSON();
    /*
     * $json is this:
     * {
     *     "foo": "bar"
     * }
    `*/

可使用此方法判断 `$response` 是否确实包含 JSON 内容：

    // Verify the response is JSON
    $this->assertTrue($result->getJSON() !== false);

备注

注意，结果中的 JSON 字符串将进行格式美化。

#### assertJSONFragment(array $fragment)

断言 JSON 响应中包含指定的 `$fragment`。无需匹配整个 JSON 值。

    /*
     * Response body is this:
     * [
     *     'config' => ['key-a', 'key-b'],
     * ]
     */

    // Is true
    $result->assertJSONFragment(['config' => ['key-a']]);

#### assertJSONExact($test)

与 `assertJSONFragment()` 类似，但会检查整个 JSON 响应以确保完全匹配。

### 处理 XML

#### getXML()

如果应用返回 XML 内容，可通过此方法获取。