-
Notifications
You must be signed in to change notification settings - Fork 70
Add E2E tests for Resources/Namespaces in the dashboard #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @SunsetB612, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request significantly enhances the end-to-end testing coverage for the dashboard's Namespaces section. It introduces a suite of Playwright tests that validate the core functionalities of namespace management, including creation, listing, and deletion. Additionally, it includes a test to ensure proper handling of network errors when fetching namespace data. This work also involves a minor refactoring of the E2E test directory structure to better organize the test files.
Highlights
- E2E Test File Restructuring: The existing
login.spec.ts
file was refactored and moved into a newlogin
subdirectory, indicating an organization of E2E tests. - Comprehensive Namespace E2E Tests: New Playwright E2E tests have been introduced to cover the full lifecycle of namespace management within the dashboard. This includes tests for creating, listing, and deleting namespaces.
- Network Error Handling Test for Namespaces: A dedicated E2E test was added to specifically verify the dashboard's resilience and error handling when network requests for namespaces fail, ensuring a robust user experience.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request adds a comprehensive set of E2E tests for namespace management in the dashboard, covering creation, deletion, listing, and network error scenarios. The tests are well-structured and cover important user flows.
However, there is significant code duplication across the new test files, particularly in the setup (beforeEach
block and related constants). I recommend refactoring this common logic into a shared helper function to improve maintainability.
Additionally, I've pointed out several areas for improvement in the individual test files, such as removing hardcoded IP addresses, avoiding static waits (waitForTimeout
), removing leftover debugging code, and strengthening assertions. Addressing these points will make the tests more robust and reliable.
const baseURL = process.env.BASE_URL || 'http://192.168.47.131:5173'; | ||
const basePath = '/multicloud-resource-manage'; | ||
const token = process.env.KARMADA_TOKEN || ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These constants, especially baseURL
with a hardcoded IP address, are duplicated across all new test files. This makes the tests less portable and harder to maintain. As mentioned in the general feedback, this setup logic should be centralized in a shared helper. The playwright.config.ts
already defines a baseURL
based on localhost
, which is a better practice than using a hardcoded IP.
const rowCount = await tableRows.count(); | ||
const errorCount = await errorMsg.count(); | ||
|
||
console.log(`Table rows: ${rowCount}, Error messages: ${errorCount}`); | ||
|
||
// 最终断言:要么表格为空,要么显示网络错误 | ||
expect(rowCount === 0 || errorCount > 0).toBeTruthy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section contains leftover debugging code and a weak assertion. The test should explicitly check that an error message is visible and that the table is empty when the API call fails. This makes the test more precise and robust.
const rowCount = await tableRows.count(); | |
const errorCount = await errorMsg.count(); | |
console.log(`Table rows: ${rowCount}, Error messages: ${errorCount}`); | |
// 最终断言:要么表格为空,要么显示网络错误 | |
expect(rowCount === 0 || errorCount > 0).toBeTruthy(); | |
// Assert that an error message is shown and the table is empty | |
await expect(errorMsg).toBeVisible(); | |
await expect(tableRows).toHaveCount(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the relationship of two asserts should be or
or and
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems that the advice from bot more useful
const searchBox = page.getByPlaceholder('Search by Name'); | ||
await searchBox.fill(namespaceName); | ||
await searchBox.press('Enter'); | ||
await page.waitForTimeout(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using page.waitForTimeout()
is generally discouraged as it can lead to flaky tests (if the wait is too short) or slow down the test suite (if it's too long). It's better to wait for a specific element state or network condition. In this case, the following waitForSelector
should be sufficient. Please remove this static wait.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, waitForTimeout seems useful when debug the e2e test, but not suitable for e2e test in production
await page.waitForSelector(`tr:has-text("${namespaceName}")`, { timeout: 60000 }); | ||
await expect(page.locator('table')).toContainText(namespaceName); | ||
|
||
await page.screenshot({ path: 'debug-namespace-create.png', fullPage: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This screenshot seems to be for debugging purposes. While useful during development, it should be removed from the final test code to avoid cluttering the repository with artifacts. Playwright's tracing feature, enabled in your config (trace: 'retry-with-trace'
), is a better way to debug failed test runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
const searchBox = page.getByPlaceholder('Search by Name'); | ||
await searchBox.fill(namespaceName); | ||
await searchBox.press('Enter'); | ||
await page.waitForTimeout(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same problem
await page.reload({ waitUntil: 'networkidle' }); | ||
|
||
// 使用搜索框确认删除 | ||
await searchBox.fill(''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
await searchBox.fill('');
await searchBox.fill(namespaceName);
seems has the same effect as
await searchBox.fill(namespaceName);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can test it locally and recheck it
// 清空搜索框 | ||
await searchBox.clear(); | ||
|
||
await page.screenshot({ path: 'debug-namespace-delete.png', fullPage: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 验证表格中包含默认 namespace | ||
await expect(table).toContainText('default'); | ||
|
||
await page.screenshot({ path: 'debug-namespace-list.png', fullPage: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. What about add debug condition, and when debug condition is true, then take snapshot, otherwise ignore screenshotting, any ideas?
expect(rowCount === 0 || errorCount > 0).toBeTruthy(); | ||
|
||
// 截图调试 | ||
await page.screenshot({ path: 'debug-namespace-network-failure.png', fullPage: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/assign |
26af17b
to
13affa1
Compare
.github/workflows/ci.yml
Outdated
path: karmada-dashboard/ui/apps/dashboard/playwright-report/ | ||
retention-days: 30 | ||
|
||
retention-days: 30 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plz fix all kind of similar problem, just add extra new line at the end of the file ~
.github/workflows/ci.yml
Outdated
# the same as the End of Life of the Kubernetes release: https://kubernetes.io/releases/ | ||
# Please remember to update the CI Schedule Workflow when we add a new version. | ||
k8s: [ v1.31.0, v1.32.0, v1.33.0 ] | ||
# k8s: [ v1.31.0 ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clean the debug code
export CLUSTER_VERSION=kindest/node:${{ matrix.k8s }} | ||
hack/local-up-karmada.sh | ||
echo "KUBECONFIG=/home/runner/.kube/karmada.config" >> $GITHUB_ENV | ||
- name: Debug cluster status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could optimize the debug code or adopt the debug code with debug var
const searchBox = page.getByPlaceholder('Search by Name'); | ||
await searchBox.fill(namespaceName); | ||
await searchBox.press('Enter'); | ||
await page.waitForTimeout(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, waitForTimeout seems useful when debug the e2e test, but not suitable for e2e test in production
await page.waitForSelector(`tr:has-text("${namespaceName}")`, { timeout: 60000 }); | ||
await expect(page.locator('table')).toContainText(namespaceName); | ||
|
||
await page.screenshot({ path: 'debug-namespace-create.png', fullPage: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
await page.reload({ waitUntil: 'networkidle' }); | ||
|
||
// 使用搜索框确认删除 | ||
await searchBox.fill(''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
await searchBox.fill('');
await searchBox.fill(namespaceName);
seems has the same effect as
await searchBox.fill(namespaceName);
await page.reload({ waitUntil: 'networkidle' }); | ||
|
||
// 使用搜索框确认删除 | ||
await searchBox.fill(''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can test it locally and recheck it
// 验证表格中包含默认 namespace | ||
await expect(table).toContainText('default'); | ||
|
||
await page.screenshot({ path: 'debug-namespace-list.png', fullPage: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. What about add debug condition, and when debug condition is true, then take snapshot, otherwise ignore screenshotting, any ideas?
const rowCount = await tableRows.count(); | ||
const errorCount = await errorMsg.count(); | ||
|
||
console.log(`Table rows: ${rowCount}, Error messages: ${errorCount}`); | ||
|
||
// 最终断言:要么表格为空,要么显示网络错误 | ||
expect(rowCount === 0 || errorCount > 0).toBeTruthy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the relationship of two asserts should be or
or and
const rowCount = await tableRows.count(); | ||
const errorCount = await errorMsg.count(); | ||
|
||
console.log(`Table rows: ${rowCount}, Error messages: ${errorCount}`); | ||
|
||
// 最终断言:要么表格为空,要么显示网络错误 | ||
expect(rowCount === 0 || errorCount > 0).toBeTruthy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems that the advice from bot more useful
13affa1
to
8d71a78
Compare
aeff57c
to
b406008
Compare
hack/local-up-karmada.sh | ||
echo "KUBECONFIG=/home/runner/.kube/karmada.config" >> $GITHUB_ENV | ||
- name: Debug cluster status | ||
if: ${{ env.DEBUG == 'true' }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
# 使用 kubectl create token 命令生成临时 token | ||
#TOKEN=$(kubectl --context=karmada-apiserver create token e2e-test -n kube-system --duration=3600s) | ||
# kubectl --context=karmada-apiserver apply -f karmada-dashboard/artifacts/dashboard | ||
kubectl --context=karmada-host apply -k karmada-dashboard/artifacts/overlays/nodeport-mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can reuse the debug var or just drop lines
.github/workflows/ci.yml
Outdated
make run-api & | ||
echo $! > .api.pid | ||
sleep 5 | ||
# ===== 添加API服务器健康检查 ===== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plz translate the line~
// Debug | ||
if(process.env.DEBUG === 'true'){ | ||
await page.screenshot({ path: 'debug-namespace-create.png', fullPage: true }); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good job~
if(process.env.DEBUG === 'true'){ | ||
await page.screenshot({ path: 'debug-namespace-network-failure.png', fullPage: true }); | ||
} | ||
}); No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra empty line should be added
@SunsetB612 in short
after that, I think we can merge the PR and push forward ~ |
Signed-off-by: SunsetB612 <10235101575@stu.ecnu.edu.cn>
b68374b
to
1734a70
Compare
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: warjiang The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Add E2E tests for Resources/Namespaces in the dashboard