diff --git a/frontend/src/collapsible.test.js b/frontend/src/collapsible.test.js new file mode 100644 index 0000000..c3dac0c --- /dev/null +++ b/frontend/src/collapsible.test.js @@ -0,0 +1,64 @@ +import { mount } from '@vue/test-utils' +import { beforeEach, describe, expect, it } from 'vitest' +import CollapsiblePanel from './components/CollapsiblePanel.vue' + +describe('CollapsiblePanel', () => { + beforeEach(() => { + localStorage.clear() + }) + + it('renders the title and slot when open by default', () => { + const wrapper = mount(CollapsiblePanel, { + props: { title: 'Strategy' }, + slots: { default: '
content
' }, + }) + expect(wrapper.text()).toContain('Strategy') + expect(wrapper.text()).toContain('content') + expect(wrapper.find('button').attributes('aria-expanded')).toBe('true') + }) + + it('hides the slot after clicking the header', async () => { + const wrapper = mount(CollapsiblePanel, { + props: { title: 'Strategy' }, + slots: { default: 'content
' }, + }) + await wrapper.find('button').trigger('click') + expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') + // v-show keeps the node but hides it. + expect(wrapper.find('div[style*="display: none"]').exists()).toBe(true) + }) + + it('shows the summary only when collapsed', async () => { + const wrapper = mount(CollapsiblePanel, { + props: { title: 'Backtest', summary: 'BTC/USDT 5m' }, + slots: { default: 'content
' }, + }) + expect(wrapper.text()).not.toContain('BTC/USDT 5m') + await wrapper.find('button').trigger('click') + expect(wrapper.text()).toContain('BTC/USDT 5m') + }) + + it('persists the collapsed state in localStorage', async () => { + const wrapper = mount(CollapsiblePanel, { + props: { title: 'Backtest', storageKey: 'backtest' }, + slots: { default: 'content
' }, + }) + await wrapper.find('button').trigger('click') + expect(localStorage.getItem('panel:backtest')).toBe('0') + + // A fresh mount with the same key starts collapsed. + const remounted = mount(CollapsiblePanel, { + props: { title: 'Backtest', storageKey: 'backtest' }, + slots: { default: 'content
' }, + }) + expect(remounted.find('button').attributes('aria-expanded')).toBe('false') + }) + + it('honours defaultOpen when nothing is stored', () => { + const wrapper = mount(CollapsiblePanel, { + props: { title: 'Strategy', defaultOpen: false }, + slots: { default: 'content
' }, + }) + expect(wrapper.find('button').attributes('aria-expanded')).toBe('false') + }) +}) diff --git a/frontend/src/components/BacktestPanel.vue b/frontend/src/components/BacktestPanel.vue index 4e64e96..6a2f365 100644 --- a/frontend/src/components/BacktestPanel.vue +++ b/frontend/src/components/BacktestPanel.vue @@ -1,7 +1,8 @@ -