feat(frontend): add extractNumber helper
This commit is contained in:
@@ -218,3 +218,15 @@ export function runAnalysis(rows, timestampCol, noteCol, classifications) {
|
|||||||
consecutiveStats,
|
consecutiveStats,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Numeric extraction (for numerical buckets) ────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the first signed decimal from a string. Returns null if none found.
|
||||||
|
* Examples: "L25.5" -> 25.5, "R-12" -> -12, "abc" -> null
|
||||||
|
*/
|
||||||
|
export function extractNumber(str) {
|
||||||
|
if (str == null) return null;
|
||||||
|
const m = String(str).match(/-?\d+(\.\d+)?/);
|
||||||
|
return m ? parseFloat(m[0]) : null;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
parseCSV,
|
parseCSV,
|
||||||
getUniqueNoteValues,
|
getUniqueNoteValues,
|
||||||
runAnalysis,
|
runAnalysis,
|
||||||
|
extractNumber,
|
||||||
} from '../src/lib/csvAnalysis';
|
} from '../src/lib/csvAnalysis';
|
||||||
|
|
||||||
// ── Fixtures ───────────────────────────────────────────────────────────────────
|
// ── Fixtures ───────────────────────────────────────────────────────────────────
|
||||||
@@ -276,3 +277,32 @@ describe('runAnalysis — edge cases', () => {
|
|||||||
expect(result.consecutiveStats['Failure'].totalRuns).toBe(1);
|
expect(result.consecutiveStats['Failure'].totalRuns).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('extractNumber', () => {
|
||||||
|
test('extracts positive decimal from prefixed string', () => {
|
||||||
|
expect(extractNumber('L25.5')).toBe(25.5);
|
||||||
|
});
|
||||||
|
test('extracts negative integer with letter prefix', () => {
|
||||||
|
expect(extractNumber('R-12')).toBe(-12);
|
||||||
|
});
|
||||||
|
test('extracts integer from underscore-separated label', () => {
|
||||||
|
expect(extractNumber('trial_007')).toBe(7);
|
||||||
|
});
|
||||||
|
test('does not parse scientific notation as one number', () => {
|
||||||
|
// Accepted limitation: regex matches "3.2", strips "e2"
|
||||||
|
expect(extractNumber('3.2e2')).toBe(3.2);
|
||||||
|
});
|
||||||
|
test('strips trailing units', () => {
|
||||||
|
expect(extractNumber('42 ms')).toBe(42);
|
||||||
|
});
|
||||||
|
test('returns null for purely alphabetic string', () => {
|
||||||
|
expect(extractNumber('abc')).toBeNull();
|
||||||
|
});
|
||||||
|
test('returns null for empty string', () => {
|
||||||
|
expect(extractNumber('')).toBeNull();
|
||||||
|
});
|
||||||
|
test('returns null for null/undefined', () => {
|
||||||
|
expect(extractNumber(null)).toBeNull();
|
||||||
|
expect(extractNumber(undefined)).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user