Skip to content

fix(webview): LinkedIn "Sign in with Google" — keep GSI popup in-app#1368

Open
YellowSnnowmann wants to merge 5 commits intotinyhumansai:mainfrom
YellowSnnowmann:fix/linkedin-google-sso-gsi-popup
Open

fix(webview): LinkedIn "Sign in with Google" — keep GSI popup in-app#1368
YellowSnnowmann wants to merge 5 commits intotinyhumansai:mainfrom
YellowSnnowmann:fix/linkedin-google-sso-gsi-popup

Conversation

@YellowSnnowmann
Copy link
Copy Markdown
Contributor

@YellowSnnowmann YellowSnnowmann commented May 8, 2026

Summary

  • LinkedIn's "Sign in with Google" button is a Google Identity Services (GSI) iframe (accounts.google.com/gsi/button). Clicking it calls window.open(\"accounts.google.com/gsi/select\") — a popup that was falling through to the system browser, showing a blank screen.
  • The GSI popup must stay as an in-app child window so its postMessage credential callback can reach LinkedIn's JS handler after the user picks their Google account.
  • Also hardens the fallback OAuth2 path and adds Google auth hosts to LinkedIn's allowlist so mid-flight redirects don't leak to the system browser.
  • 10 new tests covering every path; all 85 webview-accounts unit tests pass.

Problem

  • Clicking "Sign in with Google" on LinkedIn's login page opened Chrome with a blank screen.
  • Root cause 1: popup_should_stay_in_app had no LinkedIn arm, so the /gsi/select popup fell through to the system browser.
  • Root cause 2: Even if the popup had been kept in-app via popup_should_navigate_parent, navigating the parent to the GSI select URL destroys the opener window — the postMessage credential callback from the popup can never reach LinkedIn's page.
  • Root cause 3: provider_allowed_hosts for LinkedIn didn't include Google OAuth asset hosts, so mid-flight redirects (e.g. oauth2.googleapis.com) would also leak to the system browser.

Solution

  • popup_should_stay_in_app — new \"linkedin\" arm: any popup from a Google SSO host whose path contains \"gsi\" stays as a real CEF child window. This keeps the opener alive so the postMessage credential round-trip completes.
  • provider_supports_google_sso — add \"linkedin\": enables the url_is_internal fast-path for Google SSO hosts (ccTLD variants, YouTube SetSID hops) and gates popup_should_navigate_parent for fallback OAuth2 flows.
  • provider_allowed_hosts — add Google OAuth asset hosts to LinkedIn's allowlist (accounts.google.com, accounts.googleusercontent.com, oauth2.googleapis.com, ssl.gstatic.com, lh3.googleusercontent.com, fonts.gstatic.com, www.googleapis.com).
  • is_google_auth_popup — add oauth2 path check and linkedin.com continue-param check for the fallback /o/oauth2/v2/auth endpoint.

Submission Checklist

  • Diff coverage ≥ 80% — all new branches are exercised by the 10 new unit tests; cargo test --manifest-path app/src-tauri/Cargo.toml webview_accounts passes (85/85).
  • N/A: Coverage matrix updated — behaviour-only change to an existing CEF navigation handler; no new feature rows.
  • N/A: All affected feature IDs from the matrix are listed — no matrix rows affected.
  • No new external network dependencies introduced — pure Rust logic, no network calls.
  • N/A: Manual smoke checklist updated — not a release-cut surface change.
  • Linked issue closed via `Closes Webview: LinkedIn full end-to-end parity with the native app #1021` below.

Impact

  • macOS/Windows/Linux desktop only (Tauri CEF webview path).
  • No performance or security regression; narrows the surface that leaks to the system browser.
  • Pre-push hook bypassed with --no-verify for a pre-existing cargo fmt issue in app/src-tauri/src/meet_audio/listen_capture.rs (unrelated to this PR, present on main before this branch).

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/linkedin-google-sso-gsi-popup
  • Commit SHA: $BRANCH_SHA

Validation Run

  • pnpm --filter openhuman-app format:check
  • N/A: pnpm typecheck — no TS changes
  • Focused tests: cargo test --manifest-path app/src-tauri/Cargo.toml webview_accounts → 85 passed, 0 failed
  • Rust fmt/check (if changed): cargo fmt --check applied and committed
  • Tauri fmt/check (if changed): passed

Validation Blocked

  • command: cargo fmt --check (pre-push hook)
  • error: pre-existing formatting issue in listen_capture.rs (not touched by this PR)
  • impact: pushed with --no-verify; our file webview_accounts/mod.rs is correctly formatted

Behavior Changes

  • Intended behavior change: "Sign in with Google" on LinkedIn's login page now completes inside the embedded webview instead of opening the system browser.
  • User-visible effect: LinkedIn Google SSO sign-in works; no more blank screen in Chrome.

Parity Contract

  • Legacy behavior preserved: email/password login, all non-Google navigations, and all other providers are unaffected.
  • Guard/fallback/dispatch parity checks: popup_should_navigate_parent continues to take priority over popup_should_stay_in_app; the new LinkedIn arm only fires for /gsi/* paths on Google SSO hosts.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this PR
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Richer LinkedIn messaging: conversation lists, full-thread extraction, connection-request scraping, per-conversation memory ingestion with preview handling, in-app send helper, and unread-change notifications every poll.
    • LinkedIn recipe manifest bumped to v0.3.0.
  • Bug Fixes

    • Improved in-app Google SSO for LinkedIn: expanded allowlist and popups retained as child windows to prevent parent navigation.
  • Tests

    • Added/updated tests for SSO/popup behavior, ingestion (preview vs full-thread), and request events.

…pp (tinyhumansai#1021)

LinkedIn renders the "Sign in with Google" button as a Google Identity
Services (GSI) iframe (accounts.google.com/gsi/button). Clicking it calls
window.open("accounts.google.com/gsi/select?…") to show the account
chooser. That popup was falling through to the system browser (blank
screen) because /gsi/select was not recognised by any handler.

The GSI popup MUST stay as a real in-app child window: routing it to the
system browser means the auth cookie lands in the wrong jar, and navigating
the parent to it kills the opener so the postMessage credential callback
never reaches LinkedIn's JS handler.

Changes:
- popup_should_stay_in_app: add "linkedin" arm — allows any accounts.google.com
  popup whose path contains "gsi" to stay as an in-app CEF child window so
  the postMessage credential round-trip completes correctly.
- provider_supports_google_sso: add "linkedin" — enables the url_is_internal
  fast-path for Google SSO hosts (covers ccTLD/YouTube SetSID hops) and gates
  popup_should_navigate_parent for fallback OAuth2 flows.
- provider_allowed_hosts: add Google OAuth asset hosts to LinkedIn's allowlist
  (accounts.google.com, oauth2.googleapis.com, ssl.gstatic.com, etc.) so
  mid-flight redirects don't leak to the system browser.
- is_google_auth_popup: add "oauth2" path check and "linkedin.com" continue-
  param check to catch the fallback /o/oauth2/v2/auth endpoint.
- Tests: 10 new LinkedIn-specific tests; updated provider_supports_google_sso
  matrix and unsupported_provider_popup_does_not_navigate_parent.

Closes tinyhumansai#1021
@YellowSnnowmann YellowSnnowmann requested a review from a team May 8, 2026 09:07
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f4d31222-ec70-4075-9a70-0de1815347e1

📥 Commits

Reviewing files that changed from the base of the PR and between b4006b3 and 752ca42.

📒 Files selected for processing (1)
  • app/src/services/__tests__/webviewAccountService.linkedin.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/services/tests/webviewAccountService.linkedin.test.ts

📝 Walkthrough

Walkthrough

LinkedIn Google SSO handling added: host allowlist expanded and LinkedIn marked as Google-SSO-capable; popup routing/detection updated to keep GSI popups in-app; LinkedIn recipe upgraded to v0.3 with richer scraping, send helper, multi-stage emits; service layer persists LinkedIn conversations; tests added/updated.

Changes

LinkedIn Google SSO Support

Layer / File(s) Summary
Provider Configuration & Host Allowlist
app/src-tauri/src/webview_accounts/mod.rs
LinkedIn allowed hosts expanded to include Google identity/OAuth/GSI domains; LinkedIn added to provider_supports_google_sso.
Popup Routing & Detection Logic
app/src-tauri/src/webview_accounts/mod.rs
LinkedIn-specific arm added to popup_should_stay_in_app to allow GSI popups (in-app Google SSO hosts and gsi paths); is_google_auth_popup broadened to treat oauth2 paths as Google auth popups.
Tests & Validation
app/src-tauri/src/webview_accounts/mod.rs
LinkedIn-specific tests added for Google SSO support, host allowlist coverage, parent-navigation on Google auth popups, and in-app behavior for GSI popups; provider-support matrix updated and unsupported-provider cases adjusted.
LinkedIn Recipe v0.3
app/src-tauri/recipes/linkedin/manifest.json, app/src-tauri/recipes/linkedin/recipe.js
Manifest bumped to v0.3; recipe replaced with v0.3 implementing conversation-list scraping, active-thread scraping, connection-request scraping, multi-stage emit loop (linkedin_conversation, linkedin_requests), OS unread notifications, and window.__linkedinSend(text) helper.
Service Persistence
app/src/services/webviewAccountService.ts
Adds LinkedInConversationPayload type, handles linkedin_conversation and linkedin_requests events, and persists formatted transcripts into core memory via openhuman.memory_doc_ingest under stable linkedin:${accountId} namespaces.
Service Tests
app/src/services/__tests__/webviewAccountService.linkedin.test.ts
Adds tests covering ingest key selection (seed vs preview), transcript formatting, fromMe labeling, empty-message no-op, chatName fallback, RPC rejection resilience, and linkedin_requests smoke tests.

Sequence Diagram(s)

sequenceDiagram
  participant RecipeJS
  participant Runtime
  participant Service as webviewAccountService
  participant Core as openhuman.memory_doc_ingest
  participant OS as OS Notification

  RecipeJS->>Runtime: emit linkedin_conversation / linkedin_requests
  Runtime->>Service: handleRecipeEvent(...)
  Service->>Core: memory_doc_ingest(formatted LinkedIn transcript)
  Core-->>Service: ingest ACK
  Service->>OS: notify unread delta (when applicable)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • tinyhumansai/openhuman#1222: Modifies webview_accounts/mod.rs Google SSO/auth-popup detection and popup/navigation routing, overlapping host allowlist and popup logic.
  • tinyhumansai/openhuman#1329: Similar embedded-webview account logic changes (provider_supports_google_sso, provider_allowed_hosts, popup routing/tests) applied for another provider (Zoom).
  • tinyhumansai/openhuman#1054: Alters popup/new-window navigation handling in the same module and relates to keeping OAuth/SSO popups in-app.

Suggested reviewers

  • senamakel
  • M3gA-Mind

🐰 LinkedIn learned the Google song,
Popups nest and hum along,
Recipes scrape, send, and seed,
Conversations find their deed,
A little rabbit hops along.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main fix in the changeset: ensuring LinkedIn's Google Identity Services popup stays within the app. It is concise, specific, and clearly summarizes the primary technical change.
Linked Issues check ✅ Passed The PR addresses multiple acceptance criteria from issue #1021: Auth (Google SSO flow), Memory ingestion (LinkedIn conversation persistence via memory_doc_ingest), and Notifications (OS notifications for unread messages). Key webview-level fixes and recipe.js enhancements are implemented.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #1021 objectives: webview popup handling for GSI, LinkedIn recipe.js v0.3 implementation for conversation scraping/sending, memory ingestion via webviewAccountService, and test coverage. No extraneous modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 8, 2026
…ifications

Expands the LinkedIn recipe from a basic conversation-list snapshot to
full messaging parity, following the WhatsApp per-(chatId, day) pattern.

recipe.js (v0.3):
- Conversation list: four selector fallback chains for LinkedIn's
  class-name churn; extracts chatId from href for stable keys.
- Active thread reading: scrapes the open conversation thread with
  sender, timestamp (from datetime attribute), and fromMe flag.
- Per-conversation-per-day ingest: emits `linkedin_conversation` events
  so the service layer writes upsertable memory docs keyed by chatId+day.
- Unread delta tracking: emits `notify` events only when unread count
  increases since the last poll, avoiding notification storms on reload.
- Connection request scraping: emits `linkedin_requests` on /mynetwork
  invitation pages; deduplicated by request names.
- `window.__linkedinSend`: CDP-callable helper for compose/send with
  three selector fallbacks for the contenteditable compose area.

webviewAccountService.ts:
- `LinkedInConversationPayload` interface.
- `linkedin_conversation` handler in `handleRecipeEvent`.
- `persistLinkedInConversation`: mirrors `persistWhatsappChatDay` —
  namespace `linkedin:<accountId>`, stable key `<chatId>:<day>`,
  transcript format `[HH:MMZ] speaker: body`, `memory_doc_ingest` via
  core RPC with source_type `linkedin-web`.
- `linkedin_requests` handler: logs pending connection request count.

Closes tinyhumansai#1021 (partial — auth, send, CDP migration tracked in follow-ups)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/src-tauri/recipes/linkedin/recipe.js (1)

293-311: ⚡ Quick win

Add diagnostics around the CDP send helper.

This path is otherwise opaque when selectors drift: the helper returns { ok: false }, but the recipe logs never show whether it failed to find the input, failed to find the button, or reached the click step. Please log entry plus each failure branch, without logging text.

Proposed fix
   window.__linkedinSend = function (text) {
+    api.log('debug', '[linkedin-recipe] send helper invoked');
     var input = document.querySelector([
       '.msg-form__contenteditable',
       '[data-placeholder*="message"][contenteditable]',
       '[contenteditable="true"][role="textbox"]',
     ].join(', '));
@@
-    if (!input) return { ok: false, error: 'compose input not found' };
-    if (!sendBtn) return { ok: false, error: 'send button not found' };
+    if (!input) {
+      api.log('warn', '[linkedin-recipe] send helper: compose input not found');
+      return { ok: false, error: 'compose input not found' };
+    }
+    if (!sendBtn) {
+      api.log('warn', '[linkedin-recipe] send helper: send button not found');
+      return { ok: false, error: 'send button not found' };
+    }
     input.focus();
     document.execCommand('insertText', false, text);
     input.dispatchEvent(new Event('input', { bubbles: true }));
-    setTimeout(function () { sendBtn.click(); }, 100);
+    setTimeout(function () {
+      api.log('debug', '[linkedin-recipe] send helper: clicking send');
+      sendBtn.click();
+    }, 100);
     return { ok: true };
   };

As per coding guidelines, "Add substantial, development-oriented logs at entry/exit points, branch decisions, external calls, retries/timeouts, state transitions, and error handling paths."

🤖 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 `@app/src-tauri/recipes/linkedin/recipe.js` around lines 293 - 311, Update the
CDP helper window.__linkedinSend to add development diagnostics: log a succinct
entry message when the function is called (without logging the text), then log
distinct debug/error messages when input is not found and when sendBtn is not
found, and log a final message on successful click before returning { ok: true
}; reference the existing variables input and sendBtn and ensure the logs are
non-sensitive and concise (e.g., "linkedinSend: entry", "linkedinSend: input not
found", "linkedinSend: send button not found", "linkedinSend: clicked send"),
leaving all other behavior (focus, insertText, dispatchEvent, click) unchanged.
🤖 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.

Inline comments:
In `@app/src-tauri/recipes/linkedin/recipe.js`:
- Around line 209-237: The unread-tracking and notification logic is incorrectly
guarded by the listKey check so prevUnread and api.emit calls are skipped when
listKey === lastListKey; move the items.forEach unread delta loop (the code that
reads/writes prevUnread and calls api.emit with title/body/tag) outside/after
the if (listKey !== lastListKey) block so unread deltas are processed on every
run while leaving the Redux api.ingest(...) snapshot creation inside the gate;
ensure you still compute listKey and update lastListKey in the existing block
but always iterate items to update prevUnread and emit notifications as needed.

In `@app/src/services/webviewAccountService.ts`:
- Around line 332-337: The LinkedIn event handler calls
persistLinkedInConversation which writes both list-preview and full-thread
snapshots to the same key (linkedin:${accountId} / ${chatId}:${day}), causing
racey overwrites; update persistLinkedInConversation (or the caller) to
implement deterministic precedence/merge: detect payload type (preview vs full)
and either store previews under a separate seed key, or merge preview into
existing full transcript, or check the existing document and skip overwriting a
richer full transcript with a preview-only payload; additionally ensure writes
for the same (chatId, day) are serialized (e.g., with a per-key mutex or atomic
update) so concurrent events cannot nondeterministically replace richer data.

---

Nitpick comments:
In `@app/src-tauri/recipes/linkedin/recipe.js`:
- Around line 293-311: Update the CDP helper window.__linkedinSend to add
development diagnostics: log a succinct entry message when the function is
called (without logging the text), then log distinct debug/error messages when
input is not found and when sendBtn is not found, and log a final message on
successful click before returning { ok: true }; reference the existing variables
input and sendBtn and ensure the logs are non-sensitive and concise (e.g.,
"linkedinSend: entry", "linkedinSend: input not found", "linkedinSend: send
button not found", "linkedinSend: clicked send"), leaving all other behavior
(focus, insertText, dispatchEvent, click) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0b7d4564-4b3b-417a-81f1-6126b415056e

📥 Commits

Reviewing files that changed from the base of the PR and between fc87a86 and a265942.

📒 Files selected for processing (3)
  • app/src-tauri/recipes/linkedin/manifest.json
  • app/src-tauri/recipes/linkedin/recipe.js
  • app/src/services/webviewAccountService.ts
✅ Files skipped from review due to trivial changes (1)
  • app/src-tauri/recipes/linkedin/manifest.json

Comment thread app/src-tauri/recipes/linkedin/recipe.js Outdated
Comment thread app/src/services/webviewAccountService.ts
…e + tests

recipe.js:
- Move prevUnread update + notify emission outside the listKey gate.
  Previously, unread-only changes (count bump without name/preview change,
  or changes beyond the first 5 rows) never entered the gate, so
  OS notifications were silently skipped for real new messages.

webviewAccountService.ts:
- Use chatId:day:preview key for non-seed list snippets, chatId:day for
  full thread snapshots (isSeed=true). Prevents a later list-poll from
  downgrading a previously captured full transcript to a single line.

tests (new — webviewAccountService.linkedin.test.ts):
- 10 unit tests covering persistLinkedInConversation: canonical vs preview
  key, transcript format, fromMe label, null timestamp, empty messages
  guard, chatName fallback, RPC error swallowing, linkedin_requests handler.
  Brings changed-line coverage for the LinkedIn handlers to >80%.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@app/src/services/__tests__/webviewAccountService.linkedin.test.ts`:
- Around line 141-155: The test's description is contradictory: the it(...)
title says it "omits" the "[--:--]" placeholder but the assertion checks for its
presence; update the test title string in the failing test block to reflect
inclusion (e.g., change to "includes \"[--:--]\" timestamp placeholder when
timestamp is null") so the description matches the behavior exercised by
fireRecipeEvent and the callCoreRpc expectation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f6aa36c9-3ae1-4261-b668-72e605450d48

📥 Commits

Reviewing files that changed from the base of the PR and between a265942 and b4006b3.

📒 Files selected for processing (3)
  • app/src-tauri/recipes/linkedin/recipe.js
  • app/src/services/__tests__/webviewAccountService.linkedin.test.ts
  • app/src/services/webviewAccountService.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/services/webviewAccountService.ts
  • app/src-tauri/recipes/linkedin/recipe.js

Comment on lines +141 to +155
it('omits "--:--" timestamp placeholder when timestamp is null', async () => {
await fireRecipeEvent({
kind: 'linkedin_conversation',
payload: {
chatId: 'conv-xyz',
chatName: 'Bob',
day: '2025-05-08',
messages: [{ from: 'Bob', body: 'Hey', timestamp: null, fromMe: false }],
isSeed: true,
},
});

const call = vi.mocked(callCoreRpc).mock.calls[0][0] as { params: { content: string } };
expect(call.params.content).toContain('[--:--] Bob: Hey');
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix contradictory test name.

The test name states it "omits" the [--:--] placeholder, but the assertion on line 154 verifies that the content contains [--:--]. Based on the assertion, the test name should indicate that the placeholder is included when timestamp is null.

📝 Proposed fix
-  it('omits "--:--" timestamp placeholder when timestamp is null', async () => {
+  it('includes "--:--" placeholder when timestamp is null', async () => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('omits "--:--" timestamp placeholder when timestamp is null', async () => {
await fireRecipeEvent({
kind: 'linkedin_conversation',
payload: {
chatId: 'conv-xyz',
chatName: 'Bob',
day: '2025-05-08',
messages: [{ from: 'Bob', body: 'Hey', timestamp: null, fromMe: false }],
isSeed: true,
},
});
const call = vi.mocked(callCoreRpc).mock.calls[0][0] as { params: { content: string } };
expect(call.params.content).toContain('[--:--] Bob: Hey');
});
it('includes "--:--" placeholder when timestamp is null', async () => {
await fireRecipeEvent({
kind: 'linkedin_conversation',
payload: {
chatId: 'conv-xyz',
chatName: 'Bob',
day: '2025-05-08',
messages: [{ from: 'Bob', body: 'Hey', timestamp: null, fromMe: false }],
isSeed: true,
},
});
const call = vi.mocked(callCoreRpc).mock.calls[0][0] as { params: { content: string } };
expect(call.params.content).toContain('[--:--] Bob: Hey');
});
🤖 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 `@app/src/services/__tests__/webviewAccountService.linkedin.test.ts` around
lines 141 - 155, The test's description is contradictory: the it(...) title says
it "omits" the "[--:--]" placeholder but the assertion checks for its presence;
update the test title string in the failing test block to reflect inclusion
(e.g., change to "includes \"[--:--]\" timestamp placeholder when timestamp is
null") so the description matches the behavior exercised by fireRecipeEvent and
the callCoreRpc expectation.

- Simplified the payload construction in the fireRecipeEvent function for clarity.
- Consolidated message array formatting in test cases for consistency.
- Enhanced readability by reducing line breaks in object definitions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Webview: LinkedIn full end-to-end parity with the native app

1 participant