fix(ui-open-in-app): open the application the control names
With no OS-marked default the split button labelled the first registered application and marked it "(default)" in the menu, but the primary action still asked the OS to resolve the association again; on Windows that can prompt or open a different application than the button promises. Send that application's id explicitly and keep the association path for the case the Host actually marked a default. The snapshot scenario now clears the platform's own default marker and re-enters the file, so the association is read again instead of reusing the answer already held, and it asserts the launched target rather than only the labels.
This commit is contained in:
1 parent
58c70c2cca
commit
64795b4879
3 files changed
+22
-6
No files matched your search
@@ -1355,6 +1355,13 @@ else process.exit(1);
|
||||
{ id: '/Applications/Test Player.app', name: 'Test Player', default: false, icon: `data:image/png;base64,${TINY_PNG.toString('base64')}` },
|
||||
{ id: '/Applications/Other Player.app', name: 'Other Player', default: false, icon: null },
|
||||
]))
|
||||
// Leave the file and come back: the shared association state is discarded when the
|
||||
// last control for a path unmounts, so the marker is read again instead of reused.
|
||||
await openPreviewFile(column, filesTab, preview, 'notes.unknown')
|
||||
await openPreviewFile(column, filesTab, preview, 'clip.mp4')
|
||||
await unsupported.waitFor({ timeout: 15_000 })
|
||||
await emptyOpen.waitFor({ timeout: 15_000 })
|
||||
// Opening the menu settles the re-read association before the labels are compared.
|
||||
await prominent.getByRole('button', { name: 'More ways to open' }).click()
|
||||
await page.getByRole('menuitem', { name: 'Test Player (default)', exact: true }).waitFor()
|
||||
await page.keyboard.press('Escape')
|
||||
@@ -1362,14 +1369,17 @@ else process.exit(1);
|
||||
expect(await headerOpen.getAttribute('aria-label')).toBe('Open in Test Player')
|
||||
await compareOrRefreshGolden(join(SNAPSHOT_DIR, 'applications-no-default.expected.md'), await prominent.ariaSnapshot(), MODE)
|
||||
const gesturesBefore = (await opened()).length
|
||||
const launchesBefore = (await launched()).length
|
||||
await emptyOpen.click()
|
||||
await expect.poll(async () => (await opened()).length).toBe(gesturesBefore + 1)
|
||||
// Without an OS-marked default the main action still opens the file instead of revealing it.
|
||||
expect((await opened()).at(-1)).toEqual({ path: clip, action: 'open' })
|
||||
const launchesBefore = (await launched()).length
|
||||
// Without an OS-marked default the main action opens the application this control
|
||||
// names, rather than the OS association (which can prompt or pick another app).
|
||||
expect((await opened()).at(-1)).toEqual({ path: clip, action: 'application' })
|
||||
await expect.poll(async () => (await launched()).length).toBe(launchesBefore + 1)
|
||||
expect((await launched()).at(-1)?.app).toBe(launchTarget)
|
||||
await prominent.getByRole('button', { name: 'More ways to open' }).click()
|
||||
await page.getByRole('menuitem', { name: 'Test Player (default)', exact: true }).click()
|
||||
await expect.poll(async () => (await launched()).length).toBe(launchesBefore + 1)
|
||||
await expect.poll(async () => (await launched()).length).toBe(launchesBefore + 2)
|
||||
expect((await launched()).at(-1)?.app).toBe(launchTarget)
|
||||
await expect.poll(async () => (await opened()).length).toBe(gesturesBefore + 2)
|
||||
expect((await opened()).at(-1)).toEqual({ path: clip, action: 'application' })
|
||||
|
||||
@@ -92,7 +92,13 @@ export function OpenTargetButton(props: OpenTargetButtonProps): ReactNode {
|
||||
const revealDefault = kind === 'file' && preferred === undefined && props.loading !== true
|
||||
const primaryLabel = preferred === undefined ? t('path.reveal') : t('open.title', { app: preferred.name })
|
||||
const run = (operation: OpenTargetOperation): void => { setMenuOpen(false); act(operation) }
|
||||
const primary = (): void => { run({ kind: revealDefault ? 'reveal' : 'default' }) }
|
||||
const primary = (): void => {
|
||||
if (revealDefault) { run({ kind: 'reveal' }); return }
|
||||
// The Host's default marker is best effort. With none, request the application
|
||||
// this control names instead of letting the OS resolve the association again.
|
||||
if (preferred !== undefined && preferred.id !== defaultId) { run({ kind: 'application', id: preferred.id }); return }
|
||||
run({ kind: 'default' })
|
||||
}
|
||||
const icon = props.loading === true && preferred === undefined
|
||||
? <span className={css.skeleton} data-open-target-skeleton aria-hidden="true" style={{ width: props.prominent ? 18 : 13, height: props.prominent ? 18 : 13 }} />
|
||||
: revealDefault
|
||||
|
||||
@@ -202,7 +202,7 @@ it('opens with the first registered application when none is marked default', as
|
||||
await act(async () => {})
|
||||
const main = screen.getByRole('button', { name: t('open.title', { app: 'Player' }) })
|
||||
await act(async () => { fireEvent.click(main) })
|
||||
expect(b.openPath).toHaveBeenLastCalledWith(ABSOLUTE_PATH, 'open', undefined)
|
||||
expect(b.openPath).toHaveBeenLastCalledWith(ABSOLUTE_PATH, 'open', '/Player.app')
|
||||
await act(async () => { fireEvent.click(screen.getByRole('button', { name: zh['path.more'] })) })
|
||||
expect(screen.getAllByRole('menuitem').map(item => item.textContent)).toEqual(['Player(默认)', zh['path.reveal']])
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user