108 lines
3.5 KiB
Dart
108 lines
3.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:kouyu_english/core/dialogue_decision.dart';
|
|
import 'package:kouyu_english/core/models.dart';
|
|
|
|
DialogueAiIntervention acceptedAi() => const DialogueAiIntervention(
|
|
accepted: true,
|
|
goalSatisfied: true,
|
|
verdict: DialogueAiVerdict.accepted,
|
|
explanation: '表达自然。',
|
|
);
|
|
|
|
void main() {
|
|
group('resolveDialogueTurnDecision', () {
|
|
test('requires local and AI agreement for independent scene evidence', () {
|
|
final decision = resolveDialogueTurnDecision(
|
|
local: LocalDialogueVerdict.accepted,
|
|
ai: acceptedAi(),
|
|
aiWasAttempted: true,
|
|
isFreeScene: true,
|
|
supportLevel: DialogueSupportLevel.none,
|
|
);
|
|
|
|
expect(decision.canAdvance, isTrue);
|
|
expect(decision.evidenceOutcome, EvidenceKind.independentSuccess);
|
|
expect(decision.validationSource, DialogueValidationSource.localAndAi);
|
|
});
|
|
|
|
test(
|
|
'AI semantic acceptance advances an unknown local expression safely',
|
|
() {
|
|
final decision = resolveDialogueTurnDecision(
|
|
local: LocalDialogueVerdict.uncertain,
|
|
ai: acceptedAi(),
|
|
aiWasAttempted: true,
|
|
isFreeScene: true,
|
|
supportLevel: DialogueSupportLevel.none,
|
|
);
|
|
|
|
expect(decision.canAdvance, isTrue);
|
|
expect(decision.evidenceOutcome, EvidenceKind.pending);
|
|
expect(decision.validationSource, DialogueValidationSource.ai);
|
|
expect(decision.assisted, isFalse);
|
|
},
|
|
);
|
|
|
|
test('a correction can advance but is always assisted', () {
|
|
final decision = resolveDialogueTurnDecision(
|
|
local: LocalDialogueVerdict.accepted,
|
|
ai: acceptedAi(),
|
|
aiWasAttempted: true,
|
|
isFreeScene: true,
|
|
supportLevel: DialogueSupportLevel.correction,
|
|
);
|
|
|
|
expect(decision.canAdvance, isTrue);
|
|
expect(decision.evidenceOutcome, EvidenceKind.assisted);
|
|
expect(decision.assisted, isTrue);
|
|
});
|
|
|
|
test('invalid local input never advances', () {
|
|
final decision = resolveDialogueTurnDecision(
|
|
local: LocalDialogueVerdict.rejected,
|
|
ai: acceptedAi(),
|
|
aiWasAttempted: true,
|
|
isFreeScene: true,
|
|
supportLevel: DialogueSupportLevel.none,
|
|
);
|
|
|
|
expect(decision.canAdvance, isFalse);
|
|
});
|
|
|
|
test('AI outage degrades strict local acceptance to pending evidence', () {
|
|
final decision = resolveDialogueTurnDecision(
|
|
local: LocalDialogueVerdict.accepted,
|
|
ai: null,
|
|
aiWasAttempted: true,
|
|
isFreeScene: true,
|
|
supportLevel: DialogueSupportLevel.none,
|
|
);
|
|
|
|
expect(decision.canAdvance, isTrue);
|
|
expect(decision.evidenceOutcome, EvidenceKind.pending);
|
|
expect(decision.validationSource, DialogueValidationSource.unavailable);
|
|
});
|
|
|
|
test('explicit AI correction stops a local false positive', () {
|
|
const correction = DialogueAiIntervention(
|
|
accepted: false,
|
|
goalSatisfied: false,
|
|
verdict: DialogueAiVerdict.correctable,
|
|
suggestion: 'My name is Mia.',
|
|
explanation: '这句话需要修改。',
|
|
);
|
|
final decision = resolveDialogueTurnDecision(
|
|
local: LocalDialogueVerdict.accepted,
|
|
ai: correction,
|
|
aiWasAttempted: true,
|
|
isFreeScene: true,
|
|
supportLevel: DialogueSupportLevel.none,
|
|
);
|
|
|
|
expect(decision.canAdvance, isFalse);
|
|
expect(decision.evidenceOutcome, EvidenceKind.pending);
|
|
expect(decision.validationSource, DialogueValidationSource.disagreement);
|
|
});
|
|
});
|
|
}
|