diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml new file mode 100644 index 000000000..f5ecce628 --- /dev/null +++ b/.github/workflows/e2e-tests.yaml @@ -0,0 +1,41 @@ +name: E2E tests +on: + push: + branches: + - master + - develop + - 'feature/**' + +jobs: + e2e-tests: + runs-on: ubuntu-latest + container: node:18 + + steps: + - name: Install dependencies + run: | + apt-get update + apt-get install -y xvfb libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - name: yarn install + run: | + yarn install + - name: Build + run: | + yarn prepare:packer + - name: yarn install cypress + run: | + cd e2e-tests + yarn install + - name: Run Cypress tests + run: | + cd e2e-tests + yarn test:ci + + services: + mysql: + image: mysql:8.0.18 + env: + MYSQL_ROOT_PASSWORD: Pwd2020Db diff --git a/common/defineVolatileDependencies.js b/common/defineVolatileDependencies.js index 0997d62b7..e63c8ff23 100644 --- a/common/defineVolatileDependencies.js +++ b/common/defineVolatileDependencies.js @@ -14,7 +14,7 @@ for (const pkg of volatilePackages) { if (apiPackageJson.dependencies[pkg]) { dependencies[pkg] = apiPackageJson.dependencies[pkg]; } - if (apiPackageJson.optionalDependencies[pkg]) { + if (apiPackageJson.optionalDependencies?.[pkg]) { optionalDependencies[pkg] = apiPackageJson.optionalDependencies[pkg]; } } diff --git a/e2e-tests/cypress.config.js b/e2e-tests/cypress.config.js new file mode 100644 index 000000000..ce6efca4f --- /dev/null +++ b/e2e-tests/cypress.config.js @@ -0,0 +1,29 @@ +const { defineConfig } = require('cypress'); +const killPort = require('kill-port'); +const { clearDataWithBackup } = require('./e2eTestTools'); +const waitOn = require('wait-on'); +const { exec } = require('child_process'); + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + + on('before:spec', async details => { + await clearDataWithBackup(); + + if (config.isInteractive) { + await killPort(3000); + serverProcess = exec('yarn start'); + await waitOn({ resources: ['http://localhost:3000'] }); + serverProcess.stdout.on('data', data => { + console.log(data.toString()); + }); + serverProcess.stderr.on('data', data => { + console.error(data.toString()); + }); + } + }); + }, + }, +}); diff --git a/e2e-tests/cypress/e2e/connect.cy.js b/e2e-tests/cypress/e2e/connect.cy.js new file mode 100644 index 000000000..39bf8a110 --- /dev/null +++ b/e2e-tests/cypress/e2e/connect.cy.js @@ -0,0 +1,31 @@ +describe('Initialization', () => { + it('successfully loads', () => { + cy.visit('http://localhost:3000'); + cy.contains('Database not selected'); + }); + + it('adds connection', () => { + const runOnCI = Cypress.env('runOnCI'); + + cy.visit('http://localhost:3000'); + // cy.get('[data-testid=ConnectionList_buttonNewConnection]').click(); + cy.get('[data-testid=ConnectionDriverFields_connectionType]').select('MySQL'); + cy.get('[data-testid=ConnectionDriverFields_user]').clear().type('root'); + cy.get('[data-testid=ConnectionDriverFields_password]').clear().type('Pwd2020Db'); + if (runOnCI) { + cy.get('[data-testid=ConnectionDriverFields_server]').clear().type('mysql'); + } else { + cy.get('[data-testid=ConnectionDriverFields_port]').clear().type('16004'); + } + cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-1'); + cy.get('[data-testid=ConnectionTab_buttonSave]').click(); + cy.get('[data-testid=ConnectionTab_buttonConnect]').click(); + cy.contains('performance_schema'); + }); + + // it('import chinook DB', () => { + // cy.visit('http://localhost:3000'); + // cy.get('[data-testid=ConnectionTab_buttonConnect]').click(); + // }); + +}); diff --git a/e2e-tests/cypress/fixtures/example.json b/e2e-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/e2e-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/e2e-tests/cypress/support/commands.js b/e2e-tests/cypress/support/commands.js new file mode 100644 index 000000000..66ea16ef0 --- /dev/null +++ b/e2e-tests/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file diff --git a/e2e-tests/cypress/support/e2e.js b/e2e-tests/cypress/support/e2e.js new file mode 100644 index 000000000..0e7290a13 --- /dev/null +++ b/e2e-tests/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.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') \ No newline at end of file diff --git a/e2e-tests/e2eTestTools.js b/e2e-tests/e2eTestTools.js new file mode 100644 index 000000000..3d34035be --- /dev/null +++ b/e2e-tests/e2eTestTools.js @@ -0,0 +1,32 @@ +const path = require('path'); +const os = require('os'); +const fs = require('fs'); + +const baseDir = path.join(os.homedir(), '.dbgate'); + +function createTimeStamp() { + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); // měsíc je 0-indexovaný + const day = String(now.getDate()).padStart(2, '0'); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + + // Poskládáme datum a čas do názvu souboru + const ts = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`; + return ts; +} + +function clearDataWithBackup() { + if (fs.existsSync(path.join(baseDir, 'connections.jsonl'))) { + fs.renameSync( + path.join(baseDir, 'connections.jsonl'), + path.join(baseDir, `connections-${createTimeStamp()}.jsonl.bak`) + ); + } +} + +module.exports = { + clearDataWithBackup, +}; diff --git a/e2e-tests/package.json b/e2e-tests/package.json index 3d8b3dc5f..0f5eff1b0 100644 --- a/e2e-tests/package.json +++ b/e2e-tests/package.json @@ -4,6 +4,18 @@ "main": "index.js", "license": "GPL", "devDependencies": { - "cypress": "^13.16.1" + "axios": "^1.7.9", + "cross-env": "^7.0.3", + "cypress": "^13.16.1", + "kill-port": "^2.0.1", + "start-server-and-test": "^2.0.8" + }, + "scripts": { + "cy:open": "cypress open --config experimentalInteractiveRunEvents=true", + "cy:run": "cypress run", + "cy:run:ci": "cypress run --env runOnCI=true", + "start": "cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests", + "test:ci": "start-server-and-test start http://localhost:3000 cy:run:ci", + "test": "start-server-and-test start http://localhost:3000 cy:run" } } diff --git a/e2e-tests/yarn.lock b/e2e-tests/yarn.lock index 2dbe814d7..1a31e6637 100644 --- a/e2e-tests/yarn.lock +++ b/e2e-tests/yarn.lock @@ -39,6 +39,35 @@ debug "^3.1.0" lodash.once "^4.1.1" +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@types/node@*": version "22.10.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766" @@ -100,6 +129,11 @@ arch@^2.2.0: resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -142,6 +176,15 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== +axios@^1.7.7, axios@^1.7.9: + version "1.7.9" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" + integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -159,7 +202,7 @@ blob-util@^2.0.2: resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== -bluebird@^3.7.2: +bluebird@3.7.2, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -213,7 +256,7 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -check-more-types@^2.24.0: +check-more-types@2.24.0, check-more-types@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== @@ -291,7 +334,14 @@ core-util-is@1.0.2: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -cross-spawn@^7.0.0: +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -361,6 +411,13 @@ dayjs@^1.10.4: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== +debug@4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + debug@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -389,6 +446,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +duplexer@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -434,6 +496,19 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +event-stream@=3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + eventemitter2@6.4.7: version "6.4.7" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" @@ -454,6 +529,21 @@ execa@4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + executable@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" @@ -501,12 +591,17 @@ figures@^3.2.0: dependencies: escape-string-regexp "^1.0.5" +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== -form-data@~4.0.0: +form-data@^4.0.0, form-data@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== @@ -515,6 +610,11 @@ form-data@~4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== + fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -548,6 +648,16 @@ get-stream@^5.0.0, get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-them-args@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/get-them-args/-/get-them-args-1.3.2.tgz#74a20ba8a4abece5ae199ad03f2bcc68fdfc9ba5" + integrity sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw== + getos@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" @@ -624,6 +734,11 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -682,6 +797,17 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== +joi@^17.13.3: + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -716,7 +842,15 @@ jsprim@^2.0.2: json-schema "0.4.0" verror "1.10.0" -lazy-ass@^1.6.0: +kill-port@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/kill-port/-/kill-port-2.0.1.tgz#e5e18e2706b13d54320938be42cb7d40609b15cf" + integrity sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ== + dependencies: + get-them-args "1.3.2" + shell-exec "1.0.2" + +lazy-ass@1.6.0, lazy-ass@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== @@ -763,6 +897,11 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -795,7 +934,7 @@ ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -npm-run-path@^4.0.0: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -814,7 +953,7 @@ once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -838,6 +977,13 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== + dependencies: + through "~2.3" + pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -868,6 +1014,18 @@ proxy-from-env@1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +ps-tree@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" + integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== + dependencies: + event-stream "=3.3.4" + pump@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" @@ -903,7 +1061,7 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== -rxjs@^7.5.1: +rxjs@^7.5.1, rxjs@^7.8.1: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== @@ -949,6 +1107,11 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shell-exec@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shell-exec/-/shell-exec-1.0.2.tgz#2e9361b0fde1d73f476c4b6671fa17785f696756" + integrity sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg== + side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -959,7 +1122,7 @@ side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.2: +signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -982,6 +1145,13 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== + dependencies: + through "2" + sshpk@^1.18.0: version "1.18.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" @@ -997,6 +1167,27 @@ sshpk@^1.18.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +start-server-and-test@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-2.0.8.tgz#0423ed00a7c052c4e74ff6bb0b90878bbd1d7cd9" + integrity sha512-v2fV6NV2F7tL1ocwfI4Wpait+IKjRbT5l3ZZ+ZikXdMLmxYsS8ynGAsCQAUVXkVyGyS+UibsRnvgHkMvJIvCsw== + dependencies: + arg "^5.0.2" + bluebird "3.7.2" + check-more-types "2.24.0" + debug "4.3.7" + execa "5.1.1" + lazy-ass "1.6.0" + ps-tree "1.2.0" + wait-on "8.0.1" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== + dependencies: + duplexer "~0.1.1" + string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -1037,7 +1228,7 @@ throttleit@^1.0.0: resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.1.tgz#304ec51631c3b770c65c6c6f76938b384000f4d5" integrity sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ== -through@^2.3.8: +through@2, through@^2.3.8, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -1122,6 +1313,17 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +wait-on@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-8.0.1.tgz#13c8ec77115517f8fbc2d670521a444201f03f53" + integrity sha512-1wWQOyR2LVVtaqrcIL2+OM+x7bkpmzVROa0Nf6FryXkS+er5Sa1kzFGjzZRqLnHa3n1rACFLeTwUqE1ETL9Mig== + dependencies: + axios "^1.7.7" + joi "^17.13.3" + lodash "^4.17.21" + minimist "^1.2.8" + rxjs "^7.8.1" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" diff --git a/packages/api/src/controllers/connections.js b/packages/api/src/controllers/connections.js index 94a9fe3a7..ccddc32f5 100644 --- a/packages/api/src/controllers/connections.js +++ b/packages/api/src/controllers/connections.js @@ -510,4 +510,10 @@ module.exports = { } return null; }, + + reloadConnectionList_meta: true, + async reloadConnectionList() { + if (portalConnections) return; + await this.datastore.unload(); + }, }; diff --git a/packages/api/src/main.js b/packages/api/src/main.js index 9fb3fbe53..d262f552f 100644 --- a/packages/api/src/main.js +++ b/packages/api/src/main.js @@ -28,6 +28,7 @@ const files = require('./controllers/files'); const scheduler = require('./controllers/scheduler'); const queryHistory = require('./controllers/queryHistory'); const onFinished = require('on-finished'); +const processArgs = require('./utility/processArgs'); const { rundir } = require('./utility/directories'); const platformInfo = require('./utility/platformInfo'); @@ -77,6 +78,8 @@ function start() { app.use(getExpressPath('/'), express.static('/home/dbgate-docker/public')); } else if (platformInfo.isAwsUbuntuLayout) { app.use(getExpressPath('/'), express.static('/home/ubuntu/build/public')); + } else if (processArgs.runE2eTests) { + app.use(getExpressPath('/'), express.static(path.resolve('packer/build/public'))); } else if (platformInfo.isNpmDist) { app.use( getExpressPath('/'), diff --git a/packages/api/src/utility/JsonLinesDatabase.js b/packages/api/src/utility/JsonLinesDatabase.js index 026692c54..6a305fb80 100644 --- a/packages/api/src/utility/JsonLinesDatabase.js +++ b/packages/api/src/utility/JsonLinesDatabase.js @@ -23,6 +23,12 @@ class JsonLinesDatabase { await fs.writeFile(this.filename, this.data.map(x => JSON.stringify(x)).join('\n')); } + async unload() { + this.data = []; + this.loadedOk = false; + this.loadPerformed = false; + } + async _ensureLoaded() { if (!this.loadPerformed) { await lock.acquire('reader', async () => { diff --git a/packages/api/src/utility/directories.js b/packages/api/src/utility/directories.js index 99617c1a2..b5d4ab72a 100644 --- a/packages/api/src/utility/directories.js +++ b/packages/api/src/utility/directories.js @@ -96,6 +96,9 @@ function packagedPluginsDir() { // return path.resolve(__dirname, '../../plugins'); // } } + if (processArgs.runE2eTests) { + return path.resolve('packer/build/plugins'); + } return null; } diff --git a/packages/api/src/utility/processArgs.js b/packages/api/src/utility/processArgs.js index b00877cce..a2dd45189 100644 --- a/packages/api/src/utility/processArgs.js +++ b/packages/api/src/utility/processArgs.js @@ -14,6 +14,7 @@ const workspaceDir = getNamedArg('--workspace-dir'); const processDisplayName = getNamedArg('--process-display-name'); const listenApi = process.argv.includes('--listen-api'); const listenApiChild = process.argv.includes('--listen-api-child') || listenApi; +const runE2eTests = process.argv.includes('--run-e2e-tests'); function getPassArgs() { const res = []; @@ -23,6 +24,9 @@ function getPassArgs() { if (listenApiChild) { res.push('listen-api-child'); } + if (runE2eTests) { + res.push('--run-e2e-tests'); + } return res; } @@ -36,4 +40,5 @@ module.exports = { listenApi, listenApiChild, processDisplayName, + runE2eTests, }; diff --git a/packages/web/src/buttons/InlineButton.svelte b/packages/web/src/buttons/InlineButton.svelte index 14b79a412..147751a3a 100644 --- a/packages/web/src/buttons/InlineButton.svelte +++ b/packages/web/src/buttons/InlineButton.svelte @@ -11,7 +11,16 @@ } -
+
diff --git a/packages/web/src/settings/ConnectionDriverFields.svelte b/packages/web/src/settings/ConnectionDriverFields.svelte index f0e15f38e..40de755ee 100644 --- a/packages/web/src/settings/ConnectionDriverFields.svelte +++ b/packages/web/src/settings/ConnectionDriverFields.svelte @@ -76,6 +76,7 @@ name="engine" isNative disabled={isConnected} + data-testid="ConnectionDriverFields_connectionType" options={[ { label: '(select connection type)', value: '' }, ..._.sortBy( @@ -116,6 +117,7 @@ @@ -125,6 +127,7 @@ {#key $authTypes} + {/if} {#if driver?.showConnectionField('endpointKey', $values, showConnectionFieldArgs)} - + {/if} {#if driver?.showConnectionField('clientLibraryPath', $values, showConnectionFieldArgs)} @@ -150,6 +163,7 @@ label="Client library path" name="clientLibraryPath" disabled={isConnected || disabledFields.includes('clientLibraryPath')} + data-testid="ConnectionDriverFields_clientLibraryPath" /> {/if} @@ -161,6 +175,7 @@ name="server" disabled={isConnected || disabledFields.includes('server')} templateProps={{ noMargin: true }} + data-testid="ConnectionDriverFields_server" />
{#if driver?.showConnectionField('port', $values, showConnectionFieldArgs)} @@ -171,6 +186,7 @@ disabled={isConnected || disabledFields.includes('port')} templateProps={{ noMargin: true }} placeholder={driver?.defaultPort} + data-testid="ConnectionDriverFields_port" />
{/if} @@ -191,6 +207,7 @@ name="serviceName" disabled={isConnected} templateProps={{ noMargin: true }} + data-testid="ConnectionDriverFields_serviceName" />
@@ -205,6 +222,7 @@ { value: 'serviceName', label: 'Service name' }, { value: 'sid', label: 'SID' }, ]} + data-testid="ConnectionDriverFields_serviceNameType" />
@@ -216,6 +234,7 @@ name="socketPath" disabled={isConnected || disabledFields.includes('socketPath')} placeholder={driver?.defaultSocketPath} + data-testid="ConnectionDriverFields_scoketPath" /> {/if} @@ -228,6 +247,7 @@ name="user" disabled={isConnected || disabledFields.includes('user')} templateProps={{ noMargin: true }} + data-testid="ConnectionDriverFields_user" /> {/if} @@ -238,22 +258,34 @@ name="password" disabled={isConnected || disabledFields.includes('password')} templateProps={{ noMargin: true }} + data-testid="ConnectionDriverFields_password" /> {/if} {/if} {#if showUser && !showPassword} - + {/if} {#if !showUser && showPassword} - + {/if} {#if driver?.showConnectionField('awsRegion', $values, showConnectionFieldArgs)} { return awsRegions.map(awsRegion => ({ text: awsRegion, @@ -273,6 +305,7 @@ name="accessKeyId" disabled={isConnected || disabledFields.includes('accessKeyId')} templateProps={{ noMargin: true }} + data-testid="ConnectionDriverFields_accesKeyId" /> {/if} @@ -283,6 +316,7 @@ name="secretAccessKey" disabled={isConnected || disabledFields.includes('secretAccessKey')} templateProps={{ noMargin: true }} + data-testid="ConnectionDriverFields_secretAccessKey" /> {/if} @@ -301,31 +335,63 @@ { value: 'askPassword', label: "Don't save, ask for password" }, { value: 'askUser', label: "Don't save, ask for login and password" }, ]} + data-testid="ConnectionDriverFields_passwordMode" /> {/if} {#if driver?.showConnectionField('treeKeySeparator', $values, showConnectionFieldArgs)} - + {/if} {#if driver?.showConnectionField('windowsDomain', $values, showConnectionFieldArgs)} - + {/if} {#if driver?.showConnectionField('isReadOnly', $values, showConnectionFieldArgs)} - + {/if} {#if driver?.showConnectionField('trustServerCertificate', $values, showConnectionFieldArgs)} - + {/if} {#if driver?.showConnectionField('defaultDatabase', $values, showConnectionFieldArgs)} - + {/if} {#if defaultDatabase && driver?.showConnectionField('singleDatabase', $values, showConnectionFieldArgs)} - + {/if} {#if driver?.showConnectionField('useSeparateSchemas', $values, showConnectionFieldArgs)} @@ -333,6 +399,7 @@ label={`Use schemas separately (use this if you have many large schemas)`} name="useSeparateSchemas" disabled={isConnected} + data-testid="ConnectionDriverFields_useSeparateSchemas" /> {/if} @@ -344,7 +411,8 @@ name="displayName" templateProps={{ noMargin: true }} disabled={isConnected} - /> + data-testid="ConnectionDriverFields_displayName" + />
diff --git a/packages/web/src/tabs/ConnectionTab.svelte b/packages/web/src/tabs/ConnectionTab.svelte index 1bb954336..d4a293c19 100644 --- a/packages/web/src/tabs/ConnectionTab.svelte +++ b/packages/web/src/tabs/ConnectionTab.svelte @@ -223,20 +223,20 @@
{#if onlyTestButton} {#if isTesting} - + {:else} - + {/if} {:else if isConnected} - + {:else} - + {#if isTesting} {:else} - + {/if} - + {/if}
diff --git a/packages/web/src/widgets/ConnectionList.svelte b/packages/web/src/widgets/ConnectionList.svelte index d73169be8..72d578975 100644 --- a/packages/web/src/widgets/ConnectionList.svelte +++ b/packages/web/src/widgets/ConnectionList.svelte @@ -194,7 +194,7 @@ /> {#if $commandsCustomized['new.connection']?.enabled} - runCommand('new.connection')} title="Add new connection"> + runCommand('new.connection')} title="Add new connection" data-testid="ConnectionList_buttonNewConnection"> runCommand('new.connection.folder')} title="Add new connection folder">