### Improved tenant assignment flow This PR improves the tenant assignment flow. I know a lot of users liked the previous flow where the field was not injected into the document. But the original flow, confused many of users because the tenant filter (top left) was being used to set the tenant on the document _and_ filter the list view. This change shown below is aiming to solve both of those groups with a slightly different approach. As always, feedback is welcome while we try to really make this plugin work for everyone. https://github.com/user-attachments/assets/ceee8b3a-c5f5-40e9-8648-f583e2412199 Added 2 new localization strings: ``` // shown in the 3 dot menu 'assign-tenant-button-label': 'Assign Tenant', // shown when needing to assign a tenant to a NEW document 'assign-tenant-modal-title': 'Assign "{{title}}"', ``` Removed 2 localization strings: ``` 'confirm-modal-tenant-switch--body', 'confirm-modal-tenant-switch--heading' ```
780 lines
22 KiB
TypeScript
780 lines
22 KiB
TypeScript
import type { Page } from '@playwright/test'
|
|
import type { BasePayload } from 'payload'
|
|
|
|
import { expect, test } from '@playwright/test'
|
|
import * as path from 'path'
|
|
import { wait } from 'payload/shared'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
import type { PayloadTestSDK } from '../helpers/sdk/index.js'
|
|
import type { Config } from './payload-types.js'
|
|
|
|
import { ensureCompilationIsDone, initPageConsoleErrorCatch, saveDocAndAssert } from '../helpers.js'
|
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
|
import { loginClientSide } from '../helpers/e2e/auth/login.js'
|
|
import { goToListDoc } from '../helpers/e2e/goToListDoc.js'
|
|
import {
|
|
clearSelectInput,
|
|
getSelectInputOptions,
|
|
getSelectInputValue,
|
|
selectInput,
|
|
} from '../helpers/e2e/selectInput.js'
|
|
import { closeNav, openNav } from '../helpers/e2e/toggleNav.js'
|
|
import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js'
|
|
import { reInitializeDB } from '../helpers/reInitializeDB.js'
|
|
import { TEST_TIMEOUT_LONG } from '../playwright.config.js'
|
|
import { credentials } from './credentials.js'
|
|
import { seed } from './seed/index.js'
|
|
import { autosaveGlobalSlug, menuItemsSlug, menuSlug, tenantsSlug, usersSlug } from './shared.js'
|
|
|
|
const filename = fileURLToPath(import.meta.url)
|
|
const dirname = path.dirname(filename)
|
|
|
|
test.describe('Multi Tenant', () => {
|
|
let page: Page
|
|
let serverURL: string
|
|
let globalMenuURL: AdminUrlUtil
|
|
let autosaveGlobalURL: AdminUrlUtil
|
|
let menuItemsURL: AdminUrlUtil
|
|
let usersURL: AdminUrlUtil
|
|
let tenantsURL: AdminUrlUtil
|
|
let payload: PayloadTestSDK<Config>
|
|
|
|
test.beforeAll(async ({ browser }, testInfo) => {
|
|
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
|
|
|
const { serverURL: serverFromInit, payload: payloadFromInit } =
|
|
await initPayloadE2ENoConfig<Config>({ dirname })
|
|
serverURL = serverFromInit
|
|
globalMenuURL = new AdminUrlUtil(serverURL, menuSlug)
|
|
menuItemsURL = new AdminUrlUtil(serverURL, menuItemsSlug)
|
|
usersURL = new AdminUrlUtil(serverURL, usersSlug)
|
|
tenantsURL = new AdminUrlUtil(serverURL, tenantsSlug)
|
|
payload = payloadFromInit
|
|
autosaveGlobalURL = new AdminUrlUtil(serverURL, autosaveGlobalSlug)
|
|
|
|
const context = await browser.newContext()
|
|
page = await context.newPage()
|
|
initPageConsoleErrorCatch(page)
|
|
await ensureCompilationIsDone({ page, serverURL, noAutoLogin: true })
|
|
await reInitializeDB({
|
|
serverURL,
|
|
snapshotKey: 'multiTenant',
|
|
})
|
|
if (seed) {
|
|
await seed(payload as unknown as BasePayload)
|
|
await ensureCompilationIsDone({ page, serverURL, noAutoLogin: true })
|
|
}
|
|
})
|
|
|
|
test.describe('Filters', () => {
|
|
test.describe('Tenants', () => {
|
|
test('should show all tenants when tenant selector is empty', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await clearTenantFilter({ page })
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Blue Dog',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Steel Cat',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Public Tenant',
|
|
}),
|
|
).toBeVisible()
|
|
})
|
|
test('should show filtered tenants when tenant selector is set', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await setTenantFilter({
|
|
urlUtil: tenantsURL,
|
|
page,
|
|
tenant: 'Blue Dog',
|
|
})
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Blue Dog',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Steel Cat',
|
|
}),
|
|
).toBeHidden()
|
|
})
|
|
})
|
|
|
|
test.describe('Tenant Assigned Documents', () => {
|
|
test('should show all tenant items when tenant selector is empty', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Spicy Mac',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Pretzel Bites',
|
|
}),
|
|
).toBeVisible()
|
|
})
|
|
test('should show filtered tenant items when tenant selector is set', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await setTenantFilter({
|
|
urlUtil: menuItemsURL,
|
|
page,
|
|
tenant: 'Blue Dog',
|
|
})
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Spicy Mac',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Pretzel Bites',
|
|
}),
|
|
).toBeHidden()
|
|
})
|
|
test('should show public tenant items to super admins', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Free Pizza',
|
|
}),
|
|
).toBeVisible()
|
|
})
|
|
test('should not show public tenant items to users with assigned tenants', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.owner,
|
|
})
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Free Pizza',
|
|
}),
|
|
).toBeHidden()
|
|
})
|
|
})
|
|
|
|
test.describe('Users', () => {
|
|
test('should show all users when tenant selector is empty', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(usersURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-email', {
|
|
hasText: 'jane@blue-dog.com',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-email', {
|
|
hasText: 'huel@steel-cat.com',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-email', {
|
|
hasText: 'dev@payloadcms.com',
|
|
}),
|
|
).toBeVisible()
|
|
})
|
|
|
|
test('should show only tenant users when tenant selector is empty', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await setTenantFilter({
|
|
urlUtil: usersURL,
|
|
page,
|
|
tenant: 'Blue Dog',
|
|
})
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-email', {
|
|
hasText: 'jane@blue-dog.com',
|
|
}),
|
|
).toBeVisible()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-email', {
|
|
hasText: 'huel@steel-cat.com',
|
|
}),
|
|
).toBeHidden()
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-email', {
|
|
hasText: 'dev@payloadcms.com',
|
|
}),
|
|
).toBeHidden()
|
|
})
|
|
})
|
|
})
|
|
|
|
test.describe('Documents', () => {
|
|
test('should set tenant upon entering document', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await goToListDoc({
|
|
page,
|
|
cellClass: '.cell-name',
|
|
textToMatch: 'Spicy Mac',
|
|
urlUtil: menuItemsURL,
|
|
})
|
|
|
|
await openNav(page)
|
|
await expect
|
|
.poll(async () => {
|
|
return await getSelectInputValue<false>({
|
|
selectLocator: page.locator('.tenant-selector'),
|
|
multiSelect: false,
|
|
})
|
|
})
|
|
.toBe('Blue Dog')
|
|
})
|
|
|
|
test('should allow tenant switching cancellation', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await goToListDoc({
|
|
page,
|
|
cellClass: '.cell-name',
|
|
textToMatch: 'Spicy Mac',
|
|
urlUtil: menuItemsURL,
|
|
})
|
|
|
|
await selectDocumentTenant({
|
|
page,
|
|
tenant: 'Steel Cat',
|
|
action: 'cancel',
|
|
payload,
|
|
})
|
|
|
|
await expect(page.locator('#action-save')).toBeDisabled()
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await expect
|
|
.poll(async () => {
|
|
return await getSelectedTenantFilterName({ page, payload })
|
|
})
|
|
.toBe('Blue Dog')
|
|
})
|
|
|
|
test('should allow tenant switching confirmation', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(menuItemsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await goToListDoc({
|
|
page,
|
|
cellClass: '.cell-name',
|
|
textToMatch: 'Spicy Mac',
|
|
urlUtil: menuItemsURL,
|
|
})
|
|
|
|
await selectDocumentTenant({
|
|
page,
|
|
payload,
|
|
tenant: 'Steel Cat',
|
|
})
|
|
|
|
await saveDocAndAssert(page)
|
|
})
|
|
|
|
test('should filter internal links in Lexical editor', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
await page.goto(menuItemsURL.create)
|
|
await selectDocumentTenant({
|
|
page,
|
|
payload,
|
|
tenant: 'Blue Dog',
|
|
})
|
|
const editor = page.locator('[data-lexical-editor="true"]')
|
|
await editor.focus()
|
|
await page.keyboard.type('Hello World')
|
|
await page.keyboard.down('Shift')
|
|
for (let i = 0; i < 'World'.length; i++) {
|
|
await page.keyboard.press('ArrowLeft')
|
|
}
|
|
await page.keyboard.up('Shift')
|
|
await page.locator('.toolbar-popup__button-link').click()
|
|
await expect(page.locator('.lexical-link-edit-drawer')).toBeVisible()
|
|
const linkRadio = page.locator('.radio-input__styled-radio').last()
|
|
await expect(linkRadio).toBeVisible()
|
|
await linkRadio.click({
|
|
delay: 100,
|
|
})
|
|
await page.locator('.drawer__content').locator('.rs__input').click()
|
|
await expect(page.getByText('Chorizo Con Queso')).toBeVisible()
|
|
await expect(page.getByText('Pretzel Bites')).toBeHidden()
|
|
})
|
|
})
|
|
|
|
test.describe('Globals', () => {
|
|
test('should redirect list view to edit view', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
await page.goto(globalMenuURL.list)
|
|
await expect(page.locator('.collection-edit')).toBeVisible()
|
|
})
|
|
|
|
test('should redirect from create to edit view when tenant already has content', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
await setTenantFilter({
|
|
urlUtil: tenantsURL,
|
|
page,
|
|
tenant: 'Blue Dog',
|
|
})
|
|
await page.goto(globalMenuURL.list)
|
|
await expect(page.locator('.collection-edit')).toBeVisible()
|
|
await expect(page.locator('#field-title')).toHaveValue('Blue Dog Menu')
|
|
})
|
|
|
|
test('should prompt leave without saving changes modal when switching tenants', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await setTenantFilter({
|
|
urlUtil: tenantsURL,
|
|
page,
|
|
tenant: 'Blue Dog',
|
|
})
|
|
|
|
await page.goto(globalMenuURL.create)
|
|
|
|
// Attempt to switch tenants with unsaved changes
|
|
await page.fill('#field-title', 'New Global Menu Name')
|
|
await switchGlobalDocTenant({
|
|
page,
|
|
tenant: 'Steel Cat',
|
|
})
|
|
|
|
const confirmationModal = page.locator('#confirm-leave-without-saving')
|
|
await expect(confirmationModal).toBeVisible()
|
|
await expect(
|
|
confirmationModal.getByText(
|
|
'Your changes have not been saved. If you leave now, you will lose your changes.',
|
|
),
|
|
).toBeVisible()
|
|
|
|
await confirmationModal.locator('#confirm-action').click()
|
|
await expect(page.locator('#confirm-leave-without-saving')).toBeHidden()
|
|
await page.goto(menuItemsURL.list)
|
|
await expect
|
|
.poll(async () => {
|
|
return await getSelectInputValue({
|
|
selectLocator: page.locator('.tenant-selector'),
|
|
multiSelect: false,
|
|
})
|
|
})
|
|
.toBe('Steel Cat')
|
|
})
|
|
|
|
test('should navigate to globals with autosave enabled', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
await page.goto(tenantsURL.list)
|
|
await clearTenantFilter({ page })
|
|
await page.goto(autosaveGlobalURL.list)
|
|
await expect(page.locator('.doc-header__title')).toBeVisible()
|
|
const docID = (await page.locator('.render-title').getAttribute('data-doc-id')) as string
|
|
await expect.poll(() => docID).not.toBeUndefined()
|
|
const globalTenant = await getSelectedTenantFilterName({ page, payload })
|
|
const autosaveGlobal = await payload.find({
|
|
collection: autosaveGlobalSlug,
|
|
where: {
|
|
id: {
|
|
equals: docID,
|
|
},
|
|
'tenant.name': {
|
|
equals: globalTenant,
|
|
},
|
|
},
|
|
})
|
|
await expect.poll(() => autosaveGlobal?.totalDocs).toBe(1)
|
|
await expect.poll(() => autosaveGlobal?.docs?.[0]?.tenant).toBeDefined()
|
|
})
|
|
})
|
|
|
|
test.describe('Tenant Selector', () => {
|
|
test('should populate tenant selector on login', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Blue Dog', 'Steel Cat', 'Public Tenant', 'Anchor Bar'].sort())
|
|
})
|
|
|
|
test('should populate the tenant selector after logout with 1 tenant user', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.blueDog,
|
|
})
|
|
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Blue Dog', 'Steel Cat', 'Public Tenant', 'Anchor Bar'].sort())
|
|
})
|
|
|
|
test('should show all tenants for userHasAccessToAllTenants users', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Blue Dog', 'Steel Cat', 'Public Tenant', 'Anchor Bar'].sort())
|
|
})
|
|
|
|
test('should only show users assigned tenants', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.owner,
|
|
})
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Blue Dog', 'Anchor Bar'].sort())
|
|
})
|
|
|
|
test('should not show public tenants to users with assigned tenants', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.owner,
|
|
})
|
|
|
|
await page.goto(tenantsURL.list)
|
|
await clearTenantFilter({ page })
|
|
|
|
await expect(
|
|
page.locator('.collection-list .table .cell-name', {
|
|
hasText: 'Public Tenant',
|
|
}),
|
|
).toBeHidden()
|
|
})
|
|
|
|
test('should update the tenant name in the selector when editing a tenant', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await goToListDoc({
|
|
cellClass: '.cell-name',
|
|
page,
|
|
textToMatch: 'Blue Dog',
|
|
urlUtil: tenantsURL,
|
|
})
|
|
|
|
await expect(page.locator('#field-name')).toBeVisible()
|
|
await page.locator('#field-name').fill('Red Dog')
|
|
await saveDocAndAssert(page)
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
// Check the tenant selector
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Red Dog', 'Steel Cat', 'Public Tenant', 'Anchor Bar'].sort())
|
|
|
|
await goToListDoc({
|
|
cellClass: '.cell-name',
|
|
page,
|
|
textToMatch: 'Red Dog',
|
|
urlUtil: tenantsURL,
|
|
})
|
|
|
|
// Change the tenant back to the original name
|
|
await page.locator('#field-name').fill('Blue Dog')
|
|
await saveDocAndAssert(page)
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Blue Dog', 'Steel Cat', 'Public Tenant', 'Anchor Bar'].sort())
|
|
})
|
|
|
|
test('should add tenant to the selector when creating a new tenant', async () => {
|
|
await loginClientSide({
|
|
page,
|
|
serverURL,
|
|
data: credentials.admin,
|
|
})
|
|
|
|
await page.goto(tenantsURL.create)
|
|
await wait(300)
|
|
await expect(page.locator('#field-name')).toBeVisible()
|
|
await expect(page.locator('#field-domain')).toBeVisible()
|
|
|
|
await page.locator('#field-name').fill('House Rules')
|
|
await page.locator('#field-domain').fill('house-rules.com')
|
|
await saveDocAndAssert(page)
|
|
|
|
await page.goto(tenantsURL.list)
|
|
|
|
// Check the tenant selector
|
|
await expect
|
|
.poll(async () => {
|
|
return (await getTenantOptions({ page })).sort()
|
|
})
|
|
.toEqual(['Blue Dog', 'Steel Cat', 'Anchor Bar', 'Public Tenant', 'House Rules'].sort())
|
|
})
|
|
})
|
|
})
|
|
|
|
/**
|
|
* Helper Functions
|
|
*/
|
|
async function getTenantOptions({ page }: { page: Page }): Promise<string[]> {
|
|
await openNav(page)
|
|
return await getSelectInputOptions({
|
|
selectLocator: page.locator('.tenant-selector'),
|
|
})
|
|
}
|
|
|
|
async function openAssignTenantModal({
|
|
page,
|
|
payload,
|
|
}: {
|
|
page: Page
|
|
payload: PayloadTestSDK<Config>
|
|
}): Promise<void> {
|
|
const assignTenantModal = page.locator('#assign-tenant-field-modal')
|
|
|
|
const globalTenant = await getSelectedTenantFilterName({ page, payload })
|
|
if (!globalTenant) {
|
|
await expect(assignTenantModal).toBeVisible()
|
|
return
|
|
}
|
|
|
|
// Open the assign tenant modal
|
|
const docControlsPopup = page.locator('.doc-controls__popup')
|
|
const docControlsButton = docControlsPopup.locator('.popup-button')
|
|
await expect(docControlsButton).toBeVisible()
|
|
await docControlsButton.click()
|
|
|
|
const assignTenantButtonLocator = docControlsPopup.locator('button', { hasText: 'Assign Site' })
|
|
await expect(assignTenantButtonLocator).toBeVisible()
|
|
await assignTenantButtonLocator.click()
|
|
|
|
await expect(assignTenantModal).toBeVisible()
|
|
}
|
|
|
|
async function selectDocumentTenant({
|
|
page,
|
|
tenant,
|
|
action = 'confirm',
|
|
payload,
|
|
}: {
|
|
action?: 'cancel' | 'confirm'
|
|
page: Page
|
|
payload: PayloadTestSDK<Config>
|
|
tenant: string
|
|
}): Promise<void> {
|
|
await closeNav(page)
|
|
await openAssignTenantModal({ page, payload })
|
|
await selectInput({
|
|
selectLocator: page.locator('.tenantField'),
|
|
option: tenant,
|
|
multiSelect: false,
|
|
})
|
|
|
|
const assignTenantModal = page.locator('#assign-tenant-field-modal')
|
|
if (action === 'confirm') {
|
|
await assignTenantModal.locator('button', { hasText: 'Confirm' }).click()
|
|
await expect(assignTenantModal).toBeHidden()
|
|
} else {
|
|
await assignTenantModal.locator('button', { hasText: 'Cancel' }).click()
|
|
await expect(assignTenantModal).toBeHidden()
|
|
}
|
|
}
|
|
|
|
async function getSelectedTenantFilterName({
|
|
page,
|
|
payload,
|
|
}: {
|
|
page: Page
|
|
payload: PayloadTestSDK<Config>
|
|
}): Promise<string | undefined> {
|
|
const cookies = await page.context().cookies()
|
|
const tenantIDFromCookie = cookies.find((c) => c.name === 'payload-tenant')?.value
|
|
if (tenantIDFromCookie) {
|
|
const tenant = await payload.find({
|
|
collection: 'tenants',
|
|
where: {
|
|
id: {
|
|
equals: tenantIDFromCookie,
|
|
},
|
|
},
|
|
})
|
|
return tenant?.docs?.[0]?.name || undefined
|
|
}
|
|
|
|
return undefined
|
|
}
|
|
|
|
async function setTenantFilter({
|
|
page,
|
|
tenant,
|
|
urlUtil,
|
|
}: {
|
|
page: Page
|
|
tenant: string
|
|
urlUtil: AdminUrlUtil
|
|
}): Promise<void> {
|
|
await page.goto(urlUtil.list)
|
|
await openNav(page)
|
|
await selectInput({
|
|
selectLocator: page.locator('.tenant-selector'),
|
|
option: tenant,
|
|
multiSelect: false,
|
|
})
|
|
}
|
|
|
|
async function switchGlobalDocTenant({
|
|
page,
|
|
tenant,
|
|
}: {
|
|
page: Page
|
|
tenant: string
|
|
}): Promise<void> {
|
|
await openNav(page)
|
|
await selectInput({
|
|
selectLocator: page.locator('.tenant-selector'),
|
|
option: tenant,
|
|
multiSelect: false,
|
|
})
|
|
}
|
|
|
|
async function clearTenantFilter({ page }: { page: Page }): Promise<void> {
|
|
await openNav(page)
|
|
await clearSelectInput({
|
|
selectLocator: page.locator('.tenant-selector'),
|
|
})
|
|
await closeNav(page)
|
|
}
|