diff --git a/client/src/components/__tests__/Sidebar.test.tsx b/client/src/components/__tests__/Sidebar.test.tsx
new file mode 100644
index 0000000..765de2f
--- /dev/null
+++ b/client/src/components/__tests__/Sidebar.test.tsx
@@ -0,0 +1,278 @@
+import { render, screen, fireEvent } from '@testing-library/react';
+import { describe, it, beforeEach, jest } from '@jest/globals';
+import Sidebar from '../Sidebar';
+
+// Mock theme hook
+jest.mock('../../lib/useTheme', () => ({
+ __esModule: true,
+ default: () => ['light', jest.fn()],
+}));
+
+describe('Sidebar Environment Variables', () => {
+ const defaultProps = {
+ connectionStatus: 'disconnected' as const,
+ transportType: 'stdio' as const,
+ setTransportType: jest.fn(),
+ command: '',
+ setCommand: jest.fn(),
+ args: '',
+ setArgs: jest.fn(),
+ sseUrl: '',
+ setSseUrl: jest.fn(),
+ env: {},
+ setEnv: jest.fn(),
+ bearerToken: '',
+ setBearerToken: jest.fn(),
+ onConnect: jest.fn(),
+ stdErrNotifications: [],
+ logLevel: 'info' as const,
+ sendLogLevelRequest: jest.fn(),
+ loggingSupported: true,
+ };
+
+ const renderSidebar = (props = {}) => {
+ return render();
+ };
+
+ const openEnvVarsSection = () => {
+ const button = screen.getByText('Environment Variables');
+ fireEvent.click(button);
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ describe('Basic Operations', () => {
+ it('should add a new environment variable', () => {
+ const setEnv = jest.fn();
+ renderSidebar({ env: {}, setEnv });
+
+ openEnvVarsSection();
+
+ const addButton = screen.getByText('Add Environment Variable');
+ fireEvent.click(addButton);
+
+ expect(setEnv).toHaveBeenCalledWith({ '': '' });
+ });
+
+ it('should remove an environment variable', () => {
+ const setEnv = jest.fn();
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const removeButton = screen.getByRole('button', { name: '×' });
+ fireEvent.click(removeButton);
+
+ expect(setEnv).toHaveBeenCalledWith({});
+ });
+
+ it('should update environment variable value', () => {
+ const setEnv = jest.fn();
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const valueInput = screen.getByDisplayValue('test_value');
+ fireEvent.change(valueInput, { target: { value: 'new_value' } });
+
+ expect(setEnv).toHaveBeenCalledWith({ TEST_KEY: 'new_value' });
+ });
+
+ it('should toggle value visibility', () => {
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv });
+
+ openEnvVarsSection();
+
+ const valueInput = screen.getByDisplayValue('test_value');
+ expect(valueInput).toHaveProperty('type', 'password');
+
+ const toggleButton = screen.getByRole('button', { name: /show value/i });
+ fireEvent.click(toggleButton);
+
+ expect(valueInput).toHaveProperty('type', 'text');
+ });
+ });
+
+ describe('Key Editing', () => {
+ it('should maintain order when editing first key', () => {
+ const setEnv = jest.fn();
+ const initialEnv = {
+ FIRST_KEY: 'first_value',
+ SECOND_KEY: 'second_value',
+ THIRD_KEY: 'third_value',
+ };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const firstKeyInput = screen.getByDisplayValue('FIRST_KEY');
+ fireEvent.change(firstKeyInput, { target: { value: 'NEW_FIRST_KEY' } });
+
+ expect(setEnv).toHaveBeenCalledWith({
+ NEW_FIRST_KEY: 'first_value',
+ SECOND_KEY: 'second_value',
+ THIRD_KEY: 'third_value',
+ });
+ });
+
+ it('should maintain order when editing middle key', () => {
+ const setEnv = jest.fn();
+ const initialEnv = {
+ FIRST_KEY: 'first_value',
+ SECOND_KEY: 'second_value',
+ THIRD_KEY: 'third_value',
+ };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const middleKeyInput = screen.getByDisplayValue('SECOND_KEY');
+ fireEvent.change(middleKeyInput, { target: { value: 'NEW_SECOND_KEY' } });
+
+ expect(setEnv).toHaveBeenCalledWith({
+ FIRST_KEY: 'first_value',
+ NEW_SECOND_KEY: 'second_value',
+ THIRD_KEY: 'third_value',
+ });
+ });
+
+ it('should maintain order when editing last key', () => {
+ const setEnv = jest.fn();
+ const initialEnv = {
+ FIRST_KEY: 'first_value',
+ SECOND_KEY: 'second_value',
+ THIRD_KEY: 'third_value',
+ };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const lastKeyInput = screen.getByDisplayValue('THIRD_KEY');
+ fireEvent.change(lastKeyInput, { target: { value: 'NEW_THIRD_KEY' } });
+
+ expect(setEnv).toHaveBeenCalledWith({
+ FIRST_KEY: 'first_value',
+ SECOND_KEY: 'second_value',
+ NEW_THIRD_KEY: 'third_value',
+ });
+ });
+ });
+
+ describe('Multiple Operations', () => {
+ it('should maintain state after multiple key edits', () => {
+ const setEnv = jest.fn();
+ const initialEnv = {
+ FIRST_KEY: 'first_value',
+ SECOND_KEY: 'second_value',
+ };
+ const { rerender } = renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ // First key edit
+ const firstKeyInput = screen.getByDisplayValue('FIRST_KEY');
+ fireEvent.change(firstKeyInput, { target: { value: 'NEW_FIRST_KEY' } });
+
+ // Get the updated env from the first setEnv call
+ const updatedEnv = (setEnv.mock.calls[0][0] as Record);
+
+ // Rerender with the updated env
+ rerender();
+
+ // Second key edit
+ const secondKeyInput = screen.getByDisplayValue('SECOND_KEY');
+ fireEvent.change(secondKeyInput, { target: { value: 'NEW_SECOND_KEY' } });
+
+ // Verify the final state matches what we expect
+ expect(setEnv).toHaveBeenLastCalledWith({
+ NEW_FIRST_KEY: 'first_value',
+ NEW_SECOND_KEY: 'second_value',
+ });
+ });
+
+ it('should maintain visibility state after key edit', () => {
+ const initialEnv = { TEST_KEY: 'test_value' };
+ const { rerender } = renderSidebar({ env: initialEnv });
+
+ openEnvVarsSection();
+
+ // Show the value
+ const toggleButton = screen.getByRole('button', { name: /show value/i });
+ fireEvent.click(toggleButton);
+
+ const valueInput = screen.getByDisplayValue('test_value');
+ expect(valueInput).toHaveProperty('type', 'text');
+
+ // Edit the key
+ const keyInput = screen.getByDisplayValue('TEST_KEY');
+ fireEvent.change(keyInput, { target: { value: 'NEW_KEY' } });
+
+ // Rerender with updated env
+ rerender();
+
+ // Value should still be visible
+ const updatedValueInput = screen.getByDisplayValue('test_value');
+ expect(updatedValueInput).toHaveProperty('type', 'text');
+ });
+ });
+
+ describe('Edge Cases', () => {
+ it('should handle empty key', () => {
+ const setEnv = jest.fn();
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const keyInput = screen.getByDisplayValue('TEST_KEY');
+ fireEvent.change(keyInput, { target: { value: '' } });
+
+ expect(setEnv).toHaveBeenCalledWith({ '': 'test_value' });
+ });
+
+ it('should handle special characters in key', () => {
+ const setEnv = jest.fn();
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const keyInput = screen.getByDisplayValue('TEST_KEY');
+ fireEvent.change(keyInput, { target: { value: 'TEST-KEY@123' } });
+
+ expect(setEnv).toHaveBeenCalledWith({ 'TEST-KEY@123': 'test_value' });
+ });
+
+ it('should handle unicode characters', () => {
+ const setEnv = jest.fn();
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const keyInput = screen.getByDisplayValue('TEST_KEY');
+ fireEvent.change(keyInput, { target: { value: 'TEST_🔑' } });
+
+ expect(setEnv).toHaveBeenCalledWith({ 'TEST_🔑': 'test_value' });
+ });
+
+ it('should handle very long key names', () => {
+ const setEnv = jest.fn();
+ const initialEnv = { TEST_KEY: 'test_value' };
+ renderSidebar({ env: initialEnv, setEnv });
+
+ openEnvVarsSection();
+
+ const keyInput = screen.getByDisplayValue('TEST_KEY');
+ const longKey = 'A'.repeat(100);
+ fireEvent.change(keyInput, { target: { value: longKey } });
+
+ expect(setEnv).toHaveBeenCalledWith({ [longKey]: 'test_value' });
+ });
+ });
+});