Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2025-12-26 20:31 UTC - Provider contract VCR replay tests
- Files: tests/contracts/provider.contract.test.ts; tests/contracts/vcr/loadCassette.ts; tests/contracts/vcr/types.ts; tests/contracts/cassettes/*.json; docs/WORKLOG.md
- Why: Provider contract tests were a skipped scaffold; we need deterministic replay tests to validate real adapter behavior without network calls and without placeholder assertions.
- Details: Adds replay-only VCR cassettes that drive real `OpenAIAdapter.translate()` and `GeminiAdapter.translate()` while mocking only provider SDK boundaries; asserts JSON parsing, token accounting, cost wiring, and OpenAI metrics recording.
- Tests: `npm test`

2025-12-24 11:23 UTC - Migration recovery UI gate
- Files: App.tsx; components/MigrationRecovery.tsx; tests/components/MigrationRecovery.test.tsx; docs/WORKLOG.md
- Why: When the DB is newer/corrupted/blocked or a migration failed, users need a clear recovery path (restore from backup, upload backup, or start fresh) instead of a silent failure.
Expand Down
24 changes: 24 additions & 0 deletions tests/contracts/cassettes/gemini-happy-path.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "gemini-happy-path",
"provider": "Gemini",
"model": "gemini-2.5-flash",
"request": {
"title": "Test Title",
"content": "今天天气很好。",
"systemPrompt": "Translate this Chinese text to English.",
"temperature": 0.3,
"maxOutputTokens": 512
},
"mock": {
"responseText": "{\"translatedTitle\":\"Test Title\",\"translation\":\"The weather is very good today.\",\"footnotes\":[],\"suggestedIllustrations\":[],\"proposal\":null}",
"usageMetadata": { "promptTokenCount": 14, "candidatesTokenCount": 9 }
},
"expected": {
"translatedTitle": "Test Title",
"translation": "The weather is very good today.",
"promptTokens": 14,
"completionTokens": 9,
"estimatedCost": 0.000008
}
}

33 changes: 33 additions & 0 deletions tests/contracts/cassettes/openai-happy-path.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "openai-happy-path",
"provider": "OpenAI",
"model": "gpt-4o-mini",
"request": {
"title": "Test Title",
"content": "今天天气很好。",
"systemPrompt": "Translate this Chinese text to English.",
"temperature": 0.3,
"maxOutputTokens": 512
},
"mock": {
"sdkResponse": {
"choices": [
{
"finish_reason": "stop",
"message": {
"content": "{\"translatedTitle\":\"Test Title\",\"translation\":\"The weather is very nice today.\",\"footnotes\":[],\"suggestedIllustrations\":[]}"
}
}
],
"usage": { "prompt_tokens": 15, "completion_tokens": 8 }
}
},
"expected": {
"translatedTitle": "Test Title",
"translation": "The weather is very nice today.",
"promptTokens": 15,
"completionTokens": 8,
"estimatedCost": 0.00003
}
}

33 changes: 33 additions & 0 deletions tests/contracts/cassettes/openai-medium-chapter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "openai-medium-chapter",
"provider": "OpenAI",
"model": "gpt-4o-mini",
"request": {
"title": "Chapter 1",
"content": "그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다. 그날 하늘은 맑았다.",
"systemPrompt": "Translate this Korean web novel chapter to English.",
"temperature": 0.7,
"maxOutputTokens": 2048
},
"mock": {
"sdkResponse": {
"choices": [
{
"finish_reason": "stop",
"message": {
"content": "{\"translatedTitle\":\"Chapter 1\",\"translation\":\"That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear.\",\"footnotes\":[],\"suggestedIllustrations\":[]}"
}
}
],
"usage": { "prompt_tokens": 1000, "completion_tokens": 850 }
}
},
"expected": {
"translatedTitle": "Chapter 1",
"translation": "That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear. That day, the sky was clear.",
"promptTokens": 1000,
"completionTokens": 850,
"estimatedCost": 0.00092
}
}

Loading
Loading