diff --git a/e2e-tests/cypress.config.js b/e2e-tests/cypress.config.js index 9d55ded28..007afe056 100644 --- a/e2e-tests/cypress.config.js +++ b/e2e-tests/cypress.config.js @@ -32,6 +32,9 @@ module.exports = defineConfig({ case 'browse-data': serverProcess = exec('yarn start:browse-data'); break; + case 'team': + serverProcess = exec('yarn start:team'); + break; } await waitOn({ resources: ['http://localhost:3000'] }); diff --git a/e2e-tests/cypress/e2e/browse-data.cy.js b/e2e-tests/cypress/e2e/browse-data.cy.js index 661696de5..e0214e81d 100644 --- a/e2e-tests/cypress/e2e/browse-data.cy.js +++ b/e2e-tests/cypress/e2e/browse-data.cy.js @@ -321,4 +321,31 @@ describe('Data browser data', () => { cy.testid('WidgetIconPanel_cell-data').click(); cy.themeshot('collection'); }); + + it('Table structure editor', () => { + cy.contains('MySql-connection').click(); + cy.contains('MyChinook').click(); + cy.contains('Customer').rightclick(); + cy.contains('Open structure').click(); + cy.contains('varchar(40)'); + cy.themeshot('structure'); + cy.contains('EmployeeId').click(); + cy.contains('Ref column - Employee'); + cy.themeshot('fkeditor'); + }); + + it('Compare database', () => { + // TODO FIX: SQL diff is not dark in dark mode + cy.contains('MySql-connection').click(); + cy.contains('MyChinook').click(); + cy.contains('MyChangedChinook').rightclick(); + cy.contains('Compare with').click(); + cy.testid('CompareModelTab_gridObjects_Customer_Customer').click(); + cy.testid('WidgetIconPanel_database').click(); + cy.testid('CompareModelTab_tabDdl').click(); + cy.themeshot('dbcompare'); + cy.contains('Settings').click(); + cy.testid('CompareModelTab_tabOperations').click(); + cy.themeshot('comparesettings'); + }); }); diff --git a/e2e-tests/cypress/e2e/team.cy.js b/e2e-tests/cypress/e2e/team.cy.js new file mode 100644 index 000000000..f60d7c597 --- /dev/null +++ b/e2e-tests/cypress/e2e/team.cy.js @@ -0,0 +1,30 @@ +beforeEach(() => { + cy.visit('http://localhost:3000'); + cy.viewport(1250, 900); +}); + +describe('Team edition tests', () => { + it('Data archive editor - macros', () => { + cy.testid('LoginPage_linkAdmin').click(); + cy.testid('LoginPage_password').type('adminpwd'); + cy.testid('LoginPage_submitLogin').click(); + + cy.testid('AdminMenuWidget_itemConnections').click(); + cy.contains('New connection').click(); + cy.contains('New connection').click(); + cy.contains('New connection').click(); + cy.testid('ConnectionDriverFields_connectionType').select('PostgreSQL'); + cy.themeshot('connadmin'); + + cy.testid('AdminMenuWidget_itemRoles').click(); + cy.contains('Permissions').click(); + cy.themeshot('roleadmin'); + + cy.testid('AdminMenuWidget_itemAuthentication').click(); + cy.contains('Add authentication').click(); + cy.contains('Use database login').click(); + cy.contains('Add authentication').click(); + cy.contains('OAuth 2.0').click(); + cy.themeshot('authadmin'); + }); +}); diff --git a/e2e-tests/data/chinook-mysql-changed.sql b/e2e-tests/data/chinook-mysql-changed.sql new file mode 100644 index 000000000..1a1465c16 --- /dev/null +++ b/e2e-tests/data/chinook-mysql-changed.sql @@ -0,0 +1,176 @@ + +/******************************************************************************* + Create Tables +********************************************************************************/ +CREATE TABLE `Album` +( + `AlbumId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(160) NOT NULL, + `ArtistId` INT NOT NULL, + CONSTRAINT `PK_Album` PRIMARY KEY (`AlbumId`) +); + +CREATE TABLE `Artist` +( + `ArtistId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(120), + CONSTRAINT `PK_Artist` PRIMARY KEY (`ArtistId`) +); + +CREATE TABLE `Customer` +( + `CustomerId` INT NOT NULL AUTO_INCREMENT, + `FirstName` NVARCHAR(40) NOT NULL, + `LastName` NVARCHAR(20) NOT NULL, + `MiddleName` NVARCHAR(20) NOT NULL, + `Company` NVARCHAR(80), + `Street` NVARCHAR(70), + `City` NVARCHAR(40), + `State` NVARCHAR(40), + `Country` NVARCHAR(40), + `PostalCode` NVARCHAR(10), + `Phone` NVARCHAR(24), + `Fax` NVARCHAR(24), + `Email` NVARCHAR(60) NOT NULL, + `SupportRepId` INT, + CONSTRAINT `PK_Customer` PRIMARY KEY (`CustomerId`) +); + +CREATE TABLE `Employee` +( + `EmployeeId` INT NOT NULL AUTO_INCREMENT, + `LastName` NVARCHAR(20) NOT NULL, + `FirstName` NVARCHAR(20) NOT NULL, + `Title` NVARCHAR(30), + `ReportsTo` INT, + `BirthDate` DATETIME, + `HireDate` DATETIME, + `Address` NVARCHAR(70), + `City` NVARCHAR(40), + `State` NVARCHAR(40), + `Country` NVARCHAR(40), + `PostalCode` NVARCHAR(10), + `Phone` NVARCHAR(24), + `Fax` NVARCHAR(24), + `Email` NVARCHAR(60), + CONSTRAINT `PK_Employee` PRIMARY KEY (`EmployeeId`) +); + +CREATE TABLE `Genre` +( + `GenreId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(120), + CONSTRAINT `PK_Genre` PRIMARY KEY (`GenreId`) +); + +CREATE TABLE `Genre_Backup` +( + `GenreId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(120), + CONSTRAINT `PK_GenreBackup` PRIMARY KEY (`GenreId`) +); + +CREATE TABLE `Invoice` +( + `InvoiceId` INT NOT NULL AUTO_INCREMENT, + `CustomerId` INT NOT NULL, + `InvoiceDate` DATETIME NOT NULL, + `BillingAddress` NVARCHAR(70), + `BillingCity` NVARCHAR(40), + `BillingState` NVARCHAR(40), + `BillingCountry` NVARCHAR(40), + `BillingPostalCode` NVARCHAR(10), + `Total` NUMERIC(10,2) NOT NULL, + CONSTRAINT `PK_Invoice` PRIMARY KEY (`InvoiceId`) +); + + +CREATE TABLE `MediaType` +( + `MediaTypeId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(120), + CONSTRAINT `PK_MediaType` PRIMARY KEY (`MediaTypeId`) +); + +CREATE TABLE `Playlist` +( + `PlaylistId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(120), + CONSTRAINT `PK_Playlist` PRIMARY KEY (`PlaylistId`) +); + +CREATE TABLE `PlaylistTrack` +( + `PlaylistId` INT NOT NULL, + `TrackId` INT NOT NULL, + CONSTRAINT `PK_PlaylistTrack` PRIMARY KEY (`PlaylistId`, `TrackId`) +); + +CREATE TABLE `Track` +( + `TrackId` INT NOT NULL AUTO_INCREMENT, + `Name` NVARCHAR(200) NOT NULL, + `AlbumId` INT, + `MediaTypeId` INT NOT NULL, + `GenreId` INT, + `Composer` NVARCHAR(220), + `Milliseconds` INT NOT NULL, + `Bytes` INT, + `UnitPrice` NUMERIC(10,2) NOT NULL, + CONSTRAINT `PK_Track` PRIMARY KEY (`TrackId`) +); + + + +/******************************************************************************* + Create Primary Key Unique Indexes +********************************************************************************/ + +/******************************************************************************* + Create Foreign Keys +********************************************************************************/ +ALTER TABLE `Album` ADD CONSTRAINT `FK_AlbumArtistId` + FOREIGN KEY (`ArtistId`) REFERENCES `Artist` (`ArtistId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_AlbumArtistId` ON `Album` (`ArtistId`); + +ALTER TABLE `Customer` ADD CONSTRAINT `FK_CustomerSupportRepId` + FOREIGN KEY (`SupportRepId`) REFERENCES `Employee` (`EmployeeId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_CustomerSupportRepId` ON `Customer` (`SupportRepId`); + +ALTER TABLE `Employee` ADD CONSTRAINT `FK_EmployeeReportsTo` + FOREIGN KEY (`ReportsTo`) REFERENCES `Employee` (`EmployeeId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_EmployeeReportsTo` ON `Employee` (`ReportsTo`); + +ALTER TABLE `Invoice` ADD CONSTRAINT `FK_InvoiceCustomerId` + FOREIGN KEY (`CustomerId`) REFERENCES `Customer` (`CustomerId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_InvoiceCustomerId` ON `Invoice` (`CustomerId`); + +ALTER TABLE `PlaylistTrack` ADD CONSTRAINT `FK_PlaylistTrackPlaylistId` + FOREIGN KEY (`PlaylistId`) REFERENCES `Playlist` (`PlaylistId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_PlaylistTrackPlaylistId` ON `PlaylistTrack` (`PlaylistId`); + +ALTER TABLE `PlaylistTrack` ADD CONSTRAINT `FK_PlaylistTrackTrackId` + FOREIGN KEY (`TrackId`) REFERENCES `Track` (`TrackId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_PlaylistTrackTrackId` ON `PlaylistTrack` (`TrackId`); + +ALTER TABLE `Track` ADD CONSTRAINT `FK_TrackAlbumId` + FOREIGN KEY (`AlbumId`) REFERENCES `Album` (`AlbumId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_TrackAlbumId` ON `Track` (`AlbumId`); + +ALTER TABLE `Track` ADD CONSTRAINT `FK_TrackGenreId` + FOREIGN KEY (`GenreId`) REFERENCES `Genre` (`GenreId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_TrackGenreId` ON `Track` (`GenreId`); + +ALTER TABLE `Track` ADD CONSTRAINT `FK_TrackMediaTypeId` + FOREIGN KEY (`MediaTypeId`) REFERENCES `MediaType` (`MediaTypeId`) ON DELETE NO ACTION ON UPDATE NO ACTION; + +CREATE INDEX `IFK_TrackMediaTypeId` ON `Track` (`MediaTypeId`); + diff --git a/e2e-tests/env/team/.env b/e2e-tests/env/team/.env new file mode 100644 index 000000000..fbb92b076 --- /dev/null +++ b/e2e-tests/env/team/.env @@ -0,0 +1,7 @@ +STORAGE_SERVER=localhost +STORAGE_USER=root +STORAGE_PASSWORD=Pwd2020Db +STORAGE_PORT=16004 +STORAGE_DATABASE=DbGateInternal +STORAGE_ENGINE=mysql@dbgate-plugin-mysql +ADMIN_PASSWORD=adminpwd diff --git a/e2e-tests/init/browse-data.js b/e2e-tests/init/browse-data.js index af39483c0..151d59502 100644 --- a/e2e-tests/init/browse-data.js +++ b/e2e-tests/init/browse-data.js @@ -178,6 +178,7 @@ async function copyFolder(source, target) { async function run() { await initMySqlDatabase('MyChinook', path.resolve(path.join(__dirname, '../data/chinook-mysql.sql'))); + await initMySqlDatabase('MyChangedChinook', path.resolve(path.join(__dirname, '../data/chinook-mysql-changed.sql'))); // await initMySqlDatabase('Northwind', path.resolve(path.join(__dirname, '../data/northwind-mysql.sql'))); // await initMySqlDatabase('Sakila', path.resolve(path.join(__dirname, '../data/sakila-mysql.sql'))); diff --git a/e2e-tests/init/team.js b/e2e-tests/init/team.js new file mode 100644 index 000000000..f83f17371 --- /dev/null +++ b/e2e-tests/init/team.js @@ -0,0 +1,34 @@ +const dbgateApi = require('dbgate-api'); +dbgateApi.initializeApiEnvironment(); +const dbgatePluginMysql = require('dbgate-plugin-mysql'); +dbgateApi.registerPlugins(dbgatePluginMysql); + +async function initStorageDatabase() { + await dbgateApi.executeQuery({ + connection: { + server: process.env.STORAGE_SERVER, + user: process.env.STORAGE_USER, + password: process.env.STORAGE_PASSWORD, + port: process.env.STORAGE_PORT, + engine: process.env.STORAGE_ENGINE, + }, + sql: `drop database if exists ${process.env.STORAGE_DATABASE}`, + }); + + await dbgateApi.executeQuery({ + connection: { + server: process.env.STORAGE_SERVER, + user: process.env.STORAGE_USER, + password: process.env.STORAGE_PASSWORD, + port: process.env.STORAGE_PORT, + engine: process.env.STORAGE_ENGINE, + }, + sql: `create database ${process.env.STORAGE_DATABASE}`, + }); +} + +async function run() { + await initStorageDatabase(); +} + +dbgateApi.runScript(run); diff --git a/e2e-tests/package.json b/e2e-tests/package.json index 04b0e2494..7500464dc 100644 --- a/e2e-tests/package.json +++ b/e2e-tests/package.json @@ -14,15 +14,26 @@ }, "scripts": { "cy:open": "cypress open --config experimentalInteractiveRunEvents=true", + "cy:run:add-connection": "cypress run --spec cypress/e2e/add-connection.cy.js", "cy:run:portal": "cypress run --spec cypress/e2e/portal.cy.js", "cy:run:oauth": "cypress run --spec cypress/e2e/oauth.cy.js", "cy:run:browse-data": "cypress run --spec cypress/e2e/browse-data.cy.js", + "cy:run:team": "cypress run --spec cypress/e2e/team.cy.js", + "start:add-connection": "cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests", "start:portal": "cd .. && env-cmd -f e2e-tests/env/portal/.env node e2e-tests/init/portal.js && env-cmd -f e2e-tests/env/portal/.env node packer/build/bundle.js --listen-api --run-e2e-tests", "start:oauth": "cd .. && env-cmd -f e2e-tests/env/oauth/.env node packer/build/bundle.js --listen-api --run-e2e-tests", "start:browse-data": "cd .. && env-cmd -f e2e-tests/env/browse-data/.env node e2e-tests/init/browse-data.js && env-cmd -f e2e-tests/env/browse-data/.env node packer/build/bundle.js --listen-api --run-e2e-tests", - "test": "start-server-and-test start:add-connection http://localhost:3000 cy:run:add-connection && start-server-and-test start:portal http://localhost:3000 cy:run:portal && start-server-and-test start:oauth http://localhost:3000 cy:run:oauth && start-server-and-test start:browse-data http://localhost:3000 cy:run:browse-data", + "start:team": "cd .. && env-cmd -f e2e-tests/env/team/.env node e2e-tests/init/team.js && env-cmd -f e2e-tests/env/team/.env node packer/build/bundle.js --listen-api --run-e2e-tests", + + "test:add-connection": "start-server-and-test start:add-connection http://localhost:3000 cy:run:add-connection", + "test:portal": "start-server-and-test start:portal http://localhost:3000 cy:run:portal", + "test:oauth": "start-server-and-test start:oauth http://localhost:3000 cy:run:oauth", + "test:browse-data": "start-server-and-test start:browse-data http://localhost:3000 cy:run:browse-data", + "test:team": "start-server-and-test start:team http://localhost:3000 cy:run:team", + + "test": "yarn test:add-connection && yarn test:portal && yarn test:oauth && yarn test:browse-data && yarn test:team", "test:ci": "yarn test" }, "dependencies": {} diff --git a/packages/web/src/LoginPage.svelte b/packages/web/src/LoginPage.svelte index 6e5070ffd..71dc7515f 100644 --- a/packages/web/src/LoginPage.svelte +++ b/packages/web/src/LoginPage.svelte @@ -137,9 +137,9 @@