2
0

SearchEmptyKeyTest.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <?php
  2. /**
  3. * 空 key 必须被 SearchRequest 拦下。
  4. *
  5. * 修复前它不报错,而是匹配到「空值」那一类数据:wbw 检索 whereIn('real', [''])
  6. * 命中 49 万个段落,标题检索 like '%%' 命中全部三万多条。调用方看到的是成功的
  7. * 响应和满屏结果,却与查询无关——AI agent 曾据此把整个语料库当成命中。
  8. *
  9. * 校验在进控制器之前就失败,所以这些用例不需要造数据。
  10. */
  11. use Illuminate\Foundation\Testing\RefreshDatabase;
  12. use Illuminate\Support\Facades\DB;
  13. uses(RefreshDatabase::class);
  14. $emptyKeys = [
  15. '空字符串' => '',
  16. '只有空白' => ' ',
  17. '只有逗号' => ',,',
  18. '只有分号' => ';;',
  19. ];
  20. $endpoints = [
  21. 'search view=title' => '/api/v2/search?view=title',
  22. 'search view=page' => '/api/v2/search?view=page',
  23. 'search view=pali' => '/api/v2/search?view=pali',
  24. 'search-book-list' => '/api/v2/search-book-list',
  25. 'search-pali-wbw' => '/api/v2/search-pali-wbw',
  26. 'search-pali-wbw-books' => '/api/v2/search-pali-wbw-books',
  27. ];
  28. foreach ($endpoints as $name => $url) {
  29. $glue = str_contains($url, '?') ? '&' : '?';
  30. foreach ($emptyKeys as $label => $key) {
  31. it("rejects {$label} on {$name}", function () use ($url, $glue, $key) {
  32. $this->getJson($url.$glue.'key='.urlencode($key))
  33. ->assertStatus(422)
  34. ->assertJsonValidationErrors('key');
  35. });
  36. }
  37. it("rejects a missing key on {$name}", function () use ($url) {
  38. $this->getJson($url)
  39. ->assertStatus(422)
  40. ->assertJsonValidationErrors('key');
  41. });
  42. }
  43. it('drops empty words split out of a valid key', function () {
  44. // `dhammo,,` 能过校验——它确实有一个可检索的词。但 explode 切出的空串若进了
  45. // whereIn('real', ...),就会把 real 为空的段落一并捞出来;线上那批有 49 万个
  46. $row = fn (int $paragraph, string $real, string $word) => [
  47. 'book' => 1, 'paragraph' => $paragraph, 'wid' => 1,
  48. 'word' => $word, 'real' => $real,
  49. 'type' => '', 'gramma' => '', 'part' => '', 'style' => '',
  50. 'pcd_book_id' => 1, 'weight' => 1,
  51. ];
  52. DB::table('wbw_templates')->insert([
  53. $row(1, 'dhammo', 'dhammo'),
  54. $row(2, '', '.'), // 线上这类空词元有四百多万行
  55. ]);
  56. $response = $this->getJson('/api/v2/search-pali-wbw?key='.urlencode('dhammo,,'))
  57. ->assertOk();
  58. expect($response->json('data.count'))->toBe(1)
  59. ->and($response->json('data.rows.0.paragraph'))->toBe(1);
  60. });
  61. it('rejects an empty key without an Accept header too', function () {
  62. // 默认配置下校验失败会 302 跳首页,客户端跟随重定向就拿到一张 HTML 首页;
  63. // bootstrap/app.php 里的 shouldRenderJsonWhen 让 api/* 一律回 JSON
  64. $this->get('/api/v2/search?view=title&key=')
  65. ->assertStatus(422)
  66. ->assertJsonValidationErrors('key');
  67. });