mirror of https://github.com/rancher/dashboard.git
e2e: Add built UI to docker container rather than run a node process (#9063)
* e2e: Add built UI to docker container rather than run a node process * Fix to ensure docker:local:stop tried to both clean and remove cypress container * Check dist folder is correct * Build U first * Remove debug, wait for ui * Change cluster test * Tweak test * Improve resilience of cluster manager delete tests * Fix lint * Try and fix delete tests * Remove unused var * Remove unused baseUrl * Fix cluster delete tests * Address lint issues * Fix api keys test
This commit is contained in:
parent
a5b55ddbf4
commit
226ed30e39
|
|
@ -36,4 +36,8 @@ export default class ComponentPo {
|
|||
checkVisible(): Cypress.Chainable<boolean> {
|
||||
return this.self().scrollIntoView().should('be.visible');
|
||||
}
|
||||
|
||||
checkNotVisible(): Cypress.Chainable<boolean> {
|
||||
return this.self().scrollIntoView().should('not.be.visible');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,4 +9,8 @@ export default class CreateEditViewPo extends ComponentPo {
|
|||
save() {
|
||||
return new AsyncButtonPo(this.self().find('.cru-resource-footer .role-primary')).click();
|
||||
}
|
||||
|
||||
saveAndWait() {
|
||||
return new AsyncButtonPo(this.self().find('.cru-resource-footer .role-primary')).action('Save', 'Saved');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export default class SortableTablePo extends ComponentPo {
|
|||
//
|
||||
|
||||
rowElements() {
|
||||
return this.self().find('tbody tr');
|
||||
return this.self().find('tbody tr:not(.sub-row)');
|
||||
}
|
||||
|
||||
rowElementWithName(name: string) {
|
||||
|
|
@ -75,6 +75,14 @@ export default class SortableTablePo extends ComponentPo {
|
|||
return new ListRowPo(this.rowElementWithName(name));
|
||||
}
|
||||
|
||||
rowNames() {
|
||||
return this.rowElements().find('.cluster-link').then(($els: any) => {
|
||||
return (
|
||||
Cypress.$.makeArray($els).map((el: any) => el.innerText)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
rowActionMenu() {
|
||||
return new ActionMenuPo();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,4 +22,8 @@ export default abstract class ClusterManagerCreateImportPagePo extends PagePo {
|
|||
save() {
|
||||
return this.resourceDetail().createEditView().save();
|
||||
}
|
||||
|
||||
saveAndWait() {
|
||||
return this.resourceDetail().createEditView().saveAndWait();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ const runTimestamp = +new Date();
|
|||
const runPrefix = `e2e-test-${ runTimestamp }`;
|
||||
|
||||
// File specific consts
|
||||
const { baseUrl } = Cypress.config();
|
||||
const clusterRequestBase = `${ baseUrl }/v1/provisioning.cattle.io.clusters/fleet-default`;
|
||||
const clusterNamePartial = `${ runPrefix }-create`;
|
||||
const rke2CustomName = `${ clusterNamePartial }-rke2-custom`;
|
||||
const importGenericName = `${ clusterNamePartial }-import-generic`;
|
||||
|
|
@ -55,8 +53,6 @@ describe('Cluster Manager', () => {
|
|||
});
|
||||
|
||||
it('can edit cluster and see changes afterwards', () => {
|
||||
cy.intercept('PUT', `${ clusterRequestBase }/${ rke2CustomName }`).as('saveRequest');
|
||||
|
||||
clusterList.goTo();
|
||||
clusterList.list().actionMenu(rke2CustomName).getMenuItem('Edit Config').click();
|
||||
|
||||
|
|
@ -64,13 +60,13 @@ describe('Cluster Manager', () => {
|
|||
editCreatedClusterPage.nameNsDescription().description().set(rke2CustomName);
|
||||
editCreatedClusterPage.save();
|
||||
|
||||
cy.wait('@saveRequest').then(() => {
|
||||
clusterList.goTo();
|
||||
clusterList.list().actionMenu(rke2CustomName).getMenuItem('Edit Config').click();
|
||||
// We should be taken back to the list page if the save was successful
|
||||
clusterList.waitForPage();
|
||||
|
||||
editCreatedClusterPage.waitForPage('mode=edit', 'basic');
|
||||
editCreatedClusterPage.nameNsDescription().description().self().should('have.value', rke2CustomName);
|
||||
});
|
||||
clusterList.list().actionMenu(rke2CustomName).getMenuItem('Edit Config').click();
|
||||
|
||||
editCreatedClusterPage.waitForPage('mode=edit', 'basic');
|
||||
editCreatedClusterPage.nameNsDescription().description().self().should('have.value', rke2CustomName);
|
||||
});
|
||||
|
||||
it('can view cluster YAML editor', () => {
|
||||
|
|
@ -100,18 +96,19 @@ describe('Cluster Manager', () => {
|
|||
});
|
||||
|
||||
it('can delete cluster', () => {
|
||||
cy.intercept('DELETE', `${ clusterRequestBase }/${ rke2CustomName }`).as('deleteRequest');
|
||||
|
||||
clusterList.goTo();
|
||||
clusterList.sortableTable().rowElementWithName(rke2CustomName).should('exist', { timeout: 15000 });
|
||||
clusterList.list().actionMenu(rke2CustomName).getMenuItem('Delete').click();
|
||||
|
||||
const promptRemove = new PromptRemove();
|
||||
clusterList.sortableTable().rowNames().then((rows: any) => {
|
||||
const promptRemove = new PromptRemove();
|
||||
|
||||
promptRemove.confirm(rke2CustomName);
|
||||
promptRemove.remove();
|
||||
promptRemove.confirm(rke2CustomName);
|
||||
promptRemove.remove();
|
||||
|
||||
cy.wait('@deleteRequest').then(() => {
|
||||
return clusterList.sortableTable().rowElementWithName(rke2CustomName).should('not.exist', { timeout: 15000 });
|
||||
clusterList.waitForPage();
|
||||
clusterList.sortableTable().checkRowCount(false, rows.length - 1);
|
||||
clusterList.sortableTable().rowNames().should('not.contain', rke2CustomName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -146,20 +143,21 @@ describe('Cluster Manager', () => {
|
|||
});
|
||||
|
||||
it('can delete cluster by bulk actions', () => {
|
||||
cy.intercept('DELETE', `${ clusterRequestBase }/${ importGenericName }`).as('deleteRequest');
|
||||
|
||||
clusterList.goTo();
|
||||
clusterList.sortableTable().rowElementWithName(importGenericName).should('exist', { timeout: 15000 });
|
||||
clusterList.sortableTable().rowSelectCtlWithName(importGenericName).set();
|
||||
clusterList.sortableTable().bulkActionDropDownOpen();
|
||||
clusterList.sortableTable().bulkActionDropDownButton('Delete').click();
|
||||
|
||||
const promptRemove = new PromptRemove();
|
||||
clusterList.sortableTable().rowNames().then((rows: any) => {
|
||||
const promptRemove = new PromptRemove();
|
||||
|
||||
promptRemove.confirm(importGenericName);
|
||||
promptRemove.remove();
|
||||
promptRemove.confirm(importGenericName);
|
||||
promptRemove.remove();
|
||||
|
||||
cy.wait('@deleteRequest').then(() => {
|
||||
return clusterList.sortableTable().rowElementWithName(importGenericName).should('not.exist', { timeout: 15000 });
|
||||
clusterList.waitForPage();
|
||||
clusterList.sortableTable().checkRowCount(false, rows.length - 1);
|
||||
clusterList.sortableTable().rowNames().should('not.contain', importGenericName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
"mem-dev": "bash -c 'source ./scripts/version && NODE_ENV=dev node --max-old-space-size=8192 ./node_modules/.bin/vue-cli-service serve'",
|
||||
"docker-dev": "docker run --rm --name dashboard-dev -p 8005:8005 -e API=$API -v $(pwd):/src -v dashboard_node:/src/node_modules rancher/dashboard:dev",
|
||||
"docker:local:start": "docker run -d --restart=unless-stopped -p 80:80 -p 443:443 -e CATTLE_BOOTSTRAP_PASSWORD=password -e CATTLE_PASSWORD_MIN_LENGTH=3 --name cypress --privileged rancher/rancher:v2.7-head",
|
||||
"docker:local:stop": "docker kill cypress || docker rm cypress || true",
|
||||
"docker:local:stop": "docker kill cypress || true && docker rm cypress || true",
|
||||
"build": "NODE_OPTIONS=--max_old_space_size=4096 ./node_modules/.bin/vue-cli-service build",
|
||||
"build:lib": "cd pkg/rancher-components && yarn build:lib",
|
||||
"analyze": "./node_modules/.bin/vue-cli-service build --report",
|
||||
|
|
@ -43,8 +43,8 @@
|
|||
"cy:run:sorry": "./scripts/e2e",
|
||||
"e2e:pre-dev": "yarn docker:local:stop && yarn docker:local:start && NODE_ENV=dev TEST_INSTRUMENT=true yarn build",
|
||||
"e2e:dev": "START_SERVER_AND_TEST_INSECURE=1 server-test start:dev https-get://localhost:8005 cy:run:sorry",
|
||||
"e2e:pre-prod": "yarn docker:local:stop && yarn docker:local:start && DEV_PORTS=true TEST_INSTRUMENT=true yarn build",
|
||||
"e2e:prod": "START_SERVER_AND_TEST_INSECURE=1 server-test start:prod https-get://localhost:8005 cy:run:sorry",
|
||||
"e2e:pre-prod": "yarn docker:local:stop && mkdir dist && TEST_INSTRUMENT=true ./scripts/build-e2e && ./scripts/e2e-docker-start ",
|
||||
"e2e:prod": "TEST_BASE_URL=https://127.0.0.1/dashboard yarn cy:run:sorry && yarn docker:local:stop",
|
||||
"coverage": "npx nyc merge coverage coverage/coverage.json",
|
||||
"storybook": "cd storybook && yarn install && yarn storybook",
|
||||
"build-storybook": "cd storybook && yarn install && NODE_OPTIONS=--max_old_space_size=4096 yarn build-storybook --quiet",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# Builds a production version of dashboard directly in the dist folder with the
|
||||
# base configured to be /dashboard so that this can be mapped or copied into a docker container
|
||||
# deploymet of Rancher
|
||||
|
||||
# This is currently used by the e2e tests to build a version of dashboard and map this into
|
||||
# the docker container to avoid having to run a separate node process to serve up the dashboard static assets
|
||||
|
||||
BUILD_DEBUG="${BUILD_DEBUG:-}"
|
||||
if [[ -n "${BUILD_DEBUG}" ]]; then
|
||||
set -x
|
||||
env
|
||||
fi
|
||||
|
||||
cd $(dirname $0)/..
|
||||
|
||||
echo "Building production build for e2e ..."
|
||||
yarn --pure-lockfile install
|
||||
|
||||
source scripts/version
|
||||
echo "BRANCH: ${COMMIT_BRANCH:-<none>}"
|
||||
echo "TAG: ${GIT_TAG:-<none>}"
|
||||
|
||||
OUTPUT_DIR=dist
|
||||
|
||||
echo "Building..."
|
||||
COMMIT=${COMMIT} VERSION=${VERSION} OUTPUT_DIR=$OUTPUT_DIR ROUTER_BASE='/dashboard/' RESOURCE_BASE='/dashboard/' yarn run build
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
DIR=$(cd $(dirname $0)/..; pwd)
|
||||
|
||||
DIST=${DIR}/dist
|
||||
|
||||
docker run -d --restart=unless-stopped -p 80:80 -p 443:443 \
|
||||
-v ${DIST}:/usr/share/rancher/ui-dashboard/dashboard \
|
||||
-e CATTLE_UI_OFFLINE_PREFERRED=true \
|
||||
-e CATTLE_BOOTSTRAP_PASSWORD=password \
|
||||
-e CATTLE_PASSWORD_MIN_LENGTH=3 \
|
||||
--name cypress \
|
||||
--privileged \
|
||||
rancher/rancher:v2.7-head
|
||||
|
||||
docker ps
|
||||
|
||||
echo "Waiting for dashboard UI to be reachable (initial 20s wait) ..."
|
||||
|
||||
sleep 20
|
||||
|
||||
echo "Waiting for dashboard UI to be reachable ..."
|
||||
|
||||
okay=0
|
||||
|
||||
while [ $okay -lt 20 ]; do
|
||||
STATUS=$(curl --silent --head -k https://127.0.0.1/dashboard/ | awk '/^HTTP/{print $2}')
|
||||
|
||||
echo "Status: $STATUS (Try: $okay)"
|
||||
|
||||
okay=$((okay+1))
|
||||
|
||||
if [ "$STATUS" == "200" ]; then
|
||||
okay=100
|
||||
else
|
||||
sleep 5
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$STATUS" != "200" ]; then
|
||||
echo "Dashboard did not become available in a reasonable time"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Dashboard UI is ready"
|
||||
Loading…
Reference in New Issue