mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor(editor): Rewrite TabBar to composition API (no-changelog) (#9231)
This commit is contained in:
parent
2917d04766
commit
c6b4c6dbf2
|
@ -6,8 +6,8 @@
|
||||||
<TabBar
|
<TabBar
|
||||||
v-if="onWorkflowPage"
|
v-if="onWorkflowPage"
|
||||||
:items="tabBarItems"
|
:items="tabBarItems"
|
||||||
:active-tab="activeHeaderTab"
|
:model-value="activeHeaderTab"
|
||||||
@select="onTabSelected"
|
@update:model-value="onTabSelected"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
57
packages/editor-ui/src/components/MainHeader/TabBar.spec.ts
Normal file
57
packages/editor-ui/src/components/MainHeader/TabBar.spec.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { fireEvent } from '@testing-library/vue';
|
||||||
|
import { createComponentRenderer } from '@/__tests__/render';
|
||||||
|
import TabBar from '@/components/MainHeader/TabBar.vue';
|
||||||
|
|
||||||
|
const renderComponent = createComponentRenderer(TabBar);
|
||||||
|
|
||||||
|
describe('TabBar', () => {
|
||||||
|
const items = [
|
||||||
|
{ name: 'Workflow', value: 'workflow' },
|
||||||
|
{ name: 'Executions', value: 'executions' },
|
||||||
|
];
|
||||||
|
|
||||||
|
it('should render the correct number of tabs', async () => {
|
||||||
|
const { findAllByRole } = renderComponent({
|
||||||
|
props: {
|
||||||
|
items,
|
||||||
|
modelValue: 'workflow',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabs = await findAllByRole('radio');
|
||||||
|
expect(tabs.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit update:modelValue event when a tab is clicked', async () => {
|
||||||
|
const { findAllByRole, emitted } = renderComponent({
|
||||||
|
props: {
|
||||||
|
items,
|
||||||
|
modelValue: 'workflow',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabs = await findAllByRole('radio');
|
||||||
|
const executionsTab = tabs[1];
|
||||||
|
|
||||||
|
await fireEvent.click(executionsTab);
|
||||||
|
|
||||||
|
expect(emitted()).toHaveProperty('update:modelValue');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the active tab when modelValue prop changes', async () => {
|
||||||
|
const { findAllByRole, rerender } = renderComponent({
|
||||||
|
props: {
|
||||||
|
items,
|
||||||
|
modelValue: 'workflow',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await rerender({ modelValue: 'executions' });
|
||||||
|
|
||||||
|
const tabs = await findAllByRole('radio');
|
||||||
|
const executionsTab = tabs[1];
|
||||||
|
const executionsTabButton = executionsTab.querySelector('.button');
|
||||||
|
|
||||||
|
expect(executionsTabButton).toHaveClass('active');
|
||||||
|
});
|
||||||
|
});
|
|
@ -4,50 +4,35 @@
|
||||||
:class="{
|
:class="{
|
||||||
[$style.container]: true,
|
[$style.container]: true,
|
||||||
['tab-bar-container']: true,
|
['tab-bar-container']: true,
|
||||||
[$style.menuCollapsed]: mainSidebarCollapsed,
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<n8n-radio-buttons :model-value="activeTab" :options="items" @update:model-value="onSelect" />
|
<N8nRadioButtons
|
||||||
|
:model-value="modelValue"
|
||||||
|
:options="items"
|
||||||
|
@update:model-value="onUpdateModelValue"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import type { PropType } from 'vue';
|
|
||||||
import type { ITabBarItem } from '@/Interface';
|
|
||||||
import { MAIN_HEADER_TABS } from '@/constants';
|
import { MAIN_HEADER_TABS } from '@/constants';
|
||||||
import { mapStores } from 'pinia';
|
import type { ITabBarItem } from '@/Interface';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
|
||||||
|
|
||||||
export default defineComponent({
|
withDefaults(
|
||||||
name: 'TabBar',
|
defineProps<{
|
||||||
props: {
|
items: ITabBarItem[];
|
||||||
items: {
|
modelValue?: string;
|
||||||
type: Array as PropType<ITabBarItem[]>,
|
}>(),
|
||||||
required: true,
|
{
|
||||||
},
|
modelValue: MAIN_HEADER_TABS.WORKFLOW,
|
||||||
activeTab: {
|
|
||||||
type: String,
|
|
||||||
default: MAIN_HEADER_TABS.WORKFLOW,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
);
|
||||||
return {
|
|
||||||
MAIN_HEADER_TABS,
|
const emit = defineEmits(['update:modelValue']);
|
||||||
};
|
|
||||||
},
|
function onUpdateModelValue(tab: string, event: MouseEvent): void {
|
||||||
computed: {
|
emit('update:modelValue', tab, event);
|
||||||
...mapStores(useUIStore),
|
}
|
||||||
mainSidebarCollapsed(): boolean {
|
|
||||||
return this.uiStore.sidebarMenuCollapsed;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSelect(tab: string, event: MouseEvent): void {
|
|
||||||
this.$emit('select', tab, event);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
|
|
Loading…
Reference in a new issue