Skip to content

Commit 70712bd

Browse files
authored
test: stream_routes in services (#3113)
* feat(services/routes): filter by `service_id` * feat(services): filter stream_routes by service_id * fix: type * test: routes in services * test: stream_routes in services * Revert "test: stream_routes in services" This reverts commit 77d7803. * test: stream_routes in services * chore: rm stream_routes pom * feat: add only show routes with service_id case * test: add not show other service route case * feat: add services stream_routes pom * test: stream_routes in services * fix: use exact match * chore: rollback useless change
1 parent 91955b6 commit 70712bd

File tree

3 files changed

+543
-0
lines changed

3 files changed

+543
-0
lines changed

e2e/pom/services.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ const locator = {
2929
page.getByRole('tab', { name: 'Routes', exact: true }),
3030
getAddRouteBtn: (page: Page) =>
3131
page.getByRole('button', { name: 'Add Route', exact: true }),
32+
// Service stream routes locators
33+
getServiceStreamRoutesTab: (page: Page) =>
34+
page.getByRole('tab', { name: 'Stream Routes', exact: true }),
35+
getAddStreamRouteBtn: (page: Page) =>
36+
page.getByRole('button', { name: 'Add Stream Route', exact: true }),
3237
};
3338

3439
const assert = {
@@ -81,6 +86,36 @@ const assert = {
8186
const title = page.getByRole('heading', { name: 'Route Detail' });
8287
await expect(title).toBeVisible();
8388
},
89+
// Service stream routes assertions
90+
isServiceStreamRoutesPage: async (page: Page) => {
91+
await expect(page).toHaveURL(
92+
(url) =>
93+
url.pathname.includes('/services/detail') &&
94+
url.pathname.includes('/stream_routes')
95+
);
96+
// Wait for page to load completely
97+
await page.waitForLoadState('networkidle');
98+
const title = page.getByRole('heading', { name: 'Stream Routes' });
99+
await expect(title).toBeVisible();
100+
},
101+
isServiceStreamRouteAddPage: async (page: Page) => {
102+
await expect(page).toHaveURL(
103+
(url) =>
104+
url.pathname.includes('/services/detail') &&
105+
url.pathname.includes('/stream_routes/add')
106+
);
107+
const title = page.getByRole('heading', { name: 'Add Stream Route' });
108+
await expect(title).toBeVisible();
109+
},
110+
isServiceStreamRouteDetailPage: async (page: Page) => {
111+
await expect(page).toHaveURL(
112+
(url) =>
113+
url.pathname.includes('/services/detail') &&
114+
url.pathname.includes('/stream_routes/detail')
115+
);
116+
const title = page.getByRole('heading', { name: 'Stream Route Detail' });
117+
await expect(title).toBeVisible();
118+
},
84119
};
85120

86121
const goto = {
@@ -92,6 +127,12 @@ const goto = {
92127
uiGoto(page, '/services/detail/$id/routes/add', {
93128
id: serviceId,
94129
}),
130+
toServiceStreamRoutes: (page: Page, serviceId: string) =>
131+
uiGoto(page, '/services/detail/$id/stream_routes', { id: serviceId }),
132+
toServiceStreamRouteAdd: (page: Page, serviceId: string) =>
133+
uiGoto(page, '/services/detail/$id/stream_routes/add', {
134+
id: serviceId,
135+
}),
95136
};
96137

97138
export const servicesPom = {
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
import { servicesPom } from '@e2e/pom/services';
18+
import { randomId } from '@e2e/utils/common';
19+
import { e2eReq } from '@e2e/utils/req';
20+
import { test } from '@e2e/utils/test';
21+
import { uiHasToastMsg } from '@e2e/utils/ui';
22+
import { expect } from '@playwright/test';
23+
24+
import { deleteAllServices, postServiceReq } from '@/apis/services';
25+
import { deleteAllStreamRoutes } from '@/apis/stream_routes';
26+
27+
const serviceName = randomId('test-service');
28+
const streamRouteServerAddr = '127.0.0.1';
29+
const streamRouteServerPort = 8080;
30+
const updatedStreamRouteServerAddr = '127.0.0.2';
31+
const updatedStreamRouteServerPort = 8081;
32+
33+
let testServiceId: string;
34+
35+
test.beforeAll(async () => {
36+
await deleteAllStreamRoutes(e2eReq);
37+
await deleteAllServices(e2eReq);
38+
39+
// Create a test service for testing service stream routes
40+
const serviceResponse = await postServiceReq(e2eReq, {
41+
name: serviceName,
42+
desc: 'Test service for stream route CRUD testing',
43+
});
44+
45+
testServiceId = serviceResponse.data.value.id;
46+
});
47+
48+
test.afterAll(async () => {
49+
await deleteAllStreamRoutes(e2eReq);
50+
await deleteAllServices(e2eReq);
51+
});
52+
53+
test('should CRUD stream route under service', async ({ page }) => {
54+
// Navigate to service detail page
55+
await servicesPom.toIndex(page);
56+
await servicesPom.isIndexPage(page);
57+
58+
// Click on the service to go to detail page
59+
await page
60+
.getByRole('row', { name: serviceName })
61+
.getByRole('button', { name: 'View' })
62+
.click();
63+
await servicesPom.isDetailPage(page);
64+
65+
// Navigate to Stream Routes tab
66+
await servicesPom.getServiceStreamRoutesTab(page).click();
67+
await servicesPom.isServiceStreamRoutesPage(page);
68+
69+
await servicesPom.getAddStreamRouteBtn(page).click();
70+
await servicesPom.isServiceStreamRouteAddPage(page);
71+
72+
await test.step('can submit without any fields (no required fields)', async () => {
73+
// Verify service_id is pre-filled and disabled (since it's read-only in service context)
74+
const serviceIdField = page.getByLabel('Service ID', { exact: true });
75+
await expect(serviceIdField).toHaveValue(testServiceId);
76+
await expect(serviceIdField).toBeDisabled();
77+
78+
// Submit the form without filling any other fields
79+
await servicesPom.getAddBtn(page).click();
80+
await uiHasToastMsg(page, {
81+
hasText: 'Add Stream Route Successfully',
82+
});
83+
});
84+
85+
await test.step('auto navigate to stream route detail page', async () => {
86+
await servicesPom.isServiceStreamRouteDetailPage(page);
87+
88+
// Verify the stream route details
89+
// Verify ID exists
90+
const ID = page.getByRole('textbox', { name: 'ID', exact: true });
91+
await expect(ID).toBeVisible();
92+
await expect(ID).toBeDisabled();
93+
94+
// Verify service_id is still pre-filled and disabled
95+
const serviceIdField = page.getByLabel('Service ID', { exact: true });
96+
await expect(serviceIdField).toHaveValue(testServiceId);
97+
await expect(serviceIdField).toBeDisabled();
98+
99+
// Verify default values for server address and port (should be empty initially)
100+
const serverAddrField = page.getByLabel('Server Address', { exact: true });
101+
const serverPortField = page.getByLabel('Server Port', { exact: true });
102+
103+
// These fields might be empty or have default values
104+
await expect(serverAddrField).toBeVisible();
105+
await expect(serverPortField).toBeVisible();
106+
});
107+
108+
await test.step('edit and update stream route with some fields', async () => {
109+
// Click the Edit button in the detail page
110+
await page.getByRole('button', { name: 'Edit' }).click();
111+
112+
// Verify we're in edit mode - fields should be editable now
113+
const serverAddrField = page.getByLabel('Server Address', { exact: true });
114+
await expect(serverAddrField).toBeEnabled();
115+
116+
// Service ID should still be disabled even in edit mode
117+
const serviceIdField = page.getByLabel('Service ID', { exact: true });
118+
await expect(serviceIdField).toBeDisabled();
119+
120+
// Fill in some fields
121+
await serverAddrField.fill(streamRouteServerAddr);
122+
123+
const serverPortField = page.getByLabel('Server Port', { exact: true });
124+
await serverPortField.fill(streamRouteServerPort.toString());
125+
126+
// Click the Save button to save changes
127+
const saveBtn = page.getByRole('button', { name: 'Save' });
128+
await saveBtn.click();
129+
130+
// Verify the update was successful
131+
await uiHasToastMsg(page, {
132+
hasText: 'success',
133+
});
134+
135+
// Verify we're back in detail view mode
136+
await servicesPom.isServiceStreamRouteDetailPage(page);
137+
138+
// Verify the updated fields
139+
await expect(
140+
page.getByLabel('Server Address', { exact: true })
141+
).toHaveValue(streamRouteServerAddr);
142+
await expect(page.getByLabel('Server Port', { exact: true })).toHaveValue(
143+
streamRouteServerPort.toString()
144+
);
145+
});
146+
147+
await test.step('edit again and update with different values', async () => {
148+
// Click the Edit button again
149+
await page.getByRole('button', { name: 'Edit' }).click();
150+
151+
// Update with different values
152+
const serverAddrField = page.getByLabel('Server Address', { exact: true });
153+
await serverAddrField.fill(updatedStreamRouteServerAddr);
154+
155+
const serverPortField = page.getByLabel('Server Port', { exact: true });
156+
await serverPortField.fill(updatedStreamRouteServerPort.toString());
157+
158+
// Click the Save button
159+
const saveBtn = page.getByRole('button', { name: 'Save' });
160+
await saveBtn.click();
161+
162+
// Verify the update was successful
163+
await uiHasToastMsg(page, {
164+
hasText: 'success',
165+
});
166+
167+
// Verify the updated values
168+
await expect(
169+
page.getByLabel('Server Address', { exact: true })
170+
).toHaveValue(updatedStreamRouteServerAddr);
171+
await expect(page.getByLabel('Server Port', { exact: true })).toHaveValue(
172+
updatedStreamRouteServerPort.toString()
173+
);
174+
});
175+
176+
await test.step('stream route should exist in service stream routes list', async () => {
177+
// Navigate back to service stream routes list
178+
await servicesPom.toServiceStreamRoutes(page, testServiceId);
179+
await servicesPom.isServiceStreamRoutesPage(page);
180+
181+
// Verify the stream route appears in the list with updated values
182+
await expect(
183+
page.getByRole('cell', { name: updatedStreamRouteServerAddr })
184+
).toBeVisible();
185+
await expect(
186+
page.getByRole('cell', { name: updatedStreamRouteServerPort.toString() })
187+
).toBeVisible();
188+
189+
// Click on the stream route to go to the detail page
190+
await page
191+
.getByRole('row', { name: updatedStreamRouteServerAddr })
192+
.getByRole('button', { name: 'View' })
193+
.click();
194+
await servicesPom.isServiceStreamRouteDetailPage(page);
195+
});
196+
197+
await test.step('delete stream route in detail page', async () => {
198+
// We're already on the detail page from the previous step
199+
200+
// Delete the stream route
201+
await page.getByRole('button', { name: 'Delete' }).click();
202+
203+
await page
204+
.getByRole('dialog', { name: 'Delete Stream Route' })
205+
.getByRole('button', { name: 'Delete' })
206+
.click();
207+
208+
// Will redirect to service stream routes page
209+
await servicesPom.isServiceStreamRoutesPage(page);
210+
await uiHasToastMsg(page, {
211+
hasText: 'Delete Stream Route Successfully',
212+
});
213+
214+
// Verify the stream route is no longer in the list
215+
await expect(
216+
page.getByRole('cell', { name: updatedStreamRouteServerAddr })
217+
).toBeHidden();
218+
});
219+
220+
await test.step('create another stream route with minimal fields', async () => {
221+
// Add another stream route to test creation with minimal data
222+
await servicesPom.getAddStreamRouteBtn(page).click();
223+
await servicesPom.isServiceStreamRouteAddPage(page);
224+
225+
// Just fill server address this time
226+
const serverAddrField = page.getByLabel('Server Address', { exact: true });
227+
await serverAddrField.fill('192.168.1.1');
228+
229+
// Submit the form
230+
await servicesPom.getAddBtn(page).click();
231+
await uiHasToastMsg(page, {
232+
hasText: 'Add Stream Route Successfully',
233+
});
234+
235+
// Verify we're on the detail page
236+
await servicesPom.isServiceStreamRouteDetailPage(page);
237+
await expect(
238+
page.getByLabel('Server Address', { exact: true })
239+
).toHaveValue('192.168.1.1');
240+
241+
// Clean up - delete this stream route too
242+
await page.getByRole('button', { name: 'Delete' }).click();
243+
await page
244+
.getByRole('dialog', { name: 'Delete Stream Route' })
245+
.getByRole('button', { name: 'Delete' })
246+
.click();
247+
await servicesPom.isServiceStreamRoutesPage(page);
248+
});
249+
});

0 commit comments

Comments
 (0)