ファイル
btrc-hub/frontend/src/pages/GekanatorPage.test.tsx
T
2026-06-12 01:33:40 +09:00

155 行
5.4 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { isQuestionHardFilteredAfterAnswers } from '@/lib/gekanatorQuestionFilters'
import type {
GekanatorAnswerLog,
GekanatorAnswerValue,
GekanatorQuestion,
GekanatorQuestionCondition,
} from '@/lib/gekanator'
const question = (
condition: GekanatorQuestionCondition,
): GekanatorQuestion => ({
id: `${ condition.type }:candidate`,
text: 'candidate?',
kind: condition.type === 'source'
? 'source'
: condition.type.startsWith ('original-')
? 'original_date'
: condition.type.startsWith ('title-')
? 'title'
: 'tag',
condition,
source: 'default',
priorityWeight: 1,
test: () => false,
})
const answer = (
condition: GekanatorQuestionCondition,
value: GekanatorAnswerValue,
): GekanatorAnswerLog => ({
questionId: 'previous',
questionText: 'previous?',
questionCondition: condition,
answer: value,
originalAnswer: value,
})
const blocked = (
candidate: GekanatorQuestionCondition,
previous: GekanatorQuestionCondition,
value: GekanatorAnswerValue,
): boolean =>
isQuestionHardFilteredAfterAnswers (question (candidate), [answer (previous, value)])
describe('isQuestionHardFilteredAfterAnswers', () => {
it('blocks only contradictory or redundant month questions after a yes answer', () => {
const previous: GekanatorQuestionCondition = { type: 'original-month', month: 12 }
expect(blocked ({ type: 'original-month', month: 12 }, previous, 'yes')).toBe(true)
expect(blocked ({ type: 'original-month', month: 2 }, previous, 'yes')).toBe(true)
expect(blocked ({ type: 'original-month-day', monthDay: '2-14' }, previous, 'yes'))
.toBe(true)
expect(blocked ({ type: 'original-month-day', monthDay: '12-25' }, previous, 'yes'))
.toBe(false)
expect(blocked ({ type: 'original-year', year: 2024 }, previous, 'yes')).toBe(false)
expect(blocked ({ type: 'source', host: 'example.com' }, previous, 'yes')).toBe(false)
expect(blocked ({ type: 'tag', key: 'character:喜多郁代' }, previous, 'yes')).toBe(false)
})
it('blocks same-month facts after a no answer', () => {
const previous: GekanatorQuestionCondition = { type: 'original-month', month: 12 }
expect(blocked ({ type: 'original-month', month: 12 }, previous, 'no')).toBe(true)
expect(blocked ({ type: 'original-month', month: 2 }, previous, 'no')).toBe(false)
expect(blocked ({ type: 'original-month-day', monthDay: '12-25' }, previous, 'no'))
.toBe(true)
expect(blocked ({ type: 'original-month-day', monthDay: '2-14' }, previous, 'no'))
.toBe(false)
})
it('blocks all month and month-day questions after a month-day yes answer', () => {
const previous: GekanatorQuestionCondition = {
type: 'original-month-day',
monthDay: '12-25',
}
expect(blocked ({ type: 'original-month', month: 12 }, previous, 'yes')).toBe(true)
expect(blocked ({ type: 'original-month', month: 2 }, previous, 'yes')).toBe(true)
expect(blocked ({ type: 'original-month-day', monthDay: '12-25' }, previous, 'yes'))
.toBe(true)
expect(blocked ({ type: 'original-month-day', monthDay: '12-26' }, previous, 'yes'))
.toBe(true)
})
it('blocks the same month-day only after a month-day no answer', () => {
const previous: GekanatorQuestionCondition = {
type: 'original-month-day',
monthDay: '12-25',
}
expect(blocked ({ type: 'original-month-day', monthDay: '12-25' }, previous, 'no'))
.toBe(true)
expect(blocked ({ type: 'original-month-day', monthDay: '12-26' }, previous, 'no'))
.toBe(false)
expect(blocked ({ type: 'original-month', month: 12 }, previous, 'no')).toBe(false)
})
it('blocks year and source as single-value facts', () => {
expect(blocked (
{ type: 'original-year', year: 2025 },
{ type: 'original-year', year: 2024 },
'yes',
)).toBe(true)
expect(blocked (
{ type: 'original-year', year: 2024 },
{ type: 'original-year', year: 2024 },
'no',
)).toBe(true)
expect(blocked (
{ type: 'source', host: 'b.example' },
{ type: 'source', host: 'a.example' },
'yes',
)).toBe(true)
expect(blocked (
{ type: 'source', host: 'b.example' },
{ type: 'source', host: 'a.example' },
'no',
)).toBe(false)
})
it('does not hard-filter partial, probably_no, or unknown fact answers', () => {
const previous: GekanatorQuestionCondition = { type: 'original-month', month: 12 }
const candidate: GekanatorQuestionCondition = { type: 'original-month', month: 2 }
expect(blocked (candidate, previous, 'partial')).toBe(false)
expect(blocked (candidate, previous, 'probably_no')).toBe(false)
expect(blocked (candidate, previous, 'unknown')).toBe(false)
})
it('keeps title-length hard redundancy for yes and no only', () => {
const previous: GekanatorQuestionCondition = {
type: 'title-length-at-least',
length: 30,
}
expect(blocked ({ type: 'title-length-at-least', length: 20 }, previous, 'yes'))
.toBe(true)
expect(blocked ({ type: 'title-length-at-least', length: 40 }, previous, 'yes'))
.toBe(false)
expect(blocked ({ type: 'title-length-at-least', length: 40 }, previous, 'no'))
.toBe(true)
expect(blocked ({ type: 'title-length-at-least', length: 20 }, previous, 'no'))
.toBe(false)
expect(blocked ({ type: 'title-length-at-least', length: 20 }, previous, 'partial'))
.toBe(false)
})
})