Files
study-bible-project/src/utils/ownWork.test.js
T
nmemmertandClaude Sonnet 5.5 0c8a632cff Add own-work tracking, Claude hand-off check, and weekly recall
- Long pastes into Observe/Interpret/Apply are tagged as pasted; notes show
  Mine / N pasted and an own-words share. Pastes follow text through merges.
- The "-> Claude" buttons on the Script stage ask first when a chunk lacks
  enough of the user's own (non-pasted) words.
- Weekly recall card on Home: write a passage from memory, compare with notes,
  self-rate; recalls are saved on the chunk and synced.
- Recall history on Home with an eight-week strip and the full list.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 12:25:49 -04:00

59 lines
2.7 KiB
JavaScript

import { test, expect } from 'vitest';
import { thinFields, chunksNeedingWork } from './ownWork.js';
const text = (n) => Array.from({ length: n }, (_, i) => `w${i}`).join(' ');
test('a field counts as done once it reaches its minimum word count', () => {
const chunk = { observation: text(20), interpretation: text(19), application: text(10) };
expect(thinFields(chunk).map((f) => f.field)).toEqual(['interpretation']);
});
test('empty or missing notes are all flagged', () => {
expect(thinFields({}).map((f) => f.label)).toEqual(['Observe', 'Interpret', 'Apply']);
expect(thinFields(null)).toHaveLength(3);
});
test('only chunks with something missing are returned', () => {
const done = { id: 'a', observation: text(25), interpretation: text(25), application: text(12) };
const thin = { id: 'b', observation: text(25), interpretation: '', application: text(12) };
const result = chunksNeedingWork([done, thin]);
expect(result.map((r) => r.chunk.id)).toEqual(['b']);
expect(result[0].missing[0]).toMatchObject({ label: 'Interpret', have: 0, need: 20 });
});
import { withPaste, pastedWords, ownWords, ownShare, clearPastes } from './ownWork.js';
import { mergeChunk } from './mergeStudies.js';
test('only long pastes are remembered', () => {
expect(withPaste({}, 'observation', text(5))).toBeNull();
expect(withPaste({}, 'observation', text(15))).toEqual({ observation: [text(15)] });
});
test('pasted text stops counting once it is removed from the note', () => {
const pasted = text(30);
const chunk = { observation: `my own thought ${pasted}`, aiPastes: { observation: [pasted] } };
expect(pastedWords(chunk, 'observation')).toBe(30);
expect(ownWords(chunk, 'observation')).toBe(3);
expect(ownWords({ ...chunk, observation: 'now I wrote this myself' }, 'observation')).toBe(5);
});
test('pasted words do not satisfy the own-work minimum', () => {
const pasted = text(40);
const chunk = { observation: pasted, interpretation: text(25), application: text(12), aiPastes: { observation: [pasted] } };
expect(thinFields(chunk).map((f) => f.field)).toEqual(['observation']);
});
test('the own-words share and "That\'s mine"', () => {
const pasted = text(30);
const chunk = { observation: `${text(10)} ${pasted}`, aiPastes: { observation: [pasted] } };
expect(ownShare(chunk)).toBe(25);
expect(ownShare({})).toBeNull();
expect(ownShare({ ...chunk, aiPastes: clearPastes(chunk, 'observation') })).toBe(100);
});
test('merging two copies keeps the pastes from both', () => {
const a = { id: 'x', observation: 'a', editedAt: 2, aiPastes: { observation: ['p1'] } };
const b = { id: 'x', observation: 'b', editedAt: 1, aiPastes: { observation: ['p2'] } };
expect(mergeChunk(a, b).chunk.aiPastes.observation).toEqual(['p1', 'p2']);
});