Skip to content

Commit 77f2856

Browse files
anuj-kumaryclaude
andcommitted
test(playwright): verify inverse relation types display correctly on both sides
Add E2E tests for #29687 that verify the UI shows the correct relation perspective on each side of an asymmetric relation (narrower/broader, hasPart/partOf) and that the correct type persists after page reload. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a7cfbbb commit 77f2856

1 file changed

Lines changed: 153 additions & 0 deletions

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright 2026 Collate.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
import test, { expect } from '@playwright/test';
14+
import { SidebarItem } from '../../../constant/sidebar';
15+
import { Glossary } from '../../../support/glossary/Glossary';
16+
import { GlossaryTerm } from '../../../support/glossary/GlossaryTerm';
17+
import { getApiContext, redirectToHomePage } from '../../../utils/common';
18+
import {
19+
addRelatedTermsByRelationType,
20+
selectActiveGlossary,
21+
selectActiveGlossaryTerm,
22+
} from '../../../utils/glossary';
23+
import { sidebarClick } from '../../../utils/sidebar';
24+
25+
test.use({
26+
storageState: 'playwright/.auth/admin.json',
27+
});
28+
29+
test.describe('Glossary Term — Inverse Relation Display (#29687)', () => {
30+
test.beforeEach(async ({ page }) => {
31+
await redirectToHomePage(page);
32+
});
33+
34+
test('should show correct inverse relation type on the target term after reload', async ({
35+
page,
36+
}) => {
37+
const { apiContext, afterAction } = await getApiContext(page);
38+
const glossary = new Glossary();
39+
const termFrom = new GlossaryTerm(glossary);
40+
const termTo = new GlossaryTerm(glossary);
41+
42+
try {
43+
await glossary.create(apiContext);
44+
await termFrom.create(apiContext);
45+
await termTo.create(apiContext);
46+
47+
await sidebarClick(page, SidebarItem.GLOSSARY);
48+
await selectActiveGlossary(page, glossary.data.displayName);
49+
await selectActiveGlossaryTerm(page, termFrom.data.displayName);
50+
51+
await addRelatedTermsByRelationType(page, [
52+
{ relationTypeLabel: 'Narrower', terms: [termTo] },
53+
]);
54+
55+
const termToName =
56+
termTo.responseData?.displayName ?? termTo.data.displayName;
57+
58+
await expect(page.getByTestId(termToName)).toBeVisible();
59+
await expect(
60+
page
61+
.getByTestId('related-term-container')
62+
.getByText('Narrower', { exact: true })
63+
).toBeVisible();
64+
65+
await selectActiveGlossaryTerm(page, termTo.data.displayName);
66+
67+
const termFromName =
68+
termFrom.responseData?.displayName ?? termFrom.data.displayName;
69+
70+
await expect(page.getByTestId(termFromName)).toBeVisible();
71+
await expect(
72+
page
73+
.getByTestId('related-term-container')
74+
.getByText('Broader', { exact: true })
75+
).toBeVisible();
76+
77+
const reloadRes = page.waitForResponse(
78+
`/api/v1/glossaryTerms/name/*${encodeURIComponent(
79+
termTo.data.name
80+
)}*`
81+
);
82+
await page.reload();
83+
await reloadRes;
84+
85+
await expect(page.getByTestId(termFromName)).toBeVisible();
86+
await expect(
87+
page
88+
.getByTestId('related-term-container')
89+
.getByText('Broader', { exact: true })
90+
).toBeVisible();
91+
} finally {
92+
await termFrom.delete(apiContext);
93+
await termTo.delete(apiContext);
94+
await glossary.delete(apiContext);
95+
await afterAction();
96+
}
97+
});
98+
99+
test('should show different inverse types on each side of the same relation', async ({
100+
page,
101+
}) => {
102+
const { apiContext, afterAction } = await getApiContext(page);
103+
const glossary = new Glossary();
104+
const termParent = new GlossaryTerm(glossary);
105+
const termChild = new GlossaryTerm(glossary);
106+
107+
try {
108+
await glossary.create(apiContext);
109+
await termParent.create(apiContext);
110+
await termChild.create(apiContext);
111+
112+
await sidebarClick(page, SidebarItem.GLOSSARY);
113+
await selectActiveGlossary(page, glossary.data.displayName);
114+
await selectActiveGlossaryTerm(page, termParent.data.displayName);
115+
116+
await addRelatedTermsByRelationType(page, [
117+
{ relationTypeLabel: 'Has Part', terms: [termChild] },
118+
]);
119+
120+
const termChildName =
121+
termChild.responseData?.displayName ?? termChild.data.displayName;
122+
const termParentName =
123+
termParent.responseData?.displayName ?? termParent.data.displayName;
124+
125+
await expect(
126+
page
127+
.getByTestId('related-term-container')
128+
.getByText('Has Part', { exact: true })
129+
).toBeVisible();
130+
await expect(page.getByTestId(termChildName)).toBeVisible();
131+
132+
await selectActiveGlossaryTerm(page, termChild.data.displayName);
133+
134+
await expect(
135+
page
136+
.getByTestId('related-term-container')
137+
.getByText('Part Of', { exact: true })
138+
).toBeVisible();
139+
await expect(page.getByTestId(termParentName)).toBeVisible();
140+
141+
await expect(
142+
page
143+
.getByTestId('related-term-container')
144+
.getByText('Has Part', { exact: true })
145+
).not.toBeVisible();
146+
} finally {
147+
await termParent.delete(apiContext);
148+
await termChild.delete(apiContext);
149+
await glossary.delete(apiContext);
150+
await afterAction();
151+
}
152+
});
153+
});

0 commit comments

Comments
 (0)