diff --git a/packages/nc-gui/components/smartsheet/toolbar/SearchData.vue b/packages/nc-gui/components/smartsheet/toolbar/SearchData.vue index 6e56d64f81..24c6468aec 100644 --- a/packages/nc-gui/components/smartsheet/toolbar/SearchData.vue +++ b/packages/nc-gui/components/smartsheet/toolbar/SearchData.vue @@ -17,7 +17,7 @@ const { meta } = useSmartsheetStoreOrThrow() const activeView = inject(ActiveViewInj, ref()) -const { search, loadFieldQuery } = useFieldQuery(activeView) +const { search, loadFieldQuery } = useFieldQuery() const isDropdownOpen = ref(false) @@ -36,7 +36,7 @@ watch( () => activeView.value?.id, (n, o) => { if (n !== o) { - loadFieldQuery(activeView) + loadFieldQuery(activeView.value?.id) } }, { immediate: true }, @@ -76,6 +76,7 @@ function onPressEnter() { class="max-w-[200px]" :placeholder="$t('placeholder.filterQuery')" :bordered="false" + data-testid="search-data-input" @press-enter="onPressEnter" > diff --git a/packages/nc-gui/composables/useFieldQuery.ts b/packages/nc-gui/composables/useFieldQuery.ts index b18f488ce5..564742dcf2 100644 --- a/packages/nc-gui/composables/useFieldQuery.ts +++ b/packages/nc-gui/composables/useFieldQuery.ts @@ -1,8 +1,6 @@ -import type { Ref } from 'vue' -import type { ViewType } from 'nocodb-sdk' import { useState } from '#imports' -export function useFieldQuery(view: Ref) { +export function useFieldQuery() { // initial search object const emptyFieldQueryObj = { field: '', @@ -13,21 +11,16 @@ export function useFieldQuery(view: Ref) { const searchMap = useState>('field-query-search-map', () => ({})) // the fieldQueryObj under the current view - const search = useState<{ field: string; query: string }>('field-query-search', () => emptyFieldQueryObj) - - // map current view id to emptyFieldQueryObj - if (view?.value?.id) { - searchMap.value[view!.value!.id] = search.value - } + const search = useState<{ field: string; query: string }>('field-query-search', () => ({ ...emptyFieldQueryObj })) // retrieve the fieldQueryObj of the given view id // if it is not found in `searchMap`, init with emptyFieldQueryObj - const loadFieldQuery = (view: Ref) => { - if (!view.value?.id) return - if (!(view!.value!.id in searchMap.value)) { - searchMap.value[view!.value!.id!] = emptyFieldQueryObj + const loadFieldQuery = (id?: string) => { + if (!id) return + if (!(id in searchMap.value)) { + searchMap.value[id] = { ...emptyFieldQueryObj } } - search.value = searchMap.value[view!.value!.id!] + search.value = searchMap.value[id] } return { search, loadFieldQuery } diff --git a/packages/nc-gui/composables/useSmartsheetStore.ts b/packages/nc-gui/composables/useSmartsheetStore.ts index a0982e4b66..d76791a360 100644 --- a/packages/nc-gui/composables/useSmartsheetStore.ts +++ b/packages/nc-gui/composables/useSmartsheetStore.ts @@ -19,7 +19,7 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState( const cellRefs = ref([]) - const { search } = useFieldQuery(view) + const { search } = useFieldQuery() const eventBus = useEventBus(Symbol('SmartsheetStore')) diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/SearchData.ts b/tests/playwright/pages/Dashboard/common/Toolbar/SearchData.ts new file mode 100644 index 0000000000..f592407728 --- /dev/null +++ b/tests/playwright/pages/Dashboard/common/Toolbar/SearchData.ts @@ -0,0 +1,20 @@ +import BasePage from '../../../Base'; +import { ToolbarPage } from './index'; +import { expect } from '@playwright/test'; + +export class ToolbarSearchDataPage extends BasePage { + readonly toolbar: ToolbarPage; + + constructor(toolbar: ToolbarPage) { + super(toolbar.rootPage); + this.toolbar = toolbar; + } + + get() { + return this.rootPage.getByTestId('search-data-input'); + } + + async verify(query: string) { + await expect(await this.get().inputValue()).toBe(query); + } +} diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/index.ts b/tests/playwright/pages/Dashboard/common/Toolbar/index.ts index c97c263051..e5e2ccafbf 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/index.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/index.ts @@ -13,6 +13,7 @@ import { KanbanPage } from '../../Kanban'; import { FormPage } from '../../Form'; import { ToolbarStackbyPage } from './StackBy'; import { ToolbarAddEditStackPage } from './AddEditKanbanStack'; +import { ToolbarSearchDataPage } from './SearchData'; export class ToolbarPage extends BasePage { readonly parent: GridPage | GalleryPage | FormPage | KanbanPage; @@ -24,6 +25,7 @@ export class ToolbarPage extends BasePage { readonly actions: ToolbarActionsPage; readonly stackBy: ToolbarStackbyPage; readonly addEditStack: ToolbarAddEditStackPage; + readonly searchData: ToolbarSearchDataPage; constructor(parent: GridPage | GalleryPage | FormPage | KanbanPage) { super(parent.rootPage); @@ -36,6 +38,7 @@ export class ToolbarPage extends BasePage { this.actions = new ToolbarActionsPage(this); this.stackBy = new ToolbarStackbyPage(this); this.addEditStack = new ToolbarAddEditStackPage(this); + this.searchData = new ToolbarSearchDataPage(this); } get() { diff --git a/tests/playwright/tests/views.spec.ts b/tests/playwright/tests/views.spec.ts index 6db52ecc57..c823384eed 100644 --- a/tests/playwright/tests/views.spec.ts +++ b/tests/playwright/tests/views.spec.ts @@ -1,14 +1,17 @@ -import { test } from '@playwright/test'; +import { expect, test } from '@playwright/test'; import { DashboardPage } from '../pages/Dashboard'; +import { ToolbarPage } from '../pages/Dashboard/common/Toolbar'; import setup from '../setup'; test.describe('Views CRUD Operations', () => { let dashboard: DashboardPage; let context: any; + let toolbar: ToolbarPage; test.beforeEach(async ({ page }) => { context = await setup({ page }); dashboard = new DashboardPage(page, context.project); + toolbar = dashboard.grid.toolbar; }); test('Create views, reorder and delete', async () => { @@ -73,4 +76,48 @@ test.describe('Views CRUD Operations', () => { index: 1, }); }); + + test('Save search query for each table and view', async () => { + await dashboard.treeView.openTable({ title: 'City' }); + + await toolbar.searchData.verify(''); + await toolbar.searchData.get().fill('City-City'); + await toolbar.searchData.verify('City-City'); + + await dashboard.viewSidebar.createGridView({ title: 'CityGrid' }); + await toolbar.searchData.verify(''); + await toolbar.searchData.get().fill('City-CityGrid'); + await toolbar.searchData.verify('City-CityGrid'); + + await dashboard.viewSidebar.createGridView({ title: 'CityGrid2' }); + await toolbar.searchData.verify(''); + await toolbar.searchData.get().fill('City-CityGrid2'); + await toolbar.searchData.verify('City-CityGrid2'); + + await dashboard.viewSidebar.openView({ title: 'CityGrid' }); + await expect(dashboard.get().locator('[data-testid="grid-load-spinner"]')).toBeVisible(); + await dashboard.grid.waitLoading(); + await toolbar.searchData.verify('City-CityGrid'); + + await dashboard.viewSidebar.openView({ title: 'City' }); + await expect(dashboard.get().locator('[data-testid="grid-load-spinner"]')).toBeVisible(); + await dashboard.grid.waitLoading(); + await toolbar.searchData.verify('City-City'); + + await dashboard.treeView.openTable({ title: 'Actor' }); + await toolbar.searchData.verify(''); + + await dashboard.viewSidebar.createGridView({ title: 'ActorGrid' }); + await toolbar.searchData.verify(''); + await toolbar.searchData.get().fill('Actor-ActorGrid'); + await toolbar.searchData.verify('Actor-ActorGrid'); + + await dashboard.viewSidebar.openView({ title: 'Actor' }); + await expect(dashboard.get().locator('[data-testid="grid-load-spinner"]')).toBeVisible(); + await dashboard.grid.waitLoading(); + await toolbar.searchData.verify(''); + + await dashboard.treeView.openTable({ title: 'City', mode: '' }); + await toolbar.searchData.verify('City-City'); + }); });