mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 10:27:33 +00:00
test: remove 4 low-value suites and narrow notification store cases from combined audit (#42677)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -1610,7 +1610,6 @@
|
||||
"src/main/ipc/mobile.test.ts": 1861,
|
||||
"src/main/ipc/notebook-project-link.test.ts": 548,
|
||||
"src/main/ipc/notifications-message-formatting.test.ts": 229,
|
||||
"src/main/ipc/notifications-subject-retirement.test.ts": 304,
|
||||
"src/main/ipc/profiles/orca-profiles-switch-persistence.test.ts": 2761,
|
||||
"src/main/ipc/filesystem/watcher-process/supervision/parcel-watcher-crash-fuse-recovery.test.ts": 128,
|
||||
"src/main/ipc/pets/pet-bundle.test.ts": 48,
|
||||
@@ -2641,7 +2640,6 @@
|
||||
"src/main/runtime/rpc/methods/native-chat/native-chat-opencode-semantic-pages.test.ts": 540,
|
||||
"src/main/runtime/rpc/methods/native-chat/native-chat-subscription-token.test.ts": 130,
|
||||
"src/main/runtime/rpc/methods/native-chat/native-chat.test.ts": 170,
|
||||
"src/main/runtime/rpc/methods/notifications/notification-preferences.test.ts": 228,
|
||||
"src/main/runtime/rpc/methods/notifications/notification-reconnect-cooldown.test.ts": 192,
|
||||
"src/main/runtime/rpc/methods/orcad/orcad-migration.test.ts": 3037,
|
||||
"src/main/runtime/rpc/methods/orcad/orcad-terminal-census.test.ts": 104,
|
||||
@@ -4952,7 +4950,6 @@
|
||||
"src/shared/plugins/frames/plugin-frame-document.test.ts": 426,
|
||||
"src/shared/plugins/frames/plugin-panel-call-admission.test.ts": 89,
|
||||
"src/shared/plugins/frames/plugin-panel-shell.test.ts": 376,
|
||||
"src/shared/plugins/images/plugin-image-format.test.ts": 104,
|
||||
"src/shared/plugins/images/plugin-image-url.test.ts": 42,
|
||||
"src/shared/plugins/manifest/plugin-display-text.test.ts": 285,
|
||||
"src/shared/plugins/manifest/plugin-manifest-v2-rules.test.ts": 239,
|
||||
@@ -5206,7 +5203,6 @@
|
||||
"src/shared/workspace-layout/client-views/workspace-layout-views.test.ts": 183,
|
||||
"src/shared/workspace-layout/editor-tabs/workspace-layout-workspace-move.test.ts": 181,
|
||||
"src/shared/workspace-attachments/workspace-linked-item-source-context.test.ts": 65,
|
||||
"src/shared/workspace-name.test.ts": 49,
|
||||
"src/shared/workspace-attachments/workspace-reference-identity.test.ts": 82,
|
||||
"src/shared/workspace-review-checks.test.ts": 82,
|
||||
"src/shared/workspace-session/workspace-session-salvage.test.ts": 930,
|
||||
|
||||
@@ -131,7 +131,6 @@ const NODE_RUNTIME_INCLUDE = [
|
||||
'tests/e2e/helpers/persisted-profile-state.unit.test.ts',
|
||||
'src/main/runtime/push/notifications/mobile-notification-dismissal-store.test.ts',
|
||||
'src/main/runtime/push/notifications/mobile-notification-dismissal-read-failure.test.ts',
|
||||
'src/main/ipc/notifications-subject-retirement.test.ts',
|
||||
'src/main/ipc/notifications-external-acknowledgement.test.ts'
|
||||
]
|
||||
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { mkdtempSync, rmSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import {
|
||||
RuntimeMobileNotificationController,
|
||||
type MobileNotificationDispatchEvent,
|
||||
type MobileNotificationEvent
|
||||
} from '../runtime/push/notifications/runtime-mobile-notification-controller'
|
||||
import type { StructuredAttentionState } from '../../shared/agent-session/agent-session-attention'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { getDismissHandler, resetNotificationDispatchMocks } from './notifications-test-harness'
|
||||
|
||||
vi.mock('electron', async () =>
|
||||
(await import('./notifications-test-harness')).createElectronModuleMock()
|
||||
)
|
||||
|
||||
vi.mock('./notification-authorization-status', async () =>
|
||||
(await import('./notifications-test-harness')).createNotificationAuthorizationModuleMock()
|
||||
)
|
||||
|
||||
vi.mock('./ui', async () =>
|
||||
(await import('./notifications-test-harness')).createTrustedUIRendererModuleMock()
|
||||
)
|
||||
|
||||
vi.mock('../tray/system-tray', async () =>
|
||||
(await import('./notifications-test-harness')).createSystemTrayModuleMock()
|
||||
)
|
||||
|
||||
import { registerNotificationHandlers } from './notifications'
|
||||
|
||||
const PANE = 'tab-1:11111111-1111-4111-8111-111111111111'
|
||||
|
||||
function register(
|
||||
options: { suppressWhenFocused: boolean },
|
||||
controller?: RuntimeMobileNotificationController
|
||||
): {
|
||||
dispatchMobileNotification: ReturnType<typeof vi.fn>
|
||||
dismissMobileNotification: ReturnType<typeof vi.fn>
|
||||
} {
|
||||
const dispatchMobileNotification = vi.fn((event: MobileNotificationDispatchEvent) =>
|
||||
controller?.dispatch(event)
|
||||
)
|
||||
const dismissMobileNotification = vi.fn((id: string) => controller?.dismiss(id))
|
||||
const reconcileStructuredPromptAttention = (state: StructuredAttentionState) =>
|
||||
controller?.reconcileStructuredPromptAttention(state)
|
||||
registerNotificationHandlers(
|
||||
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: these paths read only getSettings; Store is a class, so a structural double needs the cast.
|
||||
{
|
||||
getSettings: () => ({
|
||||
notifications: {
|
||||
enabled: true,
|
||||
agentTaskComplete: true,
|
||||
agentNeedsInput: true,
|
||||
terminalBell: true,
|
||||
suppressWhenFocused: options.suppressWhenFocused
|
||||
}
|
||||
})
|
||||
} as never,
|
||||
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the notification handlers call only these four runtime methods.
|
||||
{
|
||||
dispatchMobileNotification,
|
||||
dismissMobileNotification,
|
||||
retireNotificationAttention: controller?.acknowledgeAttention.bind(controller),
|
||||
reconcileStructuredPromptAttention
|
||||
} as never
|
||||
)
|
||||
return { dispatchMobileNotification, dismissMobileNotification }
|
||||
}
|
||||
|
||||
describe('notifications:dismiss by acknowledged subject', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
vi.setSystemTime(new Date('2026-03-28T16:00:00Z'))
|
||||
resetNotificationDispatchMocks()
|
||||
})
|
||||
|
||||
// Reads rebuild ids for turns that never alerted; each forwarded one was a silent push and a store slot.
|
||||
it('clears on the phone only alerts that reached it, including ones sent before a restart', async () => {
|
||||
const directory = mkdtempSync(join(tmpdir(), 'orca-clear-delivered-'))
|
||||
const original = new RuntimeMobileNotificationController()
|
||||
const restarted = new RuntimeMobileNotificationController()
|
||||
try {
|
||||
original.configureDismissalStore(directory)
|
||||
original.dispatch({
|
||||
type: 'notification',
|
||||
source: 'agent-task-complete',
|
||||
title: 'Done',
|
||||
body: '',
|
||||
notificationId: 'agent:sent'
|
||||
})
|
||||
await original.closeDismissals()
|
||||
restarted.configureDismissalStore(directory)
|
||||
const events: MobileNotificationEvent[] = []
|
||||
restarted.onDispatched((event) => events.push(event))
|
||||
register({ suppressWhenFocused: false }, restarted)
|
||||
getDismissHandler()({}, ['agent:never-sent', 'agent:sent'], [PANE])
|
||||
getDismissHandler()({}, ['agent:sent'], [PANE])
|
||||
expect(events.map((event) => [event.type, event.notificationId])).toEqual([
|
||||
['dismiss', 'agent:sent']
|
||||
])
|
||||
} finally {
|
||||
await restarted.closeDismissals()
|
||||
rmSync(directory, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
// Positioned alerts survive reads before their journal boundary; pane-wide views cannot retire them.
|
||||
})
|
||||
@@ -46,48 +46,10 @@ it('reconciles an old delivered alert after desktop restart and preserves unrela
|
||||
])
|
||||
).toEqual([shown])
|
||||
})
|
||||
it('does not dismiss a newer replacement and does not treat missing or expired history as dismissal', () => {
|
||||
const h = fixture()
|
||||
const now = Date.now()
|
||||
vi.spyOn(Date, 'now').mockReturnValue(now)
|
||||
h.store.record({ ...alert, ...shown })
|
||||
h.store.record({ type: 'dismiss', ...shown, notificationSeq: 13 })
|
||||
expect(h.store.reconcile([shown])).toEqual([shown])
|
||||
h.store.record({ ...alert, ...shown, notificationSeq: 14 })
|
||||
expect(h.store.reconcile([{ ...shown, notificationSeq: 14 }])).toEqual([])
|
||||
expect(h.store.reconcile([shown])).toEqual([shown])
|
||||
h.store.record({ type: 'dismiss', ...shown, notificationSeq: 15 })
|
||||
vi.mocked(Date.now).mockReturnValue(now + 7 * 86400_000)
|
||||
expect(h.store.reconcile([shown])).toEqual([])
|
||||
expect(new MobileNotificationDismissalStore(`${h.path}-unknown`).reconcile([shown])).toEqual([])
|
||||
})
|
||||
it('lists only live deliveries across a restart', async () => {
|
||||
const h = fixture()
|
||||
const keyed = (notificationId: string, notificationSeq: number) => ({
|
||||
...alert,
|
||||
notificationId,
|
||||
notificationEpoch: 'e',
|
||||
notificationSeq
|
||||
})
|
||||
h.store.record({ ...keyed('subject:prompt:a1', 1), workspaceExecutionHostId: null })
|
||||
h.store.record(keyed('subject:prompt:a10', 2))
|
||||
h.store.record(keyed('other:prompt:a1', 3))
|
||||
h.store.record({
|
||||
type: 'dismiss',
|
||||
notificationId: 'subject:prompt:a10',
|
||||
notificationEpoch: 'e',
|
||||
notificationSeq: 4
|
||||
})
|
||||
await h.store.close()
|
||||
const restarted = new MobileNotificationDismissalStore(h.path)
|
||||
expect(restarted.liveDeliveries().map((entry) => entry.notificationId)).toEqual([
|
||||
'subject:prompt:a1',
|
||||
'other:prompt:a1'
|
||||
])
|
||||
expect(restarted.liveDeliveries()[0]).toMatchObject({ workspaceExecutionHostId: null })
|
||||
})
|
||||
|
||||
it("imports an older build's file, keeping a record whose origin it cannot read", async () => {
|
||||
const now = Date.UTC(2026, 10, 15)
|
||||
vi.spyOn(Date, 'now').mockReturnValue(now)
|
||||
const h = fixture()
|
||||
const origin = {
|
||||
scope: {
|
||||
@@ -99,7 +61,7 @@ it("imports an older build's file, keeping a record whose origin it cannot read"
|
||||
sessionId: 's',
|
||||
journalCursor: { epoch: 'j', sequence: 3 }
|
||||
}
|
||||
const entry = { ...shown, dismissedThrough: -1, expiresAt: Date.now() + 86400_000 }
|
||||
const entry = { ...shown, dismissedThrough: -1, expiresAt: now + 86400_000 }
|
||||
writeFileSync(
|
||||
join(h.path, 'mobile-notification-dismissals.json'),
|
||||
JSON.stringify([
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import { expect, it } from 'vitest'
|
||||
import { NOTIFICATION_METHODS } from './notifications'
|
||||
import { RuntimeMobileNotificationController } from '../../../push/notifications/runtime-mobile-notification-controller'
|
||||
import type { RpcContext, RpcStreamingMethod, RpcMethod } from '../../core'
|
||||
|
||||
it('keeps desktop-disabled events out of legacy live and replay streams', async () => {
|
||||
const controller = new RuntimeMobileNotificationController()
|
||||
const cleanups: (() => void)[] = []
|
||||
const runtime = {
|
||||
onNotificationDispatched: controller.onDispatched.bind(controller),
|
||||
getMobileNotificationEpoch: controller.getEpoch.bind(controller),
|
||||
getMissedNotificationsSince: controller.getMissedSince.bind(controller),
|
||||
registerSubscriptionCleanup: (_id: string, cleanup: () => void) => cleanups.push(cleanup)
|
||||
}
|
||||
const ctx = { runtime } as unknown as RpcContext
|
||||
const subscribe = NOTIFICATION_METHODS.find(
|
||||
(method) => method.name === 'notifications.subscribe'
|
||||
) as RpcStreamingMethod
|
||||
const replay = NOTIFICATION_METHODS.find(
|
||||
(method) => method.name === 'notifications.getMissedSince'
|
||||
) as RpcMethod
|
||||
const legacy: unknown[] = []
|
||||
const current: unknown[] = []
|
||||
const pending = [
|
||||
subscribe.handler({}, ctx, (event) => legacy.push(event)),
|
||||
subscribe.handler({ includeDesktopSuppressed: true }, ctx, (event) => current.push(event))
|
||||
]
|
||||
controller.dispatch({
|
||||
type: 'notification',
|
||||
source: 'terminal-bell',
|
||||
title: 'bell',
|
||||
body: '',
|
||||
desktopAllowed: false
|
||||
})
|
||||
controller.dispatch({
|
||||
type: 'notification',
|
||||
source: 'agent-task-complete',
|
||||
title: 'done',
|
||||
body: ''
|
||||
})
|
||||
expect(legacy).toHaveLength(2)
|
||||
expect(current).toHaveLength(3)
|
||||
expect(legacy[1]).toMatchObject({ title: 'done' })
|
||||
expect(current[1]).toMatchObject({ desktopAllowed: false })
|
||||
expect(await replay.handler({ lastSeenSeq: 0 }, ctx)).toMatchObject({
|
||||
notifications: [{ title: 'done' }]
|
||||
})
|
||||
const result = (await replay.handler(
|
||||
{ lastSeenSeq: 0, includeDesktopSuppressed: true },
|
||||
ctx
|
||||
)) as { notifications: unknown[] }
|
||||
expect(result.notifications).toHaveLength(2)
|
||||
cleanups.forEach((cleanup) => cleanup())
|
||||
await Promise.all(pending)
|
||||
})
|
||||
|
||||
it('preserves legacy workspace cooldown while letting current phones filter before cooldown', async () => {
|
||||
const { createNotificationStreamFilter } = await import('./notification-stream-policy')
|
||||
const events = [
|
||||
{
|
||||
type: 'notification' as const,
|
||||
source: 'terminal-bell' as const,
|
||||
title: '',
|
||||
body: '',
|
||||
worktreeId: 'folder',
|
||||
emittedAt: 10000
|
||||
},
|
||||
{
|
||||
type: 'notification' as const,
|
||||
source: 'agent-task-complete' as const,
|
||||
title: '',
|
||||
body: '',
|
||||
worktreeId: 'folder',
|
||||
emittedAt: 10250
|
||||
}
|
||||
]
|
||||
const controller = new RuntimeMobileNotificationController()
|
||||
events.forEach((event) => controller.dispatch(event))
|
||||
const recorded = controller.getMissedSince(0)
|
||||
expect(recorded.filter(createNotificationStreamFilter())).toEqual([
|
||||
expect.objectContaining(events[0])
|
||||
])
|
||||
expect(recorded.filter(createNotificationStreamFilter(true))).toHaveLength(2)
|
||||
})
|
||||
@@ -1,109 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { readPluginImageHeader } from './plugin-image-format'
|
||||
|
||||
function chunk(type: string, data: number[] = []): number[] {
|
||||
const length = data.length
|
||||
return [
|
||||
length >>> 24,
|
||||
(length >>> 16) & 255,
|
||||
(length >>> 8) & 255,
|
||||
length & 255,
|
||||
...Buffer.from(type),
|
||||
...data,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
const be32 = (n: number) => [n >>> 24, (n >>> 16) & 255, (n >>> 8) & 255, n & 255]
|
||||
|
||||
function pngBytes(width: number, height: number): Uint8Array {
|
||||
return Uint8Array.from([
|
||||
0x89,
|
||||
0x50,
|
||||
0x4e,
|
||||
0x47,
|
||||
0x0d,
|
||||
0x0a,
|
||||
0x1a,
|
||||
0x0a,
|
||||
...chunk('IHDR', [...be32(width), ...be32(height), 8, 6, 0, 0, 0]),
|
||||
...chunk('IDAT', [1, 2, 3]),
|
||||
...chunk('IEND')
|
||||
])
|
||||
}
|
||||
|
||||
function jpegBytes(width: number, height: number): Uint8Array {
|
||||
return Uint8Array.from([
|
||||
0xff,
|
||||
0xd8,
|
||||
0xff,
|
||||
0xe0,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0xff,
|
||||
0xc0,
|
||||
0,
|
||||
11,
|
||||
8,
|
||||
height >> 8,
|
||||
height & 255,
|
||||
width >> 8,
|
||||
width & 255,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
])
|
||||
}
|
||||
|
||||
function webpVp8x(width: number, height: number, flags: number): Uint8Array {
|
||||
const w = width - 1
|
||||
const h = height - 1
|
||||
return Uint8Array.from([
|
||||
...Buffer.from('RIFF'),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
...Buffer.from('WEBP'),
|
||||
...Buffer.from('VP8X'),
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
flags,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
w & 255,
|
||||
(w >> 8) & 255,
|
||||
(w >> 16) & 255,
|
||||
h & 255,
|
||||
(h >> 8) & 255,
|
||||
(h >> 16) & 255
|
||||
])
|
||||
}
|
||||
|
||||
describe('readPluginImageHeader', () => {
|
||||
it('reads PNG, JPEG and WebP sizes from headers', () => {
|
||||
expect(readPluginImageHeader(pngBytes(512, 512))).toEqual({
|
||||
format: 'png',
|
||||
width: 512,
|
||||
height: 512
|
||||
})
|
||||
expect(readPluginImageHeader(jpegBytes(1600, 1000))).toEqual({
|
||||
format: 'jpeg',
|
||||
width: 1600,
|
||||
height: 1000
|
||||
})
|
||||
expect(readPluginImageHeader(webpVp8x(1280, 800, 0))).toEqual({
|
||||
format: 'webp',
|
||||
width: 1280,
|
||||
height: 800
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,20 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { getWorkspaceIntentName } from './workspace-name'
|
||||
|
||||
describe('getWorkspaceIntentName', () => {
|
||||
it('does not treat an auto-generated slug as explicit user intent', () => {
|
||||
expect(
|
||||
getWorkspaceIntentName({
|
||||
sourceText: 'issue-123-fix-navbar',
|
||||
workItem: {
|
||||
type: 'issue',
|
||||
number: 456,
|
||||
title: 'Make importer handle archived rows'
|
||||
}
|
||||
})
|
||||
).toEqual({
|
||||
displayName: 'Issue 456 Make Importer Handle',
|
||||
seedName: 'issue-456-make-importer-handle'
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user