mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-07 14:08:38 +00:00
fix(ai): show platform-correct modifier key in AI shortcut hints (#8430)
* fix(ai): show platform-correct modifier key in AI shortcut hints * test(ai): cover platform-correct modifier key in AI shortcut hint specs * Added the import * Added ai.enabled default to playwright default preferences --------- Co-authored-by: Utkarsh <utkarsh@usebruno.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { Provider } from 'react-redux';
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { aiGenerateScript, stopAiGeneration } from 'utils/ai';
|
||||
import { getPlatformModifierKey } from 'utils/common/platform';
|
||||
import AIAssist from './index';
|
||||
|
||||
jest.mock('utils/ai', () => ({
|
||||
@@ -12,6 +13,11 @@ jest.mock('utils/ai', () => ({
|
||||
stopAiGeneration: jest.fn()
|
||||
}));
|
||||
|
||||
jest.mock('utils/common/platform', () => ({
|
||||
...jest.requireActual('utils/common/platform'),
|
||||
getPlatformModifierKey: jest.fn()
|
||||
}));
|
||||
|
||||
const theme = {
|
||||
bg: '#1e1e1e',
|
||||
text: '#ffffff',
|
||||
@@ -63,6 +69,7 @@ describe('AIAssist', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
aiGenerateScript.mockResolvedValue({ content: 'test("generated", () => {});' });
|
||||
getPlatformModifierKey.mockReturnValue('Ctrl');
|
||||
});
|
||||
|
||||
describe('visibility', () => {
|
||||
@@ -159,6 +166,17 @@ describe('AIAssist', () => {
|
||||
expect(screen.queryByRole('button', { name: 'Status 200' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['macOS', '⌘'],
|
||||
['non-macOS', 'Ctrl']
|
||||
])('shows the %s modifier in the generate shortcut hint', (_platform, modifier) => {
|
||||
getPlatformModifierKey.mockReturnValue(modifier);
|
||||
renderAIAssist();
|
||||
openPopup();
|
||||
|
||||
expect(screen.getByText(`${modifier} + Enter to generate`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('keeps Generate disabled until the prompt has text', () => {
|
||||
renderAIAssist();
|
||||
openPopup();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IconChevronDown } from '@tabler/icons';
|
||||
import ToggleSwitch from 'components/ToggleSwitch';
|
||||
import { getPlatformModifierKey } from 'utils/common/platform';
|
||||
|
||||
/**
|
||||
* Autocomplete tab content. Sibling of the Configuration tab inside
|
||||
@@ -25,7 +26,7 @@ const TRIGGER_MODES = [
|
||||
{
|
||||
value: 'manual',
|
||||
label: 'Manual',
|
||||
description: 'Only on ⌘+\\ / Ctrl+\\'
|
||||
description: `Only on ${getPlatformModifierKey()}+\\`
|
||||
}
|
||||
];
|
||||
|
||||
@@ -148,7 +149,7 @@ const AutocompletePane = ({
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[11.5px] font-medium">Keymap</span>
|
||||
<div className="autocomplete-keymap text-[10.5px]">
|
||||
<kbd>Tab</kbd> accept · <kbd>Esc</kbd> dismiss · <kbd>⌘</kbd>+<kbd>\</kbd> trigger
|
||||
<kbd>Tab</kbd> accept · <kbd>Esc</kbd> dismiss · <kbd>{getPlatformModifierKey()}</kbd>+<kbd>\</kbd> trigger
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
global.React = React;
|
||||
|
||||
jest.mock('utils/common/platform', () => ({
|
||||
getPlatformModifierKey: jest.fn(() => 'Ctrl')
|
||||
}));
|
||||
|
||||
import { getPlatformModifierKey } from 'utils/common/platform';
|
||||
import AutocompletePane from './AutocompletePane';
|
||||
|
||||
const theme = {
|
||||
primary: { solid: '#6366f1' },
|
||||
input: { bg: '#111827' },
|
||||
colors: { text: { muted: '#9ca3af' } }
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
aiEnabled: true,
|
||||
enabled: true,
|
||||
model: '',
|
||||
triggerMode: 'manual',
|
||||
availableModels: [{ id: 'model-1', label: 'Model 1' }],
|
||||
hasConfiguredProvider: true,
|
||||
onToggleEnabled: jest.fn(),
|
||||
onChangeModel: jest.fn(),
|
||||
onChangeTriggerMode: jest.fn()
|
||||
};
|
||||
|
||||
const renderPane = (modifier, props = {}) => {
|
||||
getPlatformModifierKey.mockReturnValue(modifier);
|
||||
return render(
|
||||
<ThemeProvider theme={theme}>
|
||||
<AutocompletePane {...baseProps} {...props} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('AutocompletePane shortcut copy', () => {
|
||||
it.each([
|
||||
['macOS', '⌘'],
|
||||
['non-macOS', 'Ctrl']
|
||||
])('shows the %s modifier in the keymap', (_platform, modifier) => {
|
||||
renderPane(modifier);
|
||||
expect(screen.getByText(modifier)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the platform modifier in the manual trigger description', () => {
|
||||
renderPane('Ctrl');
|
||||
expect(screen.getByText('Only on Ctrl+\\')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -40,6 +40,10 @@ export const isLinuxOS = () => {
|
||||
return osFamily.includes('linux') || osFamily.includes('ubuntu') || osFamily.includes('debian') || osFamily.includes('fedora') || osFamily.includes('centos') || osFamily.includes('arch');
|
||||
};
|
||||
|
||||
export const getPlatformModifierKey = () => {
|
||||
return isMacOS() ? '⌘' : 'Ctrl';
|
||||
};
|
||||
|
||||
export const getRevealInFolderLabel = () => {
|
||||
if (isMacOS()) return 'Reveal in Finder';
|
||||
if (isWindowsOS()) return 'Reveal in File Explorer';
|
||||
|
||||
@@ -22,6 +22,9 @@ const defaultPreferences = {
|
||||
hasLaunchedBefore: true,
|
||||
hasSeenWelcomeModal: true,
|
||||
lastSeenVersion: version
|
||||
},
|
||||
ai: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
17
tests/preferences/ai/ai-shortcut-hints.spec.ts
Normal file
17
tests/preferences/ai/ai-shortcut-hints.spec.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { test, expect } from '../../../playwright';
|
||||
|
||||
const expectedModifier = process.platform === 'darwin' ? '⌘' : 'Ctrl';
|
||||
|
||||
test.describe('AI shortcut hints', () => {
|
||||
test('autocomplete keymap shows the platform-correct modifier', async ({ pageWithUserData: page }) => {
|
||||
await page.locator('[data-app-state="loaded"]').waitFor();
|
||||
|
||||
await page.locator('.status-bar button[data-trigger="preferences"]').click();
|
||||
await page.getByRole('tab', { name: 'AI', exact: true }).click();
|
||||
await page.getByTestId('ai-tab-autocomplete').click();
|
||||
|
||||
const keymap = page.locator('.autocomplete-keymap');
|
||||
await expect(keymap).toBeVisible();
|
||||
await expect(keymap.getByText(expectedModifier, { exact: true })).toBeVisible();
|
||||
});
|
||||
});
|
||||
11
tests/preferences/ai/init-user-data/preferences.json
Normal file
11
tests/preferences/ai/init-user-data/preferences.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"preferences": {
|
||||
"onboarding": {
|
||||
"hasLaunchedBefore": true,
|
||||
"hasSeenWelcomeModal": true
|
||||
},
|
||||
"ai": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user