Skip to content

Commit 7ea5b07

Browse files
authored
change escalation chains searching to allow for partial searching (#1578)
# Which issue(s) this PR fixes Previously if you had an Escalation Chain named "Something Critical" and tried searching for "Critical", it would return no results. This was because the backend was using a "starts-with" search on the `name` attribute. This PR changes that to use "partial searching" + adds a few e2e test cases. ## Checklist - [x] Tests updated - [ ] Documentation added (N/A) - [x] `CHANGELOG.md` updated
1 parent 046d1dc commit 7ea5b07

File tree

8 files changed

+45
-7
lines changed

8 files changed

+45
-7
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Updated wording throughout plugin to use 'Alert Group' instead of 'Incident' ([1565](https://github.com/grafana/oncall/pull/1565),
1818
[1576](https://github.com/grafana/oncall/pull/1576))
1919
- Filtering for Editors/Admins was added to rotation form. It is not allowed to assign Viewer to rotation ([1124](https://github.com/grafana/oncall/issues/1124))
20+
- Modified search behaviour on the Escalation Chains page to allow for "partial searching" ([1578](https://github.com/grafana/oncall/pull/1578))
2021

2122
### Fixed
2223

engine/apps/api/views/escalation_chain.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class EscalationChainViewSet(
4646
}
4747

4848
filter_backends = [SearchFilter]
49-
search_fields = ("^name",)
49+
search_fields = ("name",)
5050

5151
serializer_class = EscalationChainSerializer
5252
list_serializer_class = EscalationChainListSerializer
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { test, expect, Page } from '@playwright/test';
2+
import { configureOnCallPlugin } from '../utils/configurePlugin';
3+
import { generateRandomValue } from '../utils/forms';
4+
import { createEscalationChain } from '../utils/escalationChain';
5+
6+
test.beforeEach(async ({ page }) => {
7+
await configureOnCallPlugin(page);
8+
});
9+
10+
const assertEscalationChainSearchWorks = async (
11+
page: Page,
12+
searchTerm: string,
13+
escalationChainFullName: string
14+
): Promise<void> => {
15+
await page.getByTestId('escalation-chain-search-input').fill(searchTerm);
16+
17+
// wait for the API call(s) to finish
18+
await page.waitForLoadState('networkidle');
19+
20+
await expect(page.getByTestId('escalation-chains-list')).toHaveText(escalationChainFullName);
21+
};
22+
23+
test('searching allows case-insensitive partial matches', async ({ page }) => {
24+
const escalationChainName = `${generateRandomValue()} ${generateRandomValue()}`;
25+
const [firstHalf, secondHalf] = escalationChainName.split(' ');
26+
27+
await createEscalationChain(page, escalationChainName);
28+
29+
await assertEscalationChainSearchWorks(page, firstHalf, escalationChainName);
30+
await assertEscalationChainSearchWorks(page, firstHalf.toUpperCase(), escalationChainName);
31+
await assertEscalationChainSearchWorks(page, firstHalf.toLowerCase(), escalationChainName);
32+
33+
await assertEscalationChainSearchWorks(page, secondHalf, escalationChainName);
34+
await assertEscalationChainSearchWorks(page, secondHalf.toUpperCase(), escalationChainName);
35+
await assertEscalationChainSearchWorks(page, secondHalf.toLowerCase(), escalationChainName);
36+
});

grafana-plugin/integration-tests/utils/alertGroup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const incidentTimelineContainsStep = async (page: Page, triggeredStepText: strin
1515
return Promise.resolve(false);
1616
}
1717

18-
if (!page.locator('div[data-testid="incident-timeline-list"]').getByText(triggeredStepText)) {
18+
if (!page.getByTestId('incident-timeline-list').getByText(triggeredStepText)) {
1919
await page.reload({ waitUntil: 'networkidle' });
2020
return incidentTimelineContainsStep(page, triggeredStepText, (retryNum += 1));
2121
}

grafana-plugin/integration-tests/utils/escalationChain.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const escalationStepValuePlaceholder: Record<EscalationStep, string> = {
1616
export const createEscalationChain = async (
1717
page: Page,
1818
escalationChainName: string,
19-
escalationStep: EscalationStep | null,
20-
escalationStepValue: string | null
19+
escalationStep?: EscalationStep,
20+
escalationStepValue?: string
2121
): Promise<void> => {
2222
// go to the escalation chains page
2323
await goToOnCallPage(page, 'escalations');
@@ -32,7 +32,7 @@ export const createEscalationChain = async (
3232
await clickButton({ page, buttonText: 'Create' });
3333
await page.waitForSelector(`text=${escalationChainName}`);
3434

35-
if (!escalationStep) {
35+
if (!escalationStep || !escalationStepValue) {
3636
return;
3737
}
3838

grafana-plugin/integration-tests/utils/integrations.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const createIntegrationAndSendDemoAlert = async (
2424
await fillInInput(page, 'div[data-testid="edit-integration-name-modal"] >> input', integrationName);
2525
await clickButton({ page, buttonText: 'Update' });
2626

27-
const integrationSettingsElement = page.locator('div[data-testid="integration-settings"]');
27+
const integrationSettingsElement = page.getByTestId('integration-settings');
2828

2929
// assign the escalation chain to the integration
3030
await selectDropdownValue({

grafana-plugin/src/components/EscalationsFilters/EscalationsFilters.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const EscalationsFilters: FC<EscalationsFiltersProps> = (props) => {
3939
<div className={cx('root')}>
4040
<Input
4141
autoFocus
42+
data-testid="escalation-chain-search-input"
4243
className={cx('search')}
4344
prefix={<Icon name="search" />}
4445
placeholder="Search escalations..."

grafana-plugin/src/pages/escalation-chains/EscalationChains.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class EscalationChainsPage extends React.Component<EscalationChainsPageProps, Es
175175
</Button>
176176
</WithPermissionControlTooltip>
177177
)}
178-
<div className={cx('escalations-list')}>
178+
<div className={cx('escalations-list')} data-testid="escalation-chains-list">
179179
{searchResult ? (
180180
<GList
181181
autoScroll

0 commit comments

Comments
 (0)