TipitakaReadChapterTest.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. use App\Models\PaliText;
  3. use Illuminate\Foundation\Testing\RefreshDatabase;
  4. use Illuminate\Support\Str;
  5. uses(RefreshDatabase::class);
  6. /**
  7. * 建一个 pali_texts 段落。第一段带 chapter_len 表示章节长度
  8. */
  9. function makePaliText(int $book, int $para, int $lenght, ?int $chapterLen = null): void
  10. {
  11. (new PaliText)->forceFill([
  12. 'book' => $book,
  13. 'paragraph' => $para,
  14. 'level' => $chapterLen ? 2 : 9,
  15. 'class' => '',
  16. 'toc' => '',
  17. 'text' => '',
  18. 'html' => '',
  19. 'lenght' => $lenght,
  20. 'chapter_len' => $chapterLen,
  21. 'pcd_book_id' => 0,
  22. 'uid' => (string) Str::uuid(),
  23. ])->save();
  24. }
  25. /**
  26. * book 9002 一个 5 段的章节,每段 100 字节,每段一句
  27. */
  28. function makeChapterFixture(): string
  29. {
  30. $channel = makeChannel(makeStudio('chapter-owner'), 'chapter channel');
  31. makePaliText(9002, 1, 100, 5);
  32. foreach (range(2, 5) as $para) {
  33. makePaliText(9002, $para, 100);
  34. }
  35. foreach (range(1, 5) as $para) {
  36. makeSentence($channel, 9002, $para, 1, "para {$para} text");
  37. }
  38. return $channel;
  39. }
  40. it('pages a chapter by paragraph count', function () {
  41. $channel = makeChapterFixture();
  42. $url = "/api/v3/tipitaka-read-chapter?book=9002&para=1&channel={$channel}&pagesize=2p";
  43. $first = $this->getJson($url)->assertOk()->json();
  44. expect(array_column($first['data'], 'para'))->toBe([1, 2]);
  45. expect($first['meta'])->toMatchArray([
  46. 'current_page' => 1,
  47. 'page_size' => '2p',
  48. 'total' => 5,
  49. 'first_para' => 1,
  50. 'last_para' => 2,
  51. 'has_more' => true,
  52. ]);
  53. $last = $this->getJson($url.'&page=3')->assertOk()->json();
  54. expect(array_column($last['data'], 'para'))->toBe([5]);
  55. expect($last['meta']['has_more'])->toBeFalse();
  56. $this->getJson($url.'&page=4')
  57. ->assertStatus(422)
  58. ->assertJsonPath('errors.page.0', __('site.invalid_parameter'));
  59. });
  60. it('pages a chapter by byte size using the lenght column', function () {
  61. $channel = makeChapterFixture();
  62. // 每段 100 字节,250b 累加到第 3 段才超过上限
  63. $url = "/api/v3/tipitaka-read-chapter?book=9002&para=1&channel={$channel}&pagesize=250b";
  64. $first = $this->getJson($url)->assertOk()->json();
  65. expect(array_column($first['data'], 'para'))->toBe([1, 2, 3]);
  66. $second = $this->getJson($url.'&page=2')->assertOk()->json();
  67. expect(array_column($second['data'], 'para'))->toBe([4, 5]);
  68. expect($second['meta']['has_more'])->toBeFalse();
  69. });
  70. it('returns at least one paragraph when it alone exceeds the byte size', function () {
  71. $channel = makeChapterFixture();
  72. $items = $this->getJson("/api/v3/tipitaka-read-chapter?book=9002&para=1&channel={$channel}&pagesize=1b")
  73. ->assertOk()
  74. ->json('data');
  75. expect(array_column($items, 'para'))->toBe([1]);
  76. });
  77. it('accepts the id form and the view parameter', function () {
  78. $channel = makeChapterFixture();
  79. $items = $this->getJson("/api/v3/tipitaka-read-chapter/9002-1?channel={$channel}&pagesize=1p&view=all")
  80. ->assertOk()
  81. ->json('data');
  82. expect($items)->toHaveCount(1);
  83. expect($items[0])->toHaveKeys(['para', 'display', 'sentences']);
  84. });
  85. it('rejects a bad id, channel, pagesize or unknown chapter', function () {
  86. $channel = makeChapterFixture();
  87. // v3 用真实状态码 + RFC 9457 Problem Details,不再看 ok 字段
  88. $this->getJson("/api/v3/tipitaka-read-chapter/bad-id?channel={$channel}")
  89. ->assertStatus(422)
  90. ->assertJsonStructure(['type', 'title', 'status', 'detail']);
  91. $this->getJson('/api/v3/tipitaka-read-chapter/9002-1?channel=not-a-uuid')
  92. ->assertStatus(422)
  93. ->assertJsonPath('errors.channel.0', __('site.invalid_parameter'));
  94. $this->getJson("/api/v3/tipitaka-read-chapter?book=9002&para=99&channel={$channel}")
  95. ->assertStatus(404)
  96. ->assertJsonPath('title', 'Resource not found.');
  97. $this->getJson("/api/v3/tipitaka-read-chapter?book=9002&para=1&channel={$channel}&pagesize=20000")
  98. ->assertStatus(422);
  99. });