155 行
5.4 KiB
TypeScript
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)
|
|
})
|
|
})
|