Skip to content

Commit

Permalink
Track inserted items and delete them when test has finished
Browse files Browse the repository at this point in the history
  • Loading branch information
laoneo committed Mar 13, 2023
1 parent 52715d6 commit da343ee
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
afterEach(() => {
cy.task('queryDB', 'DELETE FROM #__content');
cy.task('queryDB', 'DELETE FROM #__content_frontpage');
cy.task('queryDB', 'DELETE FROM #__menu WHERE id > 101');
});

describe('Test that the list view ', () => {
['default', 'blog'].forEach((layout) => {
it(`can display a list of articles in the ${layout} layout in a menu item`, () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
afterEach(() => {
cy.task('queryDB', 'DELETE FROM #__content');
cy.task('queryDB', 'DELETE FROM #__content_frontpage');
});

describe('Test that the front page', () => {
it('can display an article', () => {
cy.db_createArticle({ title: 'automated test article' }).then(() => {
Expand Down
90 changes: 85 additions & 5 deletions tests/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
const mysql = require('mysql');
const postgres = require('postgres');

// Rows cache of items which got inserted
let insertedItems = [];

/**
* Does run the given query against the database from the configuration. It caches all inserted items.
*
* @param {string} query
* @param {object} config The config
* @returns Promise
*/
function queryTestDB(query, config) {
// Parse the table name
const tableNameOfInsert = query.match(/insert\s+into\s+(.*?)\s/i);

// Find an inserted item
let insertItem = tableNameOfInsert && tableNameOfInsert.length > 1 && insertedItems.find((item) => item.table === tableNameOfInsert[1]);

// If it is an insert query, but there is no cache object, create one
if (tableNameOfInsert && tableNameOfInsert.length > 1 && !insertItem) {
insertItem = { table: tableNameOfInsert[1], rows: [] };

// Push it to the cache
insertedItems.push(insertItem);
}

// Check if the DB is from postgres
if (config.env.db_type === 'pgsql' || config.env.db_type === 'PostgreSQL (PDO)') {
const connection = postgres({
host: config.env.db_host,
Expand All @@ -13,24 +38,31 @@ function queryTestDB(query, config) {
});

// Postgres delivers the data direct as result of the insert query
if (query.indexOf('INSERT') === 0) {
if (insertItem) {
query += ' returning *'
}

// Postgres needs double quotes
query = query.replaceAll('\`', '"');

return connection.unsafe(query).then((result) => {
if (query.indexOf('INSERT') !== 0 || result.length === 0) {
if (!insertItem || result.length === 0) {
return result;
}

// Push the id to the cache when it is an insert operation
if (insertItem && result.length && result[0].id) {
insertItem.rows.push(result[0].id);
}

// Normalize the object
return { insertId: result[0].id };
});
}

// Return a promise when resolves the query
return new Promise((resolve, reject) => {
// Create the connection and connect
const connection = mysql.createConnection({
host: config.env.db_host,
user: config.env.db_user,
Expand All @@ -39,14 +71,62 @@ function queryTestDB(query, config) {
});
connection.connect();

connection.query(query, (error, results) => !error || !error.errno ? resolve(results) : reject(error));
// Perform the query
connection.query(query, (error, results) => {
// Reject when an error
if (error && error.errno) {
return reject(error);
}

// Push the id to the cache when it is an insert operation
if (insertItem && results && results.insertId) {
insertItem.rows.push(results.insertId);
}

// Resolve the result
resolve(results);
});
});
};

/**
* Deletes the inserted items from the database.
*
* @param {object} config The configuration
* @returns null
*/
function deleteInsertedItems(config) {
// Loop over the cached items
insertedItems.forEach((item) => {
// When there is nothing to delete, ignore it
if (item.rows.length < 1) {
return;
}

// Delete the items from the database
queryTestDB('DELETE FROM ' + item.table + ' WHERE ID IN (' + item.rows.join(',') + ')', config);
});

// Clear the cache
insertedItems = [];

// Cypress wants a return value
return null;
};

/**
* Does the setup of the plugins.
*
* @param {*} on
* @param {object} config The configuration
*
* @see https://docs.cypress.io/guides/references/configuration#setupNodeEvents
*/
function setupPlugins(on, config) {
on('task', {
queryDB: (query) => queryTestDB(query.replace('#__', config.env.db_prefix), config)
queryDB: (query) => queryTestDB(query.replace('#__', config.env.db_prefix), config),
cleanupDB: () => deleteInsertedItems(config),
});
}
};

module.exports = setupPlugins;
89 changes: 44 additions & 45 deletions tests/cypress/support/commands/db.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,45 @@
Cypress.Commands.add('db_createArticle', (article) => {
const defaultArticleOptions = {
title: 'test article',
alias: 'test-article',
catid: 2,
introtext: '',
fulltext: '',
state: 1,
access: 1,
language: '*',
created: '2023-01-01 20:00:00',
modified: '2023-01-01 20:00:00',
images: '',
urls: '',
attribs: '',
metadesc: '',
metadata: ''
};
const defaultArticleOptions = {
title: 'test article',
alias: 'test-article',
catid: 2,
introtext: '',
fulltext: '',
state: 1,
access: 1,
language: '*',
created: '2023-01-01 20:00:00',
modified: '2023-01-01 20:00:00',
images: '',
urls: '',
attribs: '',
metadesc: '',
metadata: ''
};

return cy.task('queryDB', createInsertQuery('content', {...defaultArticleOptions, ...article})).then((info) =>
cy.task('queryDB', "INSERT INTO #__content_frontpage (content_id, ordering) VALUES ('" + info.insertId + "', '1')")
);
return cy.task('queryDB', createInsertQuery('content', { ...defaultArticleOptions, ...article })).then((info) =>
cy.task('queryDB', "INSERT INTO #__content_frontpage (content_id, ordering) VALUES ('" + info.insertId + "', '1')").then(() => info));
});

Cypress.Commands.add('db_createMenuItem', (menuItem) => {
const defaultMenuItemOptions = {
title: 'test menu item',
alias: 'test-menu-item',
menutype: 'mainmenu',
type: 'component',
link: 'index.php?option=com_content',
component_id: 19,
path: 'test-menu-item/root',
parent_id: 1,
level: 1,
published: 1,
access: 1,
language: '*',
params: '',
img: ''
};
const defaultMenuItemOptions = {
title: 'test menu item',
alias: 'test-menu-item',
menutype: 'mainmenu',
type: 'component',
link: 'index.php?option=com_content',
component_id: 19,
path: 'test-menu-item/root',
parent_id: 1,
level: 1,
published: 1,
access: 1,
language: '*',
params: '',
img: ''
};

return cy.task('queryDB', createInsertQuery('menu', {...defaultMenuItemOptions, ...menuItem}));
return cy.task('queryDB', createInsertQuery('menu', { ...defaultMenuItemOptions, ...menuItem }));
});

/**
Expand All @@ -51,10 +50,10 @@ Cypress.Commands.add('db_createMenuItem', (menuItem) => {
*
* @returns string
*/
function createInsertQuery (table, values) {
const query= 'INSERT INTO #__' + table + ' (\`' + Object.keys(values).join('\`, \`') + '\`) VALUES (:' + Object.keys(values).join(',:') + ')';
function createInsertQuery(table, values) {
const query = 'INSERT INTO #__' + table + ' (\`' + Object.keys(values).join('\`, \`') + '\`) VALUES (:' + Object.keys(values).join(',:') + ')';

return prepareQuery(query, values);
return prepareQuery(query, values);
}

/**
Expand All @@ -66,10 +65,10 @@ function createInsertQuery (table, values) {
*
* @returns string
*/
function prepareQuery (query, values) {
Object.keys(values).forEach((variable) => {
query = query.replace(':' + variable, "'" + values[variable] + "'");
});
function prepareQuery(query, values) {
Object.keys(values).forEach((variable) => {
query = query.replace(':' + variable, "'" + values[variable] + "'");
});

return query;
return query;
}
20 changes: 11 additions & 9 deletions tests/cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import './commands'
import 'joomla-cypress'
import './commands';
import 'joomla-cypress';

before(function() {
const {registerCommands} = require('../../../node_modules/joomla-cypress/src/index.js')
before(function () {
const { registerCommands } = require('../../../node_modules/joomla-cypress/src/index.js');

registerCommands()
registerCommands();

Cypress.on('uncaught:exception', (err, runnable) => {
console.log("err :" + err)
console.log("runnable :" + runnable)
console.log("err :" + err);
console.log("runnable :" + runnable);
return false
})
})
});
});

afterEach(() => cy.task('cleanupDB'));

0 comments on commit da343ee

Please sign in to comment.