blob: 4581e21c9f92808977b56ce0d617a6b6300c800e [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { upstreamsPom } from '@e2e/pom/upstreams';
import { randomId } from '@e2e/utils/common';
import { e2eReq } from '@e2e/utils/req';
import { test } from '@e2e/utils/test';
import { uiHasToastMsg } from '@e2e/utils/ui';
import { expect } from '@playwright/test';
import { deleteAllUpstreams } from '@/apis/upstreams';
import type { APISIXType } from '@/types/schema/apisix';
const upstreamName = randomId('test-upstream');
const nodes: APISIXType['UpstreamNode'][] = [
{ host: 'test.com' },
{ host: 'test2.com', port: 80 },
];
test.beforeAll(async () => {
await deleteAllUpstreams(e2eReq);
});
test('should CRUD upstream with required fields', async ({ page }) => {
await upstreamsPom.toIndex(page);
await upstreamsPom.isIndexPage(page);
await upstreamsPom.getAddUpstreamBtn(page).click();
await upstreamsPom.isAddPage(page);
const addBtn = page.getByRole('button', { name: 'Add', exact: true });
await test.step('cannot submit without required fields', async () => {
await addBtn.click();
await upstreamsPom.isAddPage(page);
await uiHasToastMsg(page, {
hasText: 'invalid configuration: value ',
});
});
await test.step('submit with required fields', async () => {
await page.getByLabel('Name', { exact: true }).fill(upstreamName);
const nodesSection = page.getByRole('group', { name: 'Nodes' });
const noData = nodesSection.getByText('No Data');
const addNodeBtn = page.getByRole('button', { name: 'Add a Node' });
await expect(noData).toBeVisible();
await addNodeBtn.click();
await expect(noData).toBeHidden();
const rows = nodesSection.locator('tr.ant-table-row');
const firstRowHost = rows.nth(0).getByRole('textbox').first();
await firstRowHost.fill(nodes[1].host);
await expect(firstRowHost).toHaveValue(nodes[1].host);
await nodesSection.click();
// add a new node then remove it
await addNodeBtn.click();
await expect(rows.nth(1)).toBeVisible();
const secondRowHost = rows.nth(1).getByRole('textbox').first();
await secondRowHost.fill(nodes[0].host);
await expect(secondRowHost).toHaveValue(nodes[0].host);
await nodesSection.click();
// we need to replace the antd component to help fix this issue
await addNodeBtn.click();
rows.nth(2).getByRole('button', { name: 'Delete' }).click();
await expect(rows).toHaveCount(2);
await addBtn.click();
await uiHasToastMsg(page, {
hasText: 'Add Upstream Successfully',
});
});
await test.step('auto navigate to upstream detail page', async () => {
await upstreamsPom.isDetailPage(page);
// Verify ID exists
const ID = page.getByRole('textbox', { name: 'ID', exact: true });
await expect(ID).toBeVisible();
await expect(ID).toBeDisabled();
// Verify the upstream name
const name = page.getByLabel('Name', { exact: true });
await expect(name).toHaveValue(upstreamName);
await expect(name).toBeDisabled();
// Verify the upstream nodes
const nodesSection = page.getByRole('group', { name: 'Nodes' });
await expect(
nodesSection.getByRole('cell', { name: nodes[1].host })
).toBeVisible();
await expect(
nodesSection.getByRole('cell', { name: nodes[0].host })
).toBeVisible();
});
await test.step('can see upstream in list page', async () => {
await upstreamsPom.getUpstreamNavBtn(page).click();
await expect(page.getByRole('cell', { name: upstreamName })).toBeVisible();
});
await test.step('navigate to upstream detail page', async () => {
// Click on the upstream name to go to the detail page
await page
.getByRole('row', { name: upstreamName })
.getByRole('button', { name: 'View' })
.click();
await upstreamsPom.isDetailPage(page);
const name = page.getByLabel('Name', { exact: true });
await expect(name).toHaveValue(upstreamName);
});
await test.step('edit and update upstream in detail page', async () => {
// Click the Edit button in the detail page
await page.getByRole('button', { name: 'Edit' }).click();
// Verify we're in edit mode - fields should be editable now
const nameField = page.getByLabel('Name', { exact: true });
await expect(nameField).toBeEnabled();
// Update the description field
const descriptionField = page.getByLabel('Description');
await descriptionField.fill('Updated description for testing');
// Add a simple label (key:value format)
const labelsField = page.getByRole('textbox', { name: 'Labels' });
await expect(labelsField).toBeEnabled();
// Add a single label in key:value format
await labelsField.click();
await labelsField.fill('version:v1');
await labelsField.press('Enter');
// Verify the label was added by checking if the input is cleared
// This indicates the tag was successfully created
await expect(labelsField).toHaveValue('');
// Update a node - change the host of the first node
const nodesSection = page.getByRole('group', { name: 'Nodes' });
const rows = nodesSection.locator('tr.ant-table-row');
const firstRowHost = rows.nth(0).getByRole('textbox').first();
await firstRowHost.fill('updated-test.com');
await expect(firstRowHost).toHaveValue('updated-test.com');
await nodesSection.click();
// Click the Save button to save changes
const saveBtn = page.getByRole('button', { name: 'Save' });
await saveBtn.click();
// Verify the update was successful
await uiHasToastMsg(page, {
hasText: 'success',
});
// Verify we're back in detail view mode
await upstreamsPom.isDetailPage(page);
// Verify the updated fields
await expect(page.getByLabel('Description')).toHaveValue(
'Updated description for testing'
);
// Check if the updated node host text is visible somewhere in the nodes section
await expect(nodesSection).toBeVisible();
await expect(nodesSection.getByText('updated-test.com')).toBeVisible();
// check labels
await expect(page.getByText('version:v1')).toBeVisible();
// Return to list page and verify the upstream exists
await upstreamsPom.getUpstreamNavBtn(page).click();
await upstreamsPom.isIndexPage(page);
// Find the row with our upstream
const row = page.getByRole('row', { name: upstreamName });
await expect(row).toBeVisible();
});
await test.step('delete upstream in detail page', async () => {
await page.getByRole('button', { name: 'Delete' }).click();
await page
.getByRole('dialog', { name: 'Delete Upstream' })
.getByRole('button', { name: 'Delete' })
.click();
// will redirect to upstreams page
await upstreamsPom.isIndexPage(page);
await uiHasToastMsg(page, {
hasText: 'Delete Upstream Successfully',
});
await expect(page.getByRole('cell', { name: upstreamName })).toBeHidden();
});
});