feat: manual source URL intake (landing UI + server intake)#38
Conversation
ウォークスルーこのプルリクエストは、ユーザーがランディングページで任意のソースURLを提供できるようにする「手動ソースURL取り込み」機能を実装しています。URLは解析・検証・正規化・重複排除され、発見されたソースよりも優先されます。また、手動URLが存在する場合はラン キャッシュロックアップをバイパスします。 変更内容手動ソースURL取り込み機能
🎯 3 (中程度) | ⏱️ ~25分関連する可能性があるプルリクエスト
詩
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/features/landing/components/question-intake.tsx (1)
62-74: ⚡ Quick winアクセシビリティ: ヘルパーテキストが textarea に紐づいていない
ヘルパーテキスト(Lines 62–64 の
<p>)がaria-describedbyでテキストエリアに関連付けられていないため、スクリーンリーダーがこの説明を入力フィールドと対応付けられません。♿ 修正案
- <p className="muted" style={{ marginTop: "0.25rem", marginBottom: "0.5rem" }}> + <p id="source-urls-hint" className="muted" style={{ marginTop: "0.25rem", marginBottom: "0.5rem" }}> Add one URL per line. TraceMap will prioritize these sources when building the evidence map. </p> <textarea id="sourceUrls" name="sourceUrls" + aria-describedby="source-urls-hint" placeholder={`https://example.com/official-report🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/features/landing/components/question-intake.tsx` around lines 62 - 74, ヘルパーテキストの<p>(現在の説明文)をテキストエリアに関連付けるために、説明要素に一意のIDを追加(例: "sourceUrlsHelp")し、textarea(id="sourceUrls", data-testid="manual-source-urls-input")に aria-describedby="sourceUrlsHelp" を追加してスクリーンリーダーが説明を読み上げられるようにしてください(必要なら説明要素を <p> のままにするか、役割を明示するために <div role="note"> に変更しても可)。src/app/actions/manual-source-urls.ts (1)
22-25: 💤 Low valueエラー時にどの URL が無効か特定できない
normalizeSourceUrlが失敗した場合、汎用メッセージを返すため、複数 URL を入力しているユーザーが問題箇所を特定できません。例えば、エラーメッセージに無効な行の内容や行番号を含めることで UX を改善できます。- if (normalized.kind !== "ok") { - return { kind: "error", message: MANUAL_SOURCE_URLS_ERROR_MESSAGE }; - } + if (normalized.kind !== "ok") { + return { kind: "error", message: `${MANUAL_SOURCE_URLS_ERROR_MESSAGE} (入力値: "${line}")` }; + }ただし、エラーメッセージを定数として export している都合上、定数と動的メッセージを分ける設計変更が必要になる点に注意してください。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/actions/manual-source-urls.ts` around lines 22 - 25, When normalizeSourceUrl(line) returns an error, replace the opaque return using MANUAL_SOURCE_URLS_ERROR_MESSAGE with a dynamic error that includes which input failed (e.g., the line content and/or line index) and any normalized error detail; keep the exported MANUAL_SOURCE_URLS_ERROR_MESSAGE as the stable constant and compose a new message at the call site (in the code handling normalizeSourceUrl inside manual-source-urls.ts) such as combining the constant with `line` and the line number or normalized.error info so users can identify the invalid URL.tests/manual-source-urls.test.ts (1)
8-34: ⚡ Quick winテストカバレッジ: いくつかのエッジケースが未検証
以下のケースがテストされておらず、ドキュメントとしての価値を高める余地があります。
- Windows 改行 (
\r\n):split(/\r?\n/)で処理されていますが、テストがありません。- URL 間の空白行: 複数の空行を挟んだ入力でも正しく動作するか未検証。
Fileオブジェクト入力:FormDataEntryValueはstring | Fileであり、Fileが渡された場合に空リストが返ることを明示するテストがあると、意図した動作として文書化されます。✅ 追加テスト案
+ it("handles windows line endings", () => { + const result = parseManualSourceUrls("https://example.com/a\r\nhttps://example.com/b"); + expect(result).toEqual({ kind: "ok", manualSourceUrls: ["https://example.com/a", "https://example.com/b"] }); + }); + + it("ignores blank lines between valid urls", () => { + const result = parseManualSourceUrls("https://example.com/a\n\nhttps://example.com/b"); + expect(result).toEqual({ kind: "ok", manualSourceUrls: ["https://example.com/a", "https://example.com/b"] }); + }); + + it("returns empty list when a File is passed", () => { + const file = new File(["content"], "file.txt"); + expect(parseManualSourceUrls(file)).toEqual({ kind: "ok", manualSourceUrls: [] }); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/manual-source-urls.test.ts` around lines 8 - 34, Add tests to cover the missing edge cases for parseManualSourceUrls: (1) a Windows newline case using "\r\n" to ensure split(/\r?\n/) handles CRLF, (2) input containing multiple blank lines between URLs to ensure empty lines are ignored and deduplication still works, and (3) passing a File (simulate FormDataEntryValue as a File-like value) to confirm parseManualSourceUrls returns { kind: "ok", manualSourceUrls: [] } for non-string inputs; use the existing test structure and assertions (check result.kind and manualSourceUrls or equality with MANUAL_SOURCE_URLS_ERROR_MESSAGE where appropriate) to keep behavior documented.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/app/actions/manual-source-urls.ts`:
- Around line 22-25: When normalizeSourceUrl(line) returns an error, replace the
opaque return using MANUAL_SOURCE_URLS_ERROR_MESSAGE with a dynamic error that
includes which input failed (e.g., the line content and/or line index) and any
normalized error detail; keep the exported MANUAL_SOURCE_URLS_ERROR_MESSAGE as
the stable constant and compose a new message at the call site (in the code
handling normalizeSourceUrl inside manual-source-urls.ts) such as combining the
constant with `line` and the line number or normalized.error info so users can
identify the invalid URL.
In `@src/features/landing/components/question-intake.tsx`:
- Around line 62-74: ヘルパーテキストの<p>(現在の説明文)をテキストエリアに関連付けるために、説明要素に一意のIDを追加(例:
"sourceUrlsHelp")し、textarea(id="sourceUrls",
data-testid="manual-source-urls-input")に aria-describedby="sourceUrlsHelp"
を追加してスクリーンリーダーが説明を読み上げられるようにしてください(必要なら説明要素を <p> のままにするか、役割を明示するために <div
role="note"> に変更しても可)。
In `@tests/manual-source-urls.test.ts`:
- Around line 8-34: Add tests to cover the missing edge cases for
parseManualSourceUrls: (1) a Windows newline case using "\r\n" to ensure
split(/\r?\n/) handles CRLF, (2) input containing multiple blank lines between
URLs to ensure empty lines are ignored and deduplication still works, and (3)
passing a File (simulate FormDataEntryValue as a File-like value) to confirm
parseManualSourceUrls returns { kind: "ok", manualSourceUrls: [] } for
non-string inputs; use the existing test structure and assertions (check
result.kind and manualSourceUrls or equality with
MANUAL_SOURCE_URLS_ERROR_MESSAGE where appropriate) to keep behavior documented.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1e23bdbf-1df9-4349-8ec7-71cbb24f1e80
📒 Files selected for processing (13)
acceptance/README.mdacceptance/manual-source-url-intake.featuree2e/home.spec.tsspecs/README.mdspecs/manual-source-url-intake.mdsrc/app/actions/create-run.tssrc/app/actions/manual-source-urls.tssrc/features/landing/components/question-intake.tsxsrc/server/analysis/create-analysis-run-from-provider.tssrc/server/analysis/source-intake/source-intake-service.tssrc/types/source-intake.tstests/manual-source-urls.test.tstests/source-intake-integration.test.ts
Motivation
Description
specs/manual-source-url-intake.mdand register it inspecs/README.mddescribing scope, UI, server action, intake, cache, and test requirements.acceptance/manual-source-url-intake.featureand register it inacceptance/README.md.Optional source URLstextarea to the landing intake form (src/features/landing/components/question-intake.tsx) with `name=Codex Task
Summary by CodeRabbit
リリースノート
新機能
テスト
ドキュメント