[bitnami/spring-cloud-dataflow] Added the Spring Cloud Dataflow Helm chart tests (#9835)

* Created the Spring Cloud Dataflow tests

Signed-off-by: alukic <alukic@vmware.com>

* Trigger VIB for Spring Cloud Dataflow

Signed-off-by: alukic <alukic@vmware.com>

* Trigger version bump too

Signed-off-by: alukic <alukic@vmware.com>

* Removed comments

Signed-off-by: alukic <alukic@vmware.com>

* Change the pipeline syntax

Signed-off-by: alukic <alukic@vmware.com>

* Improved the tests, getting ready for the review'

Signed-off-by: alukic <alukic@vmware.com>

* Improved the tests

Signed-off-by: alukic <alukic@vmware.com>

* Added back the Goss tests

Signed-off-by: alukic <alukic@vmware.com>

* Made Goss tests even more minimalistic

Signed-off-by: alukic <alukic@vmware.com>

* Remove the test modification of files

Signed-off-by: alukic <alukic@vmware.com>

* Passed trough linter

Signed-off-by: alukic <alukic@vmware.com>

* Applied PR design suggestion

Signed-off-by: alukic <alukic@vmware.com>

* Updated tests, fixing the flaw in the design

Signed-off-by: alukic <alukic@vmware.com>

* Made changes in test design

Signed-off-by: alukic <alukic@vmware.com>

* Removed the plugin

Signed-off-by: alukic <alukic@vmware.com>

* Removed extra spaces

Signed-off-by: alukic <alukic@vmware.com>

* Fix the formatting issues

Signed-off-by: alukic <alukic@vmware.com>

* Remove a console log

Signed-off-by: alukic <alukic@vmware.com>

* Changed the locator from CSS selector

Signed-off-by: alukic <alukic@vmware.com>

* Applied the CR suggestions

Signed-off-by: alukic <alukic@vmware.com>

* Added regex to check if there are numbers in version

Signed-off-by: alukic <alukic@vmware.com>

* Improved code slightly

Signed-off-by: alukic <alukic@vmware.com>

* Apply PR suggestions

Signed-off-by: alukic <alukic@vmware.com>

* Applying PR suggestions

Signed-off-by: alukic <alukic@vmware.com>

* Applying PR suggestions

Signed-off-by: alukic <alukic@vmware.com>

* Locator change from CSS to text

Signed-off-by: alukic <alukic@vmware.com>

* Formatting, locator change

Signed-off-by: alukic <alukic@vmware.com>

* Used fixture instead of static value

Signed-off-by: alukic <alukic@vmware.com>

* Replaced CSS selectors with text

Signed-off-by: alukic <alukic@vmware.com>

* Apply review suggestions

Signed-off-by: alukic <alukic@vmware.com>

* Reorganised the fixtures

Signed-off-by: alukic <alukic@vmware.com>

* Removed the Plugins

Signed-off-by: alukic <alukic@vmware.com>

* Fix a typo

Signed-off-by: alukic <alukic@vmware.com>

* Non-o instead od 1001 user

Signed-off-by: alukic <alukic@vmware.com>

* Changed the Goss test

Signed-off-by: alukic <alukic@vmware.com>

* User ID test improvement, fixture fix

Signed-off-by: alukic <alukic@vmware.com>

* Renamed files

Signed-off-by: alukic <alukic@vmware.com>

* Applied peer review comments

Signed-off-by: alukic <alukic@vmware.com>
This commit is contained in:
superaleks
2022-05-11 17:17:08 +02:00
committed by GitHub
parent e3cbaebaa8
commit 8d67e1d058
13 changed files with 285 additions and 2 deletions

View File

@@ -0,0 +1,5 @@
{
"baseUrl": "http://localhost",
"defaultCommandTimeout": 30000,
"pageLoadTimeout": 240000
}

View File

@@ -0,0 +1,8 @@
{
"newApplication": {
"streamApplicationType": "Stream application starters for Kafka/Maven",
"taskApplicationType": "Task application starters for Maven",
"streamApplication1": "mongodb",
"streamApplication2": "cassandra"
}
}

View File

@@ -0,0 +1,7 @@
{
"newSchedule": {
"name": "test-schedule",
"cronExpression": "*/5 * * * *",
"taskType": "timestamp"
}
}

View File

@@ -0,0 +1,6 @@
{
"newStream": {
"name": "test-stream",
"type": "mongodb | cassandra"
}
}

View File

@@ -0,0 +1,13 @@
{
"date": 1650360393208,
"tasks": [
{
"name": "test-task-imported",
"dslText": "timestamp",
"composed": false,
"status": "UNKNOWN",
"composedTaskElement": false,
"description": ""
}
]
}

View File

@@ -0,0 +1,5 @@
{
"newTask": {
"name": "test-task"
}
}

View File

@@ -0,0 +1,26 @@
/// <reference types="cypress" />
import { random } from './utils';
export const importAnApplication = (application) => {
cy.visit('/dashboard');
cy.contains('button', 'Add application(s)').click();
cy.contains('label', application).click();
cy.contains('.btn-primary', 'Import').click();
cy.get('.toast-container').should('contain', 'Application(s) Imported');
};
export const createATask = (taskType) => {
cy.visit('/dashboard/#/tasks-jobs/tasks');
cy.contains('button', 'Create task').click();
cy.get('.CodeMirror-line').type(taskType);
cy.contains('#v-2', taskType);
cy.contains('button', 'Create task').click();
cy.contains('.modal-content', 'Create task');
cy.fixture('tasks').then((task) => {
cy.get('input[placeholder="Task Name"]').type(
`${task.newTask.name}-${random}`
);
cy.get('input#desc').type('This is a task');
cy.contains('button', 'Create the task').click();
});
};

View File

@@ -0,0 +1,121 @@
/// <reference types="cypress" />
import { random } from './utils.js';
import { importAnApplication, createATask } from './prepare_app_state.js';
it('allows getting Spring Cloud Dataflow info', () => {
cy.visit('/dashboard');
cy.get('.signpost-trigger').click();
cy.get('.signpost-content-body')
.invoke('text')
.should('match', /.*[0-9].*/);
cy.contains('button', 'More info').click();
cy.contains('.modal-content', 'Core')
.and('contain', 'Dashboard')
.and('contain', 'Shell');
});
it('allows a stream to be created and deployed', () => {
cy.fixture('applications').then((application) => {
importAnApplication(application.newApplication.streamApplicationType);
});
cy.visit('dashboard/#/streams/list');
cy.contains('button', 'Create stream(s)').click();
cy.fixture('streams').then((stream) => {
cy.get('.CodeMirror-line').type(stream.newStream.type);
});
cy.fixture('applications').then((application) => {
cy.contains('#v-2', application.newApplication.streamApplication1).and(
'contain',
application.newApplication.streamApplication2
);
});
cy.contains('button', 'Create stream(s)').click();
cy.get('.modal-content').should('contain', 'Create Stream');
cy.fixture('streams').then((stream) => {
cy.get('input[placeholder="Stream Name"]').type(
`${stream.newStream.name}-${random}`
);
cy.contains('button', 'Create the stream').click();
cy.contains(
'.datagrid-inner-wrapper',
`${stream.newStream.name}-${random}`
);
cy.contains('.toast-container', 'successfully');
cy.contains('clr-dg-cell', 'UNDEPLOYED')
.siblings('clr-dg-cell', stream.newStream.name)
.first()
.click();
});
cy.contains('button#btn-deploy', 'Deploy stream').click();
cy.contains('button', 'Deploy stream').click();
cy.get('.toast-container').should('contain', 'Deploy success');
});
it('allows a task to be scheduled and destroyed', () => {
cy.fixture('applications').then((application) => {
importAnApplication(application.newApplication.taskApplicationType);
});
cy.fixture('schedules').then((schedule) => {
createATask(schedule.newSchedule.taskType);
});
cy.visit('dashboard/#/tasks-jobs/tasks');
cy.fixture('tasks').then((task) => {
cy.contains('clr-dg-cell', 'UNKNOWN')
.siblings('clr-dg-cell', task.newTask.name)
.first()
.click();
});
cy.contains('button', 'Schedule').click();
cy.fixture('schedules').then((schedule) => {
cy.get('input[name="example"]')
.first()
.type(`${schedule.newSchedule.name}-${random}`);
cy.get('input[name="example"]')
.last()
.type(`${schedule.newSchedule.cronExpression}`);
});
cy.contains('button', 'Create schedule(s)').click();
cy.contains('.toast-container', 'Successfully');
cy.contains('a', 'Tasks').click();
cy.contains('clr-dg-cell', 'UNKNOWN')
.siblings('clr-dg-cell', 'test-task-')
.first()
.click();
cy.contains('button', 'Destroy task').click();
cy.contains('button', 'Destroy the task').click();
cy.contains('1 task definition(s) destroyed.');
});
it('allows importing a task from a file and destroying it ', () => {
cy.visit('/dashboard/#/manage/tools');
cy.contains('a', 'Import tasks from a JSON file').click();
cy.get('input[type="file"]').selectFile(
'cypress/fixtures/task-to-import.json',
{ force: true }
);
cy.contains('button', 'Import').click();
cy.contains('1 task(s) created');
cy.get('.close').click();
cy.visit('dashboard/#/tasks-jobs/tasks');
cy.contains('button', 'Group Actions').click();
cy.get('[aria-label="Select All"]').click({ force: true });
cy.contains('button', 'Destroy task').click();
cy.contains('.modal-content', 'Confirm Destroy Task');
cy.contains('button', 'Destroy the task').click();
cy.get('.toast-container').should('contain', 'destroyed');
});
it('allows unregistering of an application', () => {
cy.fixture('applications').then((application) => {
importAnApplication(application.newApplication.streamApplicationType);
});
cy.get('clr-dg-cell').siblings('clr-dg-cell', 'PROCESSOR').first().click();
cy.contains('button', 'Unregister Application').click();
cy.contains('button', 'Unregister the application').click();
cy.contains('Successfully removed app');
});

View File

@@ -0,0 +1 @@
export let random = (Math.random() + 1).toString(36).substring(7);

View File

@@ -0,0 +1,26 @@
const CLICK_DELAY = 800;
const TYPE_DELAY = 200;
for (const command of ['click']) {
Cypress.Commands.overwrite(command, (originalFn, ...args) => {
const origVal = originalFn(...args);
return new Promise((resolve) => {
setTimeout(() => {
resolve(origVal);
}, CLICK_DELAY);
});
});
}
for (const command of ['type']) {
Cypress.Commands.overwrite(command, (originalFn, ...args) => {
const origVal = originalFn(...args);
return new Promise((resolve) => {
setTimeout(() => {
resolve(origVal);
}, TYPE_DELAY);
});
});
}

View File

@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -0,0 +1,22 @@
file:
/opt/bitnami/spring-cloud-dataflow/conf/application.yml:
exists: true
filetype: symlink
mode: "0777"
owner: root
/bitnami/spring-cloud-dataflow:
exists: true
filetype: directory
mode: "0775"
owner: root
command:
user-id-test:
exec: if [ "$(id -u)" -eq 0 ]; then exit 1; fi
exit-status: 0
stdout: []
stderr: []
java-test:
exec: java -version
exit-status: 0
stdout:
stderr: []

View File

@@ -22,7 +22,7 @@
"url": "{SHA_ARCHIVE}",
"path": "/bitnami/spring-cloud-dataflow"
},
"runtime_parameters": "InNlcnZlciI6CiAgInNlcnZpY2UiOgogICAgInBvcnQiOiA4MAogICAgInR5cGUiOiAiTG9hZEJhbGFuY2VyIg==",
"runtime_parameters": "c2VydmVyOgogIHNlcnZpY2U6CiAgICB0eXBlOiBMb2FkQmFsYW5jZXIKICAgIHBvcnQ6IDgwCg==",
"target_platform": {
"target_platform_id": "{VIB_ENV_TARGET_PLATFORM}",
"size": {
@@ -35,7 +35,9 @@
"action_id": "trivy",
"params": {
"threshold": "CRITICAL",
"vuln_type": ["OS"]
"vuln_type": [
"OS"
]
}
},
{
@@ -44,6 +46,27 @@
"endpoint": "lb-spring-cloud-dataflow-server-http",
"app_protocol": "HTTP"
}
},
{
"action_id": "goss",
"params": {
"resources": {
"path": "/.vib/spring-cloud-dataflow/goss"
},
"remote": {
"workload": "deploy-spring-cloud-dataflow-server"
}
}
},
{
"action_id": "cypress",
"params": {
"resources": {
"path": "/.vib/spring-cloud-dataflow/cypress"
},
"endpoint": "lb-spring-cloud-dataflow-server-http",
"app_protocol": "HTTP"
}
}
]
}