0d3cb498a3
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
103 lines
4.1 KiB
TypeScript
103 lines
4.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { splitIntoSentences, splitTextIntoSentences } from '../../src/matchers/shared';
|
|
|
|
describe('splitIntoSentences', () => {
|
|
it('splits on newlines and drops blank lines', () => {
|
|
expect(splitIntoSentences('a\n\nb\n \nc')).toEqual(['a', 'b', 'c']);
|
|
});
|
|
|
|
it('treats a single prose paragraph as one unit (newline-only behavior)', () => {
|
|
expect(splitIntoSentences('One. Two. Three.')).toEqual(['One. Two. Three.']);
|
|
});
|
|
|
|
it('does not sentence-split a numbered list (markers stay attached to their line)', () => {
|
|
expect(splitIntoSentences('1. Paris is the capital.\n2. France is in Europe.')).toEqual([
|
|
'1. Paris is the capital.',
|
|
'2. France is in Europe.',
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('splitTextIntoSentences', () => {
|
|
it('segments a single prose paragraph on sentence boundaries', () => {
|
|
expect(
|
|
splitTextIntoSentences('Paris is the capital of France. France is in Europe. Nice weather.'),
|
|
).toEqual(['Paris is the capital of France.', 'France is in Europe.', 'Nice weather.']);
|
|
});
|
|
|
|
it('is unaffected by an incidental leading/trailing newline (regression for the prose fix)', () => {
|
|
const expected = ['Paris is the capital of France.', 'France is in Europe.'];
|
|
expect(
|
|
splitTextIntoSentences('Paris is the capital of France. France is in Europe.\n'),
|
|
).toEqual(expected);
|
|
expect(
|
|
splitTextIntoSentences('\nParis is the capital of France. France is in Europe.'),
|
|
).toEqual(expected);
|
|
expect(
|
|
splitTextIntoSentences('Paris is the capital of France. France is in Europe.\r\n'),
|
|
).toEqual(expected);
|
|
});
|
|
|
|
it('splits ! and ? boundaries', () => {
|
|
expect(splitTextIntoSentences('Really? Yes! Absolutely.')).toEqual([
|
|
'Really?',
|
|
'Yes!',
|
|
'Absolutely.',
|
|
]);
|
|
});
|
|
|
|
it('trims leading/trailing whitespace on a single-line prose input before splitting', () => {
|
|
expect(
|
|
splitTextIntoSentences(' Paris is the capital of France. France is in Europe. '),
|
|
).toEqual(['Paris is the capital of France.', 'France is in Europe.']);
|
|
});
|
|
|
|
it('does not split decimals', () => {
|
|
expect(splitTextIntoSentences('Pi is about 3.14 in value. It is irrational.')).toEqual([
|
|
'Pi is about 3.14 in value.',
|
|
'It is irrational.',
|
|
]);
|
|
});
|
|
|
|
it('does not split when a decimal appears at the end of text', () => {
|
|
expect(splitTextIntoSentences('The value is 3.14.')).toEqual(['The value is 3.14.']);
|
|
});
|
|
|
|
it('treats text with two or more non-empty lines as pre-segmented (one unit per line)', () => {
|
|
// No abbreviation mis-splits ("i.e.") and no collapsing of multi-sentence lines.
|
|
expect(splitTextIntoSentences('All employees i.e. engineers.\nThey get leave.')).toEqual([
|
|
'All employees i.e. engineers.',
|
|
'They get leave.',
|
|
]);
|
|
expect(splitTextIntoSentences('Line one.\n\n\nLine two.')).toEqual(['Line one.', 'Line two.']);
|
|
});
|
|
|
|
it('drops bare enumeration markers stranded from an inline numbered list', () => {
|
|
// Sentence-splitting "1. Paris ... 2. France ..." strands the "1." / "2."
|
|
// markers as their own segments; counting them would inflate sentence-level
|
|
// metrics (e.g. the RAGAS context-relevance numerator). Only real units remain.
|
|
expect(splitTextIntoSentences('1. Paris is the capital. 2. France is in Europe.')).toEqual([
|
|
'Paris is the capital.',
|
|
'France is in Europe.',
|
|
]);
|
|
// A `)`-style marker on a sentence boundary is likewise dropped when stranded.
|
|
expect(splitTextIntoSentences('1. First fact. 2. Second fact.')).toEqual([
|
|
'First fact.',
|
|
'Second fact.',
|
|
]);
|
|
});
|
|
|
|
it('keeps numbers that are part of a sentence, not bare markers', () => {
|
|
// A decimal or a number embedded in prose is content, never a stray marker.
|
|
expect(splitTextIntoSentences('Pi is 3.14 here. There are 42 items.')).toEqual([
|
|
'Pi is 3.14 here.',
|
|
'There are 42 items.',
|
|
]);
|
|
});
|
|
|
|
it('returns an empty array for empty or whitespace-only text', () => {
|
|
expect(splitTextIntoSentences('')).toEqual([]);
|
|
expect(splitTextIntoSentences(' \n \n ')).toEqual([]);
|
|
});
|
|
});
|