|
4 | 4 | import { describe, expect, test } from 'bun:test'; |
5 | 5 | import type { Element } from 'domhandler'; |
6 | 6 | import { ForumCategory } from '../../../src/module/forum/forum-category'; |
7 | | -import { ForumPost } from '../../../src/module/forum/forum-post'; |
| 7 | +import { ForumPost, ForumPostCollection } from '../../../src/module/forum/forum-post'; |
8 | 8 | import { ForumThread } from '../../../src/module/forum/forum-thread'; |
9 | 9 | import type { ForumThreadRef, SiteRef } from '../../../src/module/types'; |
10 | 10 | import { User } from '../../../src/module/user/user'; |
@@ -351,3 +351,131 @@ describe('ForumPost data class', () => { |
351 | 351 | }); |
352 | 352 | }); |
353 | 353 | }); |
| 354 | + |
| 355 | +describe('ForumPostCollection', () => { |
| 356 | + describe('getPostSources', () => { |
| 357 | + test('can get sources for posts', async () => { |
| 358 | + const site = createMockSite(); |
| 359 | + const threadRef = createMockThreadRef(site); |
| 360 | + const createdBy = createMockUser('TestUser'); |
| 361 | + const mockElement = { type: 'tag', name: 'div' } as Element; |
| 362 | + |
| 363 | + const post1 = new ForumPost({ |
| 364 | + thread: threadRef, |
| 365 | + id: 5001, |
| 366 | + title: 'Post 1', |
| 367 | + text: '<p>Content 1</p>', |
| 368 | + element: mockElement, |
| 369 | + createdBy, |
| 370 | + createdAt: new Date(), |
| 371 | + editedBy: null, |
| 372 | + editedAt: null, |
| 373 | + parentId: null, |
| 374 | + }); |
| 375 | + |
| 376 | + const post2 = new ForumPost({ |
| 377 | + thread: threadRef, |
| 378 | + id: 5002, |
| 379 | + title: 'Post 2', |
| 380 | + text: '<p>Content 2</p>', |
| 381 | + element: mockElement, |
| 382 | + createdBy, |
| 383 | + createdAt: new Date(), |
| 384 | + editedBy: null, |
| 385 | + editedAt: null, |
| 386 | + parentId: null, |
| 387 | + }); |
| 388 | + |
| 389 | + const collection = new ForumPostCollection(threadRef, [post1, post2]); |
| 390 | + |
| 391 | + const mockResponse1 = { |
| 392 | + body: '<textarea name="source">Test source 1</textarea>', |
| 393 | + }; |
| 394 | + const mockResponse2 = { |
| 395 | + body: '<textarea name="source">Test source 2</textarea>', |
| 396 | + }; |
| 397 | + |
| 398 | + site.amcRequest = async () => ({ |
| 399 | + isErr: () => false, |
| 400 | + value: [mockResponse1, mockResponse2], |
| 401 | + }); |
| 402 | + |
| 403 | + const result = await collection.getPostSources(); |
| 404 | + |
| 405 | + expect(result.isOk()).toBe(true); |
| 406 | + expect(post1._source).toBe('Test source 1'); |
| 407 | + expect(post2._source).toBe('Test source 2'); |
| 408 | + }); |
| 409 | + |
| 410 | + test('skips already acquired sources', async () => { |
| 411 | + const site = createMockSite(); |
| 412 | + const threadRef = createMockThreadRef(site); |
| 413 | + const createdBy = createMockUser('TestUser'); |
| 414 | + const mockElement = { type: 'tag', name: 'div' } as Element; |
| 415 | + |
| 416 | + const post1 = new ForumPost({ |
| 417 | + thread: threadRef, |
| 418 | + id: 5001, |
| 419 | + title: 'Post 1', |
| 420 | + text: '<p>Content 1</p>', |
| 421 | + element: mockElement, |
| 422 | + createdBy, |
| 423 | + createdAt: new Date(), |
| 424 | + editedBy: null, |
| 425 | + editedAt: null, |
| 426 | + parentId: null, |
| 427 | + }); |
| 428 | + |
| 429 | + post1._source = 'cached source'; |
| 430 | + |
| 431 | + const post2 = new ForumPost({ |
| 432 | + thread: threadRef, |
| 433 | + id: 5002, |
| 434 | + title: 'Post 2', |
| 435 | + text: '<p>Content 2</p>', |
| 436 | + element: mockElement, |
| 437 | + createdBy, |
| 438 | + createdAt: new Date(), |
| 439 | + editedBy: null, |
| 440 | + editedAt: null, |
| 441 | + parentId: null, |
| 442 | + }); |
| 443 | + |
| 444 | + const collection = new ForumPostCollection(threadRef, [post1, post2]); |
| 445 | + |
| 446 | + const mockResponse = { |
| 447 | + body: '<textarea name="source">Test source 2</textarea>', |
| 448 | + }; |
| 449 | + |
| 450 | + let callCount = 0; |
| 451 | + site.amcRequest = async (requests) => { |
| 452 | + callCount++; |
| 453 | + // Only post2 should be requested |
| 454 | + expect(requests.length).toBe(1); |
| 455 | + expect(requests[0]?.postId).toBe(5002); |
| 456 | + return { |
| 457 | + isErr: () => false, |
| 458 | + value: [mockResponse], |
| 459 | + }; |
| 460 | + }; |
| 461 | + |
| 462 | + const result = await collection.getPostSources(); |
| 463 | + |
| 464 | + expect(result.isOk()).toBe(true); |
| 465 | + expect(callCount).toBe(1); |
| 466 | + expect(post1._source).toBe('cached source'); |
| 467 | + expect(post2._source).toBe('Test source 2'); |
| 468 | + }); |
| 469 | + |
| 470 | + test('handles empty collection', async () => { |
| 471 | + const site = createMockSite(); |
| 472 | + const threadRef = createMockThreadRef(site); |
| 473 | + const collection = new ForumPostCollection(threadRef, []); |
| 474 | + |
| 475 | + const result = await collection.getPostSources(); |
| 476 | + |
| 477 | + expect(result.isOk()).toBe(true); |
| 478 | + expect(collection.length).toBe(0); |
| 479 | + }); |
| 480 | + }); |
| 481 | +}); |
0 commit comments