Add durable candidate funnel
This commit is contained in:
1 parent
5abac31c28
commit
df35648920
20 files changed
+1128
-142
No files matched your search
+14
-6
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { MonitorService } from '../src/services/monitor.js';
|
||||
import { MonitorService, parseSelfDeclaredAge } from '../src/services/monitor.js';
|
||||
import {
|
||||
RedditRateLimitError,
|
||||
RedditSubredditUnavailableError,
|
||||
@@ -24,6 +24,7 @@ function createMockPostsRepo(processedIds: Set<string> = new Set()): PostsReposi
|
||||
isProcessed: vi.fn((id: string) => processedIds.has(id)),
|
||||
isProcessedAnywhere: vi.fn((id: string) => processedIds.has(id)),
|
||||
insert: vi.fn(),
|
||||
insertIfAbsent: vi.fn(() => true),
|
||||
updateAnalysis: vi.fn(),
|
||||
markMessageSent: vi.fn(),
|
||||
setError: vi.fn(),
|
||||
@@ -168,7 +169,7 @@ describe('MonitorService', () => {
|
||||
expect(redditApi.isSellerProfile).toHaveBeenCalledWith(
|
||||
'seller', config.reddit.sellerKeywords, config.reddit.sellerDomains, sellerPost,
|
||||
);
|
||||
expect(postsRepo.insert).toHaveBeenCalledWith(expect.objectContaining({ id: 't3_seller' }));
|
||||
expect(postsRepo.insertIfAbsent).toHaveBeenCalledWith(expect.objectContaining({ id: 't3_seller' }));
|
||||
expect(postsRepo.setError).toHaveBeenCalledWith('t3_seller', 'Seller signals detected');
|
||||
});
|
||||
|
||||
@@ -192,7 +193,7 @@ describe('MonitorService', () => {
|
||||
await expect(monitor.getUnprocessedPosts()).resolves.toEqual([selected]);
|
||||
expect(logger.logs).toContainEqual(expect.objectContaining({
|
||||
level: 'info',
|
||||
message: 'r/sub1 listing: 4 fetched; 3 screened; 0 already processed; 1 already messaged; 1 seller signals; 0 missing gender tag; 0 gender not targeted; 1 eligible (selected); 0 outside recent window; 1 not evaluated after selected recent candidate',
|
||||
message: 'r/sub1 listing: 4 fetched; 3 screened; 0 already processed; 1 already messaged; 1 seller signals; 0 missing gender tag; 0 gender not targeted; 0 missing age tag; 0 underage; 1 eligible (selected); 0 outside recent window; 1 not evaluated after selected recent candidate',
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -224,7 +225,7 @@ describe('MonitorService', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('finishes the seller and gender checks for one candidate before moving to the next', async () => {
|
||||
it('runs free gender and age checks before seller profile requests', async () => {
|
||||
const newer: RedditPost = {
|
||||
id: 't3_newer', subreddit: 'chat-sub', author: 'newer', title: '[30M] hello',
|
||||
url: '', permalink: '/r/chat-sub/newer', thumbnail: '', is_self: true,
|
||||
@@ -249,11 +250,18 @@ describe('MonitorService', () => {
|
||||
|
||||
await expect(monitor.getUnprocessedPosts()).resolves.toEqual([eligible]);
|
||||
expect(vi.mocked(redditApi.isSellerProfile).mock.calls.map(([username]) => username))
|
||||
.toEqual(['newer', 'eligible']);
|
||||
expect(postsRepo.insert).toHaveBeenCalledWith(expect.objectContaining({ id: 't3_newer' }));
|
||||
.toEqual(['eligible']);
|
||||
expect(postsRepo.insertIfAbsent).toHaveBeenCalledWith(expect.objectContaining({ id: 't3_newer' }));
|
||||
expect(postsRepo.setError).toHaveBeenCalledWith('t3_newer', 'Gender tag "male" not targeted');
|
||||
});
|
||||
|
||||
it('parses adult subreddit age tags without treating unrelated numbers as ages', () => {
|
||||
expect(parseSelfDeclaredAge('28 [F4M] Online')).toBe(28);
|
||||
expect(parseSelfDeclaredAge('[25F] hello')).toBe(25);
|
||||
expect(parseSelfDeclaredAge('F 31 looking to chat')).toBe(31);
|
||||
expect(parseSelfDeclaredAge('F4M, 100 percent bored')).toBeNull();
|
||||
});
|
||||
|
||||
it('tries next subreddit when first has no valid posts', async () => {
|
||||
const post1: RedditPost = {
|
||||
id: 't3_1', subreddit: 'sub2', author: 'user1', title: 'Post',
|
||||
|
||||
Reference in new issue
Block a user