本教程演示了如何用Cypress为Ag Grid React表 组件编写E2E(端到端)测试 。
您可以在以下GitHub存储库中找到本教程的完整代码。
项目设置
通过运行以下命令来创建一个新的React项目:
npm create vite@latest testing-ag-grid -- --template react-ts
将目录更改为您新创建的应用程序,并使用以下命令安装必要的软件包:
cd testing-ag-grid
npm install
npm run dev
创建一个新的AG网格组件
接下来,继续并在您的React应用程序中创建一个新的AG网格组件。运行以下命令以安装AG网格NPM软件包。
npm install ag-grid-react
复制
接下来,打开 index.css 文件和删除所有样式并替换您的所有代码 App.tsx 用以下代码归档:
import { useState, useMemo } from "react";
import { AllCommunityModule, ModuleRegistry, ColDef } from "ag-grid-community";
import { AgGridReact } from "ag-grid-react";
export type ICar = {
make: string;
model: string;
price: number;
electric: boolean;
};
ModuleRegistry.registerModules([AllCommunityModule]);
function App() {
// Row Data: The data to be displayed.
const [rowData, setRowData] = useState<ICar[]>([
{ make: "Tesla", model: "Model Y", price: 64950, electric: true },
{ make: "Ford", model: "F-Series", price: 33850, electric: false },
{ make: "Toyota", model: "Corolla", price: 29600, electric: false },
{ make: "Mercedes", model: "EQA", price: 48890, electric: true },
{ make: "Fiat", model: "500", price: 15774, electric: false },
{ make: "Nissan", model: "Juke", price: 20675, electric: false },
]);
// Column Definitions: Defines & controls grid columns.
const [colDefs, setColDefs] = useState<ColDef<ICar>[]>([
{ field: "make", editable: true, filter: true },
{ field: "model" },
{ field: "price", editable: true },
{ field: "electric" },
]);
const defaultColDef = useMemo(() => {
return {
flex: 1
};
}, []);
return (
<div style={{ width: "100%", height: '100vh' }}>
<AgGridReact
rowData={rowData}
columnDefs={colDefs}
defaultColDef={defaultColDef}
/>
</div>
);
}
export default App
配置Cypress
首先通过运行以下命令来安装必要的依赖项:
npm install cypress --save-dev
接下来,运行以下命令在您的项目中配置Cypress:
npx cypress open
当您运行上面的命令时,将打开一个新的浏览器窗口。您将为您提供与下面类似的页面。此页面为您提供了设置不同类型测试的选项。
选择E2E Testing选项是我们将在本教程中重点关注的选择。
接下来,Cypress将为您提供生成的配置文件列表。这些文件提供特定于项目的配置。您可以在这里了解有关它们的更多信息。选择继续进行。
此时,您可能会遇到以下错误。如果确实会有此错误,请将cypress.config.ts文件更改为cypress.config.js
更改cypress.config从“.ts 从.js选择”的文件扩展名之后。
接下来,选择Web浏览器(Firefox或Chrome)或电子应用程序。这告诉赛普拉斯是您是否为Web或Electron应用程序设置测试。选择Web浏览器选项,然后选择“启动E2E测试”。
接下来,您将获得一个选项来踩踏规格文件或从头开始创建一个新的规格文件。选择创建新规格文件。
它将尝试创建一个新的测试。命名您的测试cypress/e2e/App.cy.ts。接受默认示例代码。
单击新创建的测试以运行它。测试将通过,因为我们还没有实施任何事情。
您可以以这种方式直接从浏览器中添加其他测试。如果您回到代码并进入Cypress文件夹,您将看到一个e2e/App.cy.ts也是创建的。您可以在此处添加测试,这是我们将要做的事情。
更新脚本部分package.json文件。添加一个新的测试脚本来运行测试。
"scripts": {
"test": "cypress open"
},
我们开始测试之前的最后一步是确保您的React服务器在一个终端中运行,而在另一个终端中运行。否则,Cypress将无法检测您的应用程序。
测试渲染
让我们添加一个测试,该测试可以验证网格是否正确呈现。App.cy.ts使用以下代码更新文件:
describe('AG Grid Rendering', () => {
beforeEach(() => {
cy.visit('http://localhost:5173/');
});
it('should render the AG Grid component', () => {
cy.get('.ag-root-wrapper').should('be.visible');
// Verify column headers
cy.get('.ag-header-cell-text').eq(0).should('have.text', 'Make');
cy.get('.ag-header-cell-text').eq(1).should('have.text', 'Model');
// Wait for grid to load and verify first row data
cy.get('.ag-cell').should('have.length.greaterThan', 0);
cy.get('.ag-cell').eq(0).should('have.text', 'Tesla');
});
});
测试套件在使用每个测试之前,首先在端口5173beforeEach处导航到端口5173的本地开发服务器。
主测试通过验证多个元素来检查网格是否正确呈现。它证实了网格包装器可见,证实了前两个列标题分别为“ make”和“ model”。它还通过检查细胞的存在来确保网格包含数据,并验证第一个单元格是否包含“特斯拉”。
使用以下命令运行测试:
npm run test
异步数据加载
AG网格的大多数用途都涉及从API获取数据,因此让我们通过异步加载 rowData A setTimeout:
const [rowData, setRowData] = useState<ICar[] | null>(null);
useEffect(() => {
// Simulate an asynchronous data fetch (e.g., from an API)
setTimeout(() => {
setRowData([
{ make: "Tesla", model: "Model Y", price: 64950, electric: true },
{ make: "Ford", model: "F-Series", price: 33850, electric: false },
{ make: "Toyota", model: "Corolla", price: 29600, electric: false },
{ make: "Mercedes", model: "EQA", price: 48890, electric: true },
{ make: "Fiat", model: "500", price: 15774, electric: false },
{ make: "Nissan", model: "Juke", price: 20675, electric: false },
]);
}, 500);
}, []);
接下来,让我们编写一个测试以验证该表在涉及异步数据时正确渲染:
it("should display the loading overlay and then show the data", () => {
// 1. Check that the AG Grid loading overlay is visible
cy.get(".ag-overlay-loading-center").should("be.visible");
// 2. Wait for the first cell to contain "Tesla" (data is loaded)
cy.get(".ag-cell").first().should("have.text", "Tesla");
// 3. Ensure the loading overlay disappears after data loads
cy.get(".ag-overlay-loading-center").should("not.exist");
});
该测试代码验证涉及异步数据时AG网格组件的加载行为。它检查数据时是否可见加载叠加层,然后等待实际数据出现并检查数据。最后,它证实了数据加载后加载覆盖层已经消失。
用户交互测试
Cypress可用于准确模拟用户交互。在本节中,我们将根据模拟用户交互彻底测试电网的行为。
排序
让我们创建一个测试以验证网格的排序功能。具体来说,此测试将检查单击“价格列标头”是否在上升和下降顺序中正确对数据进行分类。
让我们将以下代码添加到我们的App.cy.ts文件中:
// ... Rest of the code
describe('AG Grid sorting', () => {
beforeEach(() => {
cy.visit('http://localhost:5173/');
});
it('sorts "Price" column ascending and then descending', () => {
// 1. Locate the "Price" column header and click
cy.contains(".ag-header-cell-text", "Price").click();
// 2. Verify the first row in the grid is now 'Fiat'
cy.get('.ag-row[row-index="0"] [col-id="make"]')
.should("have.text", "Fiat");
// 3. Click again to sort in descending order
cy.contains(".ag-header-cell-text", "Price").click();
// 4. Verify the first row in the grid is now 'Tesla'
cy.get('.ag-row[row-index="0"] [col-id="make"]')
.should("have.text", "Tesla");
});
});
在上面的代码中,我们使用 rowIndex (反映该行在网格显示屏中的当前位置)来验证排序顺序。在此示例中,我们已经为期望看到的值进行了硬编码。
更健壮的测试可能会循环遍历每一行的值,以验证排序功能。以下是通过循环浏览网格值而不是硬编码期望来动态验证排序功能的测试。💡
sourceRowIndex 考虑使用之前和之后,考虑使用该值在原始数组中的位置,
rowData 并且无论排序,过滤,分组或其他UI操作如何保持恒定,也可能会很有用 。
编辑单元格值
在您的列定义中,请确保将其设置为可编辑的make和price列。
const [colDefs, _setColDefs] = useState<ColDef<ICar>[]>([
{ field: "make", editable: true, filter: true },
{ field: "model" },
{ field: "price", editable: true },
{ field: "electric" },
]);
将以下测试添加到您的测试套件中,以验证网格的单元格编辑行为。
describe("AG Grid Editable Cell", () => {
beforeEach(() => {
cy.visit("http://localhost:5173/");
});
it('should allow editing of cells and update the data', () => {
// 1. Locate the editable cell for "Price" in the first row
const priceCellSelector = '.ag-row[row-index="0"] [col-id="price"]';
// 2. Double-click the cell to activate edit mode
cy.get(priceCellSelector).dblclick();
// 3. Wait for the input field to appear
cy.get(`${priceCellSelector} input`)
.should("be.visible")
.as("priceInputField");
// 4. Enter a new value into the input field and simulate pressing Enter
const newPrice = "70000";
cy.get("@priceInputField")
.clear()
.type(`${newPrice}{enter}`);
// 5. Verify the cell displays the updated value
cy.get(priceCellSelector).should("have.text", newPrice);
});
});
以上测试模拟以下内容:
row-index="0"它通过其将价格单元定位在第一行( )中col-id="price"。- 它双击此单元格以激活单元格的编辑模式。
- 然后等待,直到可见输入字段(由AG网格渲染进行编辑)。
- 它清除了现有的价值,以新价格类型,然后按Enters Enter进行更改。
- 它验证了该单元格现在显示更新的价格值。
过滤
接下来,让我们测试过滤功能。在您的列定义中make列可过滤。
const [colDefs, _setColDefs] = useState<ColDef<ICar>[]>([
{ field: "make", editable: true, filter: true },
// ... Rest of the code
]);
添加以下测试以验证过滤器功能
describe('AG Grid Make Column Filter', () => {
beforeEach(() => {
cy.visit('http://localhost:5173/');
});
it('should filter data by "Make" using the column filter menu', () => {
// 1. Wait for the AG Grid root element to be visible
cy.get('.ag-root').should('be.visible');
// 2. Locate and click the filter menu icon for the "Make" column
cy.get('.ag-header-cell[col-id="make"] .ag-header-icon')
.should('be.visible')
.click();
// 3. Fill in the filter input with "Tesla"
cy.get('.ag-filter-body input[placeholder="Filter..."]').type('Tesla');
// 4. Verify only one row is visible
cy.get('.ag-center-cols-viewport .ag-row').should('have.length', 1);
// 5. Check that the "Make" cell in the first (and only) row contains "Tesla"
cy.get('.ag-center-cols-viewport .ag-row')
.first()
.find('.ag-cell[col-id="make"]')
.should('have.text', 'Tesla');
});
});
上面的测试单击“ Make”列标题中的过滤器图标,将“ Tesla”作为滤波器标准输入,然后通过检查仅一行保持可见,并且该行在“ Make列中”中包含“ Tesla”,从而确认过滤功能正常。
可访问性测试
与当今市场上可用的其他网格相比, AG网格为可访问性提供了最佳支持 。本节演示了如何通过验证诸如A11Y标准,ARIA标签等的事物来测试此问题。
可访问性(A11Y)检查
cypress-axe使用以下命令在项目中安装软件包
npm install --save-dev cypress-axe
导航到您的cypress/support/e2e.ts文件,并添加以下代码以导入和初始化cypress-axe:
import 'cypress-axe';
Cypress.Commands.add('injectAxe', () => {
cy.window({ log: false }).then((win) => {
// Inject axe-core runtime into the browser
// This makes the `axe` global available
const script = win.document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.6.3/axe.min.js';
win.document.head.appendChild(script);
});
});
Cypress.Commands.add('checkA11y', (context, options = {}, violationCallback) => {
// By default, run on the entire document if 'context' is not provided
cy.window({ log: false }).then((win) => {
return new Promise((resolve) => {
win.axe.run(context || win.document, options, (error, results) => {
if (error) throw error;
if (results.violations.length) {
if (violationCallback) {
violationCallback(results.violations);
} else {
cy.log('Accessibility violations found:', results.violations);
}
}
resolve(results);
});
});
});
});
接下来,将以下测试添加到您的测试套件中。
describe('Accessibility Tests', () => {
it('should have no a11y violations on load', () => {
// 1) Visit your app
cy.visit('http://localhost:5173');
// 2) Inject axe into the page
cy.injectAxe();
// 3) Optionally wait for content to finish loading
cy.get('.ag-root').should('be.visible');
cy.get('.ag-overlay-loading-center').should('not.exist');
// 4) Run accessibility checks
cy.checkA11y();
});
});
此示例Cypress测试访问您的AG网格页面,等待网格加载并运行Axe-Core审核。
该自动化测试可确保您的AG网格实现遵循可访问性标准,从而自动捕获常见问题,例如缺少ARIA标签,对比度问题或HTML结构不当。
结论
在本教程中,我们涵盖了使用Cypress测试Ag网格组件的基本测试方案。您可以基于这些示例来为其特定用例创建更专业的测试,无论是涉及复杂的数据操作,自定义单元渲染器还是高级过滤方案。