'', '只有空白' => ' ', '只有逗号' => ',,', '只有分号' => ';;', ]; $endpoints = [ 'search view=title' => '/api/v2/search?view=title', 'search view=page' => '/api/v2/search?view=page', 'search view=pali' => '/api/v2/search?view=pali', 'search-book-list' => '/api/v2/search-book-list', 'search-pali-wbw' => '/api/v2/search-pali-wbw', 'search-pali-wbw-books' => '/api/v2/search-pali-wbw-books', ]; foreach ($endpoints as $name => $url) { $glue = str_contains($url, '?') ? '&' : '?'; foreach ($emptyKeys as $label => $key) { it("rejects {$label} on {$name}", function () use ($url, $glue, $key) { $this->getJson($url.$glue.'key='.urlencode($key)) ->assertStatus(422) ->assertJsonValidationErrors('key'); }); } it("rejects a missing key on {$name}", function () use ($url) { $this->getJson($url) ->assertStatus(422) ->assertJsonValidationErrors('key'); }); } it('drops empty words split out of a valid key', function () { // `dhammo,,` 能过校验——它确实有一个可检索的词。但 explode 切出的空串若进了 // whereIn('real', ...),就会把 real 为空的段落一并捞出来;线上那批有 49 万个 $row = fn (int $paragraph, string $real, string $word) => [ 'book' => 1, 'paragraph' => $paragraph, 'wid' => 1, 'word' => $word, 'real' => $real, 'type' => '', 'gramma' => '', 'part' => '', 'style' => '', 'pcd_book_id' => 1, 'weight' => 1, ]; DB::table('wbw_templates')->insert([ $row(1, 'dhammo', 'dhammo'), $row(2, '', '.'), // 线上这类空词元有四百多万行 ]); $response = $this->getJson('/api/v2/search-pali-wbw?key='.urlencode('dhammo,,')) ->assertOk(); expect($response->json('data.count'))->toBe(1) ->and($response->json('data.rows.0.paragraph'))->toBe(1); }); it('rejects an empty key without an Accept header too', function () { // 默认配置下校验失败会 302 跳首页,客户端跟随重定向就拿到一张 HTML 首页; // bootstrap/app.php 里的 shouldRenderJsonWhen 让 api/* 一律回 JSON $this->get('/api/v2/search?view=title&key=') ->assertStatus(422) ->assertJsonValidationErrors('key'); });