diff --git a/packages/bruno-app/src/components/AIAssist/index.spec.js b/packages/bruno-app/src/components/AIAssist/index.spec.js
index 21a9bab1b..702e7b9cf 100644
--- a/packages/bruno-app/src/components/AIAssist/index.spec.js
+++ b/packages/bruno-app/src/components/AIAssist/index.spec.js
@@ -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();
diff --git a/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.js b/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.js
index 503867af2..766878f37 100644
--- a/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.js
+++ b/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.js
@@ -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 = ({
Keymap
- Tab accept · Esc dismiss · ⌘+\ trigger
+ Tab accept · Esc dismiss · {getPlatformModifierKey()}+\ trigger
diff --git a/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.spec.js b/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.spec.js
new file mode 100644
index 000000000..1edd19208
--- /dev/null
+++ b/packages/bruno-app/src/components/Preferences/AI/AutocompletePane.spec.js
@@ -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(
+
+
+
+ );
+};
+
+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();
+ });
+});
diff --git a/packages/bruno-app/src/utils/common/platform.js b/packages/bruno-app/src/utils/common/platform.js
index 687b19c3d..7ab3552e0 100644
--- a/packages/bruno-app/src/utils/common/platform.js
+++ b/packages/bruno-app/src/utils/common/platform.js
@@ -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';
diff --git a/playwright/index.ts b/playwright/index.ts
index ddcb48de6..e45165126 100644
--- a/playwright/index.ts
+++ b/playwright/index.ts
@@ -22,6 +22,9 @@ const defaultPreferences = {
hasLaunchedBefore: true,
hasSeenWelcomeModal: true,
lastSeenVersion: version
+ },
+ ai: {
+ enabled: false
}
}
};
diff --git a/tests/preferences/ai/ai-shortcut-hints.spec.ts b/tests/preferences/ai/ai-shortcut-hints.spec.ts
new file mode 100644
index 000000000..3f6bb7d31
--- /dev/null
+++ b/tests/preferences/ai/ai-shortcut-hints.spec.ts
@@ -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();
+ });
+});
diff --git a/tests/preferences/ai/init-user-data/preferences.json b/tests/preferences/ai/init-user-data/preferences.json
new file mode 100644
index 000000000..b38647a42
--- /dev/null
+++ b/tests/preferences/ai/init-user-data/preferences.json
@@ -0,0 +1,11 @@
+{
+ "preferences": {
+ "onboarding": {
+ "hasLaunchedBefore": true,
+ "hasSeenWelcomeModal": true
+ },
+ "ai": {
+ "enabled": true
+ }
+ }
+}