Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,10 @@ const GlossaryHeader = ({
Operation.EditAll,
ResourceEntity.GLOSSARY_TERM,
globalPermissions
),
[globalPermissions]
) ||
permissions[Operation.All] ||
permissions[Operation.EditAll],
[globalPermissions, permissions]
);

// To fetch the latest glossary data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,57 @@ describe('GlossaryHeader component', () => {
screen.queryByText('ChangeParentHierarchyComponent')
).not.toBeInTheDocument();
});

describe('import/export visibility with conditional policies', () => {
it('should show import/export when globalPermissions denies but entity-level permissions allow (isOwner condition satisfied)', async () => {
// Simulate a conditional policy: resource-level check returns false because
// the backend cannot evaluate isOwner() without entity context.
mockGlossaryTermPermission.All = false;
mockGlossaryTermPermission.EditAll = false;

// Entity-level permissions are fetched with the glossary ID so the backend
// correctly evaluates isOwner() and returns Allow.
mockContext.type = EntityType.GLOSSARY;
mockContext.permissions = { ...DEFAULT_ENTITY_PERMISSION, EditAll: true };

render(
<GlossaryHeader
updateVote={mockOnUpdateVote}
Comment on lines +326 to +340
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Quality: Mutable shared test state not reset between tests

The new describe block mutates module-level mockGlossaryTermPermission and mockContext (lines 330-336, 358-365) without resetting them afterward. While this matches the existing pattern in the file, the new tests depend on and further propagate leaked state. For example, the first new test (line 327) inherits mockContext.type from whatever the previous test set it to (line 233 sets it to GLOSSARY_TERM), then overrides it to GLOSSARY at line 335 — which then leaks into the second new test.

Currently this doesn't cause failures because test execution order is deterministic and these are the last tests, but it's fragile. Adding a beforeEach or afterEach in the new describe block to snapshot and restore the shared objects would make these tests order-independent.

Suggested fix:

describe('import/export visibility with conditional policies', () => {
  let origPermission: typeof mockGlossaryTermPermission;
  let origContext: typeof mockContext;

  beforeEach(() => {
    origPermission = { ...mockGlossaryTermPermission };
    origContext = { ...mockContext };
  });

  afterEach(() => {
    Object.assign(mockGlossaryTermPermission, origPermission);
    Object.assign(mockContext, origContext);
  });
  // ... tests
});

Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion

onAddGlossaryTerm={mockOnDelete}
onDelete={mockOnDelete}
/>
);

await act(async () => {
fireEvent.click(screen.getByTestId('manage-button'));
});

expect(screen.queryByText('label.import')).toBeInTheDocument();
expect(screen.queryByText('label.export')).toBeInTheDocument();
});

it('should hide import/export when both globalPermissions and entity-level permissions deny', async () => {
// Both resource-level and entity-level permissions deny — user is not the
// owner and no other condition grants access.
mockGlossaryTermPermission.All = false;
mockGlossaryTermPermission.EditAll = false;

mockContext.type = EntityType.GLOSSARY;
mockContext.permissions = {
...DEFAULT_ENTITY_PERMISSION,
All: false,
EditAll: false,
};

render(
<GlossaryHeader
updateVote={mockOnUpdateVote}
onAddGlossaryTerm={mockOnDelete}
onDelete={mockOnDelete}
/>
);

expect(screen.queryByTestId('manage-button')).not.toBeInTheDocument();
});
});
});
Loading