|
13 | 13 | import { expect, test } from '@playwright/test'; |
14 | 14 | import { DELETE_TERM } from '../../constant/common'; |
15 | 15 | import { GlobalSettingOptions } from '../../constant/settings'; |
| 16 | +import { TableClass } from '../../support/entity/TableClass'; |
| 17 | +import { TeamClass } from '../../support/team/TeamClass'; |
16 | 18 | import { |
| 19 | + createNewPage, |
17 | 20 | redirectToHomePage, |
18 | 21 | toastNotification, |
19 | 22 | uuid, |
20 | 23 | } from '../../utils/common'; |
21 | 24 | import { settingClick } from '../../utils/sidebar'; |
22 | | -import { addTeamHierarchy, getNewTeamDetails } from '../../utils/team'; |
| 25 | +import { |
| 26 | + addTeamHierarchy, |
| 27 | + addTeamOwnerToEntity, |
| 28 | + getNewTeamDetails, |
| 29 | + verifyAssetsInTeamsPage, |
| 30 | +} from '../../utils/team'; |
23 | 31 |
|
24 | 32 | // use the admin user to login |
25 | 33 | test.use({ storageState: 'playwright/.auth/admin.json' }); |
@@ -144,3 +152,115 @@ test.describe('Add Nested Teams and Test TeamsSelectable', () => { |
144 | 152 | ); |
145 | 153 | }); |
146 | 154 | }); |
| 155 | + |
| 156 | +// ── Self-contained asset count aggregation test ── |
| 157 | +// Creates hierarchy (API): aggBU (BusinessUnit) → aggGroup (Group) |
| 158 | +// Creates 1 table (API), assigns Group as owner via UI, |
| 159 | +// then verifies asset count + assets tab on the parent team via UI. |
| 160 | + |
| 161 | +const aggId = uuid(); |
| 162 | +const aggBUName = `agg-bu-${aggId}`; |
| 163 | +const aggGroupName = `agg-grp-${aggId}`; |
| 164 | + |
| 165 | +const aggBU = new TeamClass({ |
| 166 | + name: aggBUName, |
| 167 | + displayName: aggBUName, |
| 168 | + description: 'Aggregation test BU', |
| 169 | + teamType: 'BusinessUnit', |
| 170 | +}); |
| 171 | +const aggGroup = new TeamClass({ |
| 172 | + name: aggGroupName, |
| 173 | + displayName: aggGroupName, |
| 174 | + description: 'Aggregation test Group', |
| 175 | + teamType: 'Group', |
| 176 | +}); |
| 177 | + |
| 178 | +const aggTable = new TableClass(); |
| 179 | + |
| 180 | +test.describe('Verify Asset Count Aggregation', () => { |
| 181 | + test.use({ storageState: 'playwright/.auth/admin.json' }); |
| 182 | + |
| 183 | + test.beforeAll('Setup hierarchy and table', async ({ browser }) => { |
| 184 | + const { apiContext, afterAction } = await createNewPage(browser); |
| 185 | + |
| 186 | + // Create BU → Group hierarchy via API |
| 187 | + await aggBU.create(apiContext); |
| 188 | + |
| 189 | + const grpRes = await apiContext.post('/api/v1/teams', { |
| 190 | + data: { ...aggGroup.data, parents: [aggBU.responseData.id] }, |
| 191 | + }); |
| 192 | + expect(grpRes.ok()).toBeTruthy(); |
| 193 | + aggGroup.responseData = await grpRes.json(); |
| 194 | + |
| 195 | + // Create a table via API |
| 196 | + await aggTable.create(apiContext); |
| 197 | + |
| 198 | + await afterAction(); |
| 199 | + }); |
| 200 | + |
| 201 | + test.afterAll('Cleanup', async ({ browser }) => { |
| 202 | + const { apiContext, afterAction } = await createNewPage(browser); |
| 203 | + await aggTable.delete(apiContext); |
| 204 | + await aggBU.delete(apiContext); |
| 205 | + await afterAction(); |
| 206 | + }); |
| 207 | + |
| 208 | + test('Assign asset to sub-team and verify aggregated count on parent', async ({ |
| 209 | + page, |
| 210 | + }) => { |
| 211 | + test.slow(); |
| 212 | + await redirectToHomePage(page); |
| 213 | + // Step 1: Visit the table page and assign the Group team as owner (via UI) |
| 214 | + await addTeamOwnerToEntity(page, aggTable, aggGroup); |
| 215 | + |
| 216 | + // Step 2: Verify the asset appears in the Group team's Assets tab |
| 217 | + await verifyAssetsInTeamsPage(page, aggTable, aggGroup, 1); |
| 218 | + |
| 219 | + // Step 3: Navigate to the parent BU team page |
| 220 | + await redirectToHomePage(page); |
| 221 | + const getOrganizationResponse = page.waitForResponse( |
| 222 | + '/api/v1/teams/name/*' |
| 223 | + ); |
| 224 | + await settingClick(page, GlobalSettingOptions.TEAMS); |
| 225 | + await getOrganizationResponse; |
| 226 | + |
| 227 | + // Step 3: Verify asset count for the BU in the Organization-level table |
| 228 | + // Wait for skeleton in the BU row to resolve and verify aggregated count |
| 229 | + const buRow = page.locator(`[data-row-key="${aggBUName}"]`); |
| 230 | + await buRow.locator('.ant-skeleton-active').waitFor({ state: 'hidden' }); |
| 231 | + await expect(buRow.getByTestId('asset-count')).toHaveText('1'); |
| 232 | + |
| 233 | + // Click on the BU team to see its children |
| 234 | + const permissionResponse = page.waitForResponse( |
| 235 | + '/api/v1/permissions/team/name/*' |
| 236 | + ); |
| 237 | + await page.getByRole('link', { name: aggBUName }).click(); |
| 238 | + await permissionResponse; |
| 239 | + |
| 240 | + // Step 4: Verify asset count shown in the hierarchy table for the Group child |
| 241 | + // Wait for the skeleton loader to disappear, then assert the count |
| 242 | + const groupRow = page.locator( |
| 243 | + `[data-row-key="${aggGroupName}"]` |
| 244 | + ); |
| 245 | + |
| 246 | + await groupRow.locator('.ant-skeleton-active').waitFor({ state: 'hidden' }); |
| 247 | + |
| 248 | + await expect(groupRow.getByTestId('asset-count')).toHaveText('1'); |
| 249 | + |
| 250 | + // Step 5: Open the Assets tab on the BU team page and verify aggregated count |
| 251 | + const assetsRes = page.waitForResponse('/api/v1/search/query?*size=15*'); |
| 252 | + await page.getByTestId('assets').click(); |
| 253 | + await assetsRes; |
| 254 | + |
| 255 | + // Verify the BU's Assets tab shows count = 1 (aggregated from Group child) |
| 256 | + await expect( |
| 257 | + page.getByTestId('assets').getByTestId('filter-count') |
| 258 | + ).toContainText('1'); |
| 259 | + |
| 260 | + // Verify the table card is visible in the BU's Assets tab |
| 261 | + const tableFqn = aggTable.entityResponseData?.['fullyQualifiedName']; |
| 262 | + await expect( |
| 263 | + page.locator(`[data-testid="table-data-card_${tableFqn}"]`) |
| 264 | + ).toBeVisible(); |
| 265 | + }); |
| 266 | +}); |
0 commit comments