diff --git a/integration/credential_database.test.js b/integration/credential_database.test.js index 5f64fdf7..cb778582 100644 --- a/integration/credential_database.test.js +++ b/integration/credential_database.test.js @@ -5,313 +5,311 @@ // database in Docker should not be put into this file. // -if (false) { - const fs = require('fs'); - const path = require('path'); - - const { CODE_ROOT } = require('../desktop/constants'); - const { getProjectResultsFile } = require('../desktop/store'); - const { ensureSigningKey } = require('../desktop/secret'); - const { - LiteralPanelInfo, - Encrypt, - DatabasePanelInfo, - DatabaseConnectorInfo, - } = require('../shared/state'); - const { withSavedPanels, RUNNERS } = require('../desktop/panel/testutil'); - - // File only runs when SKIP_CREDENTIALED=true is not set. This is - // because these tests will always fail when an outside contributor pull - // request runs. - if (process.env.RUN_CREDENTIAL_TESTS == 'true') { - for (const subprocess of RUNNERS) { - // Most databases now only work with the Go runner. - if (!subprocess?.go) { - continue; - } - - describe('basic bigquery tests', () => { - test(`runs query against public dataset`, async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'bigquery', - database: 'multiprocess-325723', - apiKey_encrypt: new Encrypt(process.env.BIGQUERY_TOKEN), - }), - ]; - const dp = new DatabasePanelInfo(); - dp.database.connectorId = connectors[0].id; - dp.content = - 'SELECT * FROM `bigquery-public-data`.census_bureau_usa.population_by_zip_2010 ORDER BY population DESC LIMIT 10'; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id - ); - - const v = JSON.parse(panelValueBuffer.toString()); - expect(v).toStrictEqual( - JSON.parse( - fs - .readFileSync('testdata/bigquery/population_result.json') - .toString() - ) - ); - - finished = true; - }, - { evalPanels: true, connectors, subprocessName: subprocess } - ); - - if (!finished) { - throw new Error('Callback did not finish'); - } - }, 15_000); - }); - - describe('basic athena tests', () => { - test(`runs query against s3://datastation-tests/basic/`, async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'athena', - database: 'testdata', - extra: { - aws_region: 'us-east-1', - }, - address: 's3://datastation-test-results/', - username: process.env.AWS_ACCESS_KEY_ID, - password_encrypt: new Encrypt(process.env.AWS_SECRET_ACCESS_KEY), - }), - ]; - const dp = new DatabasePanelInfo(); - dp.database.connectorId = connectors[0].id; - dp.content = 'SELECT * FROM basic_users ORDER BY age desc'; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id - ); - - const v = JSON.parse(panelValueBuffer.toString()); - expect(v).toStrictEqual([ - { age: 52, name: 'Emma' }, - { age: 50, name: 'Karl' }, - { age: 43, name: 'Garry' }, - { age: 41, name: 'Nile' }, - { age: 39, name: 'Mina' }, - ]); - - finished = true; - }, - { evalPanels: true, connectors, subprocessName: subprocess } - ); - - if (!finished) { - throw new Error('Callback did not finish'); - } - }, 15_000); - }); - - describe('basic google sheets tests', () => { - test(`returns all results`, async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'google-sheets', - apiKey_encrypt: new Encrypt(process.env.BIGQUERY_TOKEN), - }), - ]; - const dp = new DatabasePanelInfo(null, { - table: '1osiz0yumwHxfovIAIYTpf5ozDapQzIHv_2jk4P2AvZg', - }); - dp.database.connectorId = connectors[0].id; - dp.content = ''; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id - ); - - const v = JSON.parse(panelValueBuffer.toString()); - expect(v).toStrictEqual([ - { age: '43', name: 'Garry' }, - { age: '39', name: 'Mina' }, - { age: '50', name: 'Karl' }, - { age: '41', name: 'Nile' }, - { age: '52', name: 'Emma' }, - ]); - - finished = true; - }, - { evalPanels: true, connectors, subprocessName: subprocess } - ); - - if (!finished) { - throw new Error('Callback did not finish'); - } - }, 15_000); - }); - - describe('basic airtable tests', () => { - const terrenceSample = { - ' Name ': 'Dr. Terrence Metz', - 'Phone Number ': '1-233-954-4550', - Email: 'Dell_Herman17@yahoo.com', - Street: '5635 Kuvalis Shores', - ' City ': 'Haagton', - State: 'New Mexico', - 'Zip Code ': '18960', - 'Routing Number ': 616515073, - Department: 'Automotive', - 'Company ': 'Smitham Inc', - 'Created At ': '2021-06-25T01:06:47.125Z', - 'Profile Photo': 'http://placeimg.com/640/480', - ' Description': - 'Omnis ut ut voluptatem provident eaque necessitatibus quia. Et molestiae molestiae magni repudiandae aut sed. Deleniti maiores voluptas placeat cumque occaecati odit.', - Activated: true, - }; - - test(`returns all results`, async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'airtable', - database: '', - apiKey_encrypt: new Encrypt(process.env.AIRTABLE_TOKEN), - }), - ]; - const dp = new DatabasePanelInfo(null, { - table: 'tblaafwMIxhqwdHkj', +const fs = require('fs'); +const path = require('path'); + +const { CODE_ROOT } = require('../desktop/constants'); +const { getProjectResultsFile } = require('../desktop/store'); +const { ensureSigningKey } = require('../desktop/secret'); +const { + LiteralPanelInfo, + Encrypt, + DatabasePanelInfo, + DatabaseConnectorInfo, +} = require('../shared/state'); +const { withSavedPanels, RUNNERS } = require('../desktop/panel/testutil'); + +// File only runs when SKIP_CREDENTIALED=true is not set. This is +// because these tests will always fail when an outside contributor pull +// request runs. +if (process.env.RUN_CREDENTIAL_TESTS == 'true') { + for (const subprocess of RUNNERS) { + // Most databases now only work with the Go runner. + if (!subprocess?.go) { + continue; + } + + describe('basic bigquery tests', () => { + test(`runs query against public dataset`, async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'bigquery', + database: 'multiprocess-325723', + apiKey_encrypt: new Encrypt(process.env.BIGQUERY_TOKEN), + }), + ]; + const dp = new DatabasePanelInfo(); + dp.database.connectorId = connectors[0].id; + dp.content = + 'SELECT * FROM `bigquery-public-data`.census_bureau_usa.population_by_zip_2010 ORDER BY population DESC LIMIT 10'; + + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = JSON.parse(panelValueBuffer.toString()); + expect(v).toStrictEqual( + JSON.parse( + fs + .readFileSync('testdata/bigquery/population_result.json') + .toString() + ) + ); + + finished = true; + }, + { evalPanels: true, connectors, subprocessName: subprocess } + ); + + if (!finished) { + throw new Error('Callback did not finish'); + } + }, 15_000); + }); + + describe('basic athena tests', () => { + test(`runs query against s3://datastation-tests/basic/`, async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'athena', + database: 'testdata', extra: { - airtable_view: 'viwk6vMHsOT3NRn63', - airtable_app: 'app9SNPHq4m8BGwgD', + aws_region: 'us-east-1', }, - }); - dp.database.connectorId = connectors[0].id; - dp.content = ''; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id - ); - - const v = JSON.parse(panelValueBuffer.toString()); - expect(v.length).toBe(1_000); - expect( - v.find((row) => row[' Name '] === 'Dr. Terrence Metz') - ).toStrictEqual(terrenceSample); - - finished = true; - }, - { evalPanels: true, connectors, subprocessName: subprocess } - ); - - if (!finished) { - throw new Error('Callback did not finish'); - } - }, 15_000); - - test(`returns filtered results`, async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'airtable', - database: '', - apiKey_encrypt: new Encrypt(process.env.AIRTABLE_TOKEN), - }), - ]; - const dp = new DatabasePanelInfo(null, { - table: 'tblaafwMIxhqwdHkj', + address: 's3://datastation-test-results/', + username: process.env.AWS_ACCESS_KEY_ID, + password_encrypt: new Encrypt(process.env.AWS_SECRET_ACCESS_KEY), + }), + ]; + const dp = new DatabasePanelInfo(); + dp.database.connectorId = connectors[0].id; + dp.content = 'SELECT * FROM basic_users ORDER BY age desc'; + + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = JSON.parse(panelValueBuffer.toString()); + expect(v).toStrictEqual([ + { age: 52, name: 'Emma' }, + { age: 50, name: 'Karl' }, + { age: 43, name: 'Garry' }, + { age: 41, name: 'Nile' }, + { age: 39, name: 'Mina' }, + ]); + + finished = true; + }, + { evalPanels: true, connectors, subprocessName: subprocess } + ); + + if (!finished) { + throw new Error('Callback did not finish'); + } + }, 15_000); + }); + + describe('basic google sheets tests', () => { + test(`returns all results`, async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'google-sheets', + apiKey_encrypt: new Encrypt(process.env.BIGQUERY_TOKEN), + }), + ]; + const dp = new DatabasePanelInfo(null, { + table: '1osiz0yumwHxfovIAIYTpf5ozDapQzIHv_2jk4P2AvZg', + }); + dp.database.connectorId = connectors[0].id; + dp.content = ''; + + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = JSON.parse(panelValueBuffer.toString()); + expect(v).toStrictEqual([ + { age: '43', name: 'Garry' }, + { age: '39', name: 'Mina' }, + { age: '50', name: 'Karl' }, + { age: '41', name: 'Nile' }, + { age: '52', name: 'Emma' }, + ]); + + finished = true; + }, + { evalPanels: true, connectors, subprocessName: subprocess } + ); + + if (!finished) { + throw new Error('Callback did not finish'); + } + }, 15_000); + }); + + describe('basic airtable tests', () => { + const terrenceSample = { + ' Name ': 'Dr. Terrence Metz', + 'Phone Number ': '1-233-954-4550', + Email: 'Dell_Herman17@yahoo.com', + Street: '5635 Kuvalis Shores', + ' City ': 'Haagton', + State: 'New Mexico', + 'Zip Code ': '18960', + 'Routing Number ': 616515073, + Department: 'Automotive', + 'Company ': 'Smitham Inc', + 'Created At ': '2021-06-25T01:06:47.125Z', + 'Profile Photo': 'http://placeimg.com/640/480', + ' Description': + 'Omnis ut ut voluptatem provident eaque necessitatibus quia. Et molestiae molestiae magni repudiandae aut sed. Deleniti maiores voluptas placeat cumque occaecati odit.', + Activated: true, + }; + + test(`returns all results`, async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'airtable', + database: '', + apiKey_encrypt: new Encrypt(process.env.AIRTABLE_TOKEN), + }), + ]; + const dp = new DatabasePanelInfo(null, { + table: 'tblaafwMIxhqwdHkj', + extra: { + airtable_view: 'viwk6vMHsOT3NRn63', + airtable_app: 'app9SNPHq4m8BGwgD', + }, + }); + dp.database.connectorId = connectors[0].id; + dp.content = ''; + + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = JSON.parse(panelValueBuffer.toString()); + expect(v.length).toBe(1_000); + expect( + v.find((row) => row[' Name '] === 'Dr. Terrence Metz') + ).toStrictEqual(terrenceSample); + + finished = true; + }, + { evalPanels: true, connectors, subprocessName: subprocess } + ); + + if (!finished) { + throw new Error('Callback did not finish'); + } + }, 15_000); + + test(`returns filtered results`, async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'airtable', + database: '', + apiKey_encrypt: new Encrypt(process.env.AIRTABLE_TOKEN), + }), + ]; + const dp = new DatabasePanelInfo(null, { + table: 'tblaafwMIxhqwdHkj', + extra: { + airtable_view: 'viwk6vMHsOT3NRn63', + airtable_app: 'app9SNPHq4m8BGwgD', + }, + }); + dp.database.connectorId = connectors[0].id; + dp.content = '{ Name } = "Dr. Terrence Metz"'; + + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = JSON.parse(panelValueBuffer.toString()); + expect(v.length).toBe(1); + const sample = v.find( + (row) => row[' Name '] === 'Dr. Terrence Metz' + ); + expect(sample).toStrictEqual(terrenceSample); + + finished = true; + }, + { evalPanels: true, connectors, subprocessName: subprocess } + ); + + if (!finished) { + throw new Error('Callback did not finish'); + } + }, 15_000); + }); + + describe('basic snowflake tests', () => { + test('basic test', async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'snowflake', + database: '', + username: process.env.SNOWFLAKE_USER, + password_encrypt: new Encrypt(process.env.SNOWFLAKE_PASSWORD), extra: { - airtable_view: 'viwk6vMHsOT3NRn63', - airtable_app: 'app9SNPHq4m8BGwgD', - }, - }); - dp.database.connectorId = connectors[0].id; - dp.content = '{ Name } = "Dr. Terrence Metz"'; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id - ); - - const v = JSON.parse(panelValueBuffer.toString()); - expect(v.length).toBe(1); - const sample = v.find( - (row) => row[' Name '] === 'Dr. Terrence Metz' - ); - expect(sample).toStrictEqual(terrenceSample); - - finished = true; + account: process.env.SNOWFLAKE_ACCOUNT, }, - { evalPanels: true, connectors, subprocessName: subprocess } - ); - - if (!finished) { - throw new Error('Callback did not finish'); - } - }, 15_000); - }); - - describe('basic snowflake tests', () => { - test('basic test', async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'snowflake', - database: '', - username: process.env.SNOWFLAKE_USER, - password_encrypt: new Encrypt(process.env.SNOWFLAKE_PASSWORD), - extra: { - account: process.env.SNOWFLAKE_ACCOUNT, - }, - }), - ]; - const dp = new DatabasePanelInfo(); - dp.database.connectorId = connectors[0].id; - dp.content = - 'select count(*) from "SNOWFLAKE_SAMPLE_DATA".tpch_sf1.lineitem;'; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id - ); - - const v = JSON.parse(panelValueBuffer.toString()); - expect(v).toStrictEqual([{ 'COUNT(*)': '6001215' }]); - - finished = true; - }, - { evalPanels: true, connectors, subprocessName: subprocess } - ); - - if (!finished) { - throw new Error('Callback did not finish'); - } - }, 360_000); - }); - } - } else { - test('stub', () => {}); + }), + ]; + const dp = new DatabasePanelInfo(); + dp.database.connectorId = connectors[0].id; + dp.content = + 'select count(*) from "SNOWFLAKE_SAMPLE_DATA".tpch_sf1.lineitem;'; + + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = JSON.parse(panelValueBuffer.toString()); + expect(v).toStrictEqual([{ 'COUNT(*)': '6001215' }]); + + finished = true; + }, + { evalPanels: true, connectors, subprocessName: subprocess } + ); + + if (!finished) { + throw new Error('Callback did not finish'); + } + }, 360_000); + }); } +} else { + test('stub', () => {}); } diff --git a/integration/mongo.test.js b/integration/mongo.test.js index ceba4897..117a28ec 100644 --- a/integration/mongo.test.js +++ b/integration/mongo.test.js @@ -1,169 +1,141 @@ -const cp = require('child_process'); -const fs = require('fs'); - -const { getProjectResultsFile } = require('../desktop/store'); -const { - DatabasePanelInfo, - Encrypt, - DatabaseConnectorInfo, -} = require('../shared/state'); -const { withSavedPanels, RUNNERS } = require('../desktop/panel/testutil'); -const { withDocker, DEFAULT_TIMEOUT } = require('./docker'); - -function testWithDocker(name, cb) { - test( - name, - async () => { - if (process.platform !== 'linux') { - return; - } - - return withDocker( - { - port: 27017, - image: 'docker.io/library/mongo:5', - env: { - MONGO_INITDB_ROOT_USERNAME: 'test', - MONGO_INITDB_DATABASE: 'test', - MONGO_INITDB_ROOT_PASSWORD: 'test', - }, - wait: () => { - try { - cp.execSync('mongosh'); - } catch (e) { - console.error(e); - throw new Error( - `It doesn't seem like mongosh is installed on your machine (or on your $PATH). Download it from here: https://www.mongodb.com/try/download/shell. Or skip this test.` +if (false) { + const cp = require('child_process'); + const fs = require('fs'); + + const { getProjectResultsFile } = require('../desktop/store'); + const { + DatabasePanelInfo, + Encrypt, + DatabaseConnectorInfo, + } = require('../shared/state'); + const { withSavedPanels, RUNNERS } = require('../desktop/panel/testutil'); + const { withDocker, DEFAULT_TIMEOUT } = require('./docker'); + + function testWithDocker(name, cb) { + test( + name, + async () => { + if (process.platform !== 'linux') { + return; + } + + return withDocker( + { + port: 27017, + image: 'docker.io/library/mongo:5', + env: { + MONGO_INITDB_ROOT_USERNAME: 'test', + MONGO_INITDB_DATABASE: 'test', + MONGO_INITDB_ROOT_PASSWORD: 'test', + }, + wait: () => { + try { + cp.execSync('mongosh'); + } catch (e) { + console.error(e); + throw new Error( + `It doesn't seem like mongosh is installed on your machine (or on your $PATH). Download it from here: https://www.mongodb.com/try/download/shell. Or skip this test.` + ); + } + const cmds = Array.from(new Array(4)).map( + (_e, i) => + `mongosh "mongodb://test:test@localhost:27017" --eval "db.test.insertOne($(cat ${ + __dirname + '/../testdata/documents/' + (i + 1) + '.json' + }))"` ); - } - const cmds = Array.from(new Array(4)).map( - (_e, i) => - `mongosh "mongodb://test:test@localhost:27017" --eval "db.test.insertOne($(cat ${ - __dirname + '/../testdata/documents/' + (i + 1) + '.json' - }))"` - ); - let first = true; - for (const cmd of cmds) { - if (first) { - while (true) { - try { - cp.execSync(cmd, { stdio: 'inherit' }); - break; - } catch (e) { - /* pass */ + let first = true; + for (const cmd of cmds) { + if (first) { + while (true) { + try { + cp.execSync(cmd, { stdio: 'inherit' }); + break; + } catch (e) { + /* pass */ + } } + + first = false; + continue; } - first = false; - continue; + cp.execSync(cmd, { stdio: 'inherit' }); } - - cp.execSync(cmd, { stdio: 'inherit' }); - } + }, }, - }, - cb - ); - }, - DEFAULT_TIMEOUT - ); -} - -describe('basic mongodb testdata/documents tests', () => { - testWithDocker('basic test', async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'mongo', - database: 'test', - username: 'test', - password_encrypt: new Encrypt('test'), - extra: { authenticationDatabase: 'admin' }, - }), - ]; - - const dp = new DatabasePanelInfo(); - dp.database.connectorId = connectors[0].id; - dp.content = 'db.test.find({ pageCount: { $gt: 0 } }).toArray()'; - - let finished = false; - const panels = [dp]; - await withSavedPanels( - panels, - async (project) => { - const panelValueBuffer = fs.readFileSync( - getProjectResultsFile(project.projectName) + dp.id + cb ); + }, + DEFAULT_TIMEOUT + ); + } - const v = Array.from(JSON.parse(panelValueBuffer.toString())).map( - (el) => { - delete el._id; - return el; - } - ); + describe('basic mongodb testdata/documents tests', () => { + testWithDocker('basic test', async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'mongo', + database: 'test', + username: 'test', + password_encrypt: new Encrypt('test'), + extra: { authenticationDatabase: 'admin' }, + }), + ]; - expect(v).toStrictEqual( - JSON.parse( - fs.readFileSync('testdata/mongo/documents.json').toString() - ) - ); + const dp = new DatabasePanelInfo(); + dp.database.connectorId = connectors[0].id; + dp.content = 'db.test.find({ pageCount: { $gt: 0 } }).toArray()'; - finished = true; - }, - { - evalPanels: true, - connectors, - subprocessName: RUNNERS.find((r) => r?.go), - } - ); + let finished = false; + const panels = [dp]; + await withSavedPanels( + panels, + async (project) => { + const panelValueBuffer = fs.readFileSync( + getProjectResultsFile(project.projectName) + dp.id + ); + + const v = Array.from(JSON.parse(panelValueBuffer.toString())).map( + (el) => { + delete el._id; + return el; + } + ); - if (!finished) { - throw new Error('Callback did not finish'); - } - }); + expect(v).toStrictEqual( + JSON.parse( + fs.readFileSync('testdata/mongo/documents.json').toString() + ) + ); - testWithDocker('errors with invalid authenticationDatabase', async () => { - const connectors = [ - new DatabaseConnectorInfo({ - type: 'mongo', - database: 'test', - username: 'test', - password_encrypt: new Encrypt('test'), - extra: { authenticationDatabase: 'invalid' }, - }), - ]; - - const dp = new DatabasePanelInfo(); - dp.database.connectorId = connectors[0].id; - dp.content = 'db.test.find({})'; - - const panels = [dp]; - try { - await withSavedPanels(panels, () => {}, { - evalPanels: true, - connectors, - subprocessName: RUNNERS.find((r) => r?.go), - }); - } catch (e) { - expect(e.name).toBe('UserError'); - expect(e.message).toBe('MongoServerError: Authentication failed.\n'); - } - }); + finished = true; + }, + { + evalPanels: true, + connectors, + subprocessName: RUNNERS.find((r) => r?.go), + } + ); - testWithDocker( - 'errors when not using .toArray() on queries returning multiple objects', - async () => { + if (!finished) { + throw new Error('Callback did not finish'); + } + }); + + testWithDocker('errors with invalid authenticationDatabase', async () => { const connectors = [ new DatabaseConnectorInfo({ type: 'mongo', database: 'test', username: 'test', password_encrypt: new Encrypt('test'), + extra: { authenticationDatabase: 'invalid' }, }), ]; const dp = new DatabasePanelInfo(); dp.database.connectorId = connectors[0].id; - dp.content = 'db.test.find({ pageCount: { $gt: 0 } })'; + dp.content = 'db.test.find({})'; const panels = [dp]; try { @@ -174,12 +146,42 @@ describe('basic mongodb testdata/documents tests', () => { }); } catch (e) { expect(e.name).toBe('UserError'); - expect( - e.message.startsWith( - 'BSONTypeError: Converting circular structure to EJSON:' - ) - ).toBe(true); + expect(e.message).toBe('MongoServerError: Authentication failed.\n'); + } + }); + + testWithDocker( + 'errors when not using .toArray() on queries returning multiple objects', + async () => { + const connectors = [ + new DatabaseConnectorInfo({ + type: 'mongo', + database: 'test', + username: 'test', + password_encrypt: new Encrypt('test'), + }), + ]; + + const dp = new DatabasePanelInfo(); + dp.database.connectorId = connectors[0].id; + dp.content = 'db.test.find({ pageCount: { $gt: 0 } })'; + + const panels = [dp]; + try { + await withSavedPanels(panels, () => {}, { + evalPanels: true, + connectors, + subprocessName: RUNNERS.find((r) => r?.go), + }); + } catch (e) { + expect(e.name).toBe('UserError'); + expect( + e.message.startsWith( + 'BSONTypeError: Converting circular structure to EJSON:' + ) + ).toBe(true); + } } - } - ); -}); + ); + }); +} diff --git a/integration/oracle.test.js b/integration/oracle.test.js index 55cf7361..28c5254b 100644 --- a/integration/oracle.test.js +++ b/integration/oracle.test.js @@ -1,31 +1,54 @@ -const { basicDatabaseTest } = require('../desktop/panel/testutil'); -const { withDocker, DEFAULT_TIMEOUT } = require('./docker'); +if (false) { + const { basicDatabaseTest } = require('../desktop/panel/testutil'); + const { withDocker, DEFAULT_TIMEOUT } = require('./docker'); -const BASIC_TESTS = [ - { - type: 'oracle', - query: - // Oracle does not have true/false literals - // Oracle doesn't support no-FROM. But the dual table is a dummy table. - `SELECT 1 AS "1", 2.2 AS "2", 1 AS "true", 'string' AS "string", TO_DATE('2021-01-01','YYYY-MM-DD') AS "date" FROM dual`, - }, -]; + const BASIC_TESTS = [ + { + type: 'oracle', + query: + // Oracle does not have true/false literals + // Oracle doesn't support no-FROM. But the dual table is a dummy table. + `SELECT 1 AS "1", 2.2 AS "2", 1 AS "true", 'string' AS "string", TO_DATE('2021-01-01','YYYY-MM-DD') AS "date" FROM dual`, + }, + ]; + + const vendorOverride = { + oracle: { + database: 'XEPDB1', + }, + }; -const vendorOverride = { - oracle: { - database: 'XEPDB1', - }, -}; + describe('basic oracle tests', () => { + for (const t of BASIC_TESTS) { + test( + t.query, + async () => { + await withDocker( + { + image: 'docker.io/gvenzl/oracle-xe:21-slim', + port: '1521', + env: { + ORACLE_RANDOM_PASSWORD: 'y', + APP_USER: 'test', + APP_USER_PASSWORD: 'test', + }, + // TODO: find a better way to wait for oracle to come up + wait: () => new Promise((r) => setTimeout(r, 60_000)), + }, + () => basicDatabaseTest(t, vendorOverride) + ); + }, + DEFAULT_TIMEOUT + ); + } -describe('basic oracle tests', () => { - for (const t of BASIC_TESTS) { test( - t.query, + 'alternative port regression test', async () => { await withDocker( { image: 'docker.io/gvenzl/oracle-xe:21-slim', - port: '1521', + port: '1520:1521', env: { ORACLE_RANDOM_PASSWORD: 'y', APP_USER: 'test', @@ -34,38 +57,17 @@ describe('basic oracle tests', () => { // TODO: find a better way to wait for oracle to come up wait: () => new Promise((r) => setTimeout(r, 60_000)), }, - () => basicDatabaseTest(t, vendorOverride) + () => + basicDatabaseTest(BASIC_TESTS[0], { + ...vendorOverride, + oracle: { + ...vendorOverride.oracle, + address: 'localhost:1520', + }, + }) ); }, - DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * 10 ); - } - - test( - 'alternative port regression test', - async () => { - await withDocker( - { - image: 'docker.io/gvenzl/oracle-xe:21-slim', - port: '1520:1521', - env: { - ORACLE_RANDOM_PASSWORD: 'y', - APP_USER: 'test', - APP_USER_PASSWORD: 'test', - }, - // TODO: find a better way to wait for oracle to come up - wait: () => new Promise((r) => setTimeout(r, 60_000)), - }, - () => - basicDatabaseTest(BASIC_TESTS[0], { - ...vendorOverride, - oracle: { - ...vendorOverride.oracle, - address: 'localhost:1520', - }, - }) - ); - }, - DEFAULT_TIMEOUT * 10 - ); -}); + }); +} diff --git a/integration/sqlserver.test.js b/integration/sqlserver.test.js index b431ff0b..d12645e2 100644 --- a/integration/sqlserver.test.js +++ b/integration/sqlserver.test.js @@ -1,13 +1,14 @@ -const { basicDatabaseTest } = require('../desktop/panel/testutil'); -const { withDocker } = require('./docker'); +if (false) { + const { basicDatabaseTest } = require('../desktop/panel/testutil'); + const { withDocker } = require('./docker'); -const BASIC_TESTS = [ - { - type: 'sqlserver', - // SQL Server doesn't have true/false literals - query: `SELECT 1 AS "1", 2.2 AS "2", 1 AS "true", 'string' AS "string", CAST('2021-01-01' AS DATE) AS "date"`, - }, - /* + const BASIC_TESTS = [ + { + type: 'sqlserver', + // SQL Server doesn't have true/false literals + query: `SELECT 1 AS "1", 2.2 AS "2", 1 AS "true", 'string' AS "string", CAST('2021-01-01' AS DATE) AS "date"`, + }, + /* NOTES ON RUNNING ODBC TESTS LOCALLY: * Install the odbc driver for SQL Server here: https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server?view=sql-server-ver16 * Run: ./runner/plugin/odbc/build.sh -race @@ -16,57 +17,58 @@ const BASIC_TESTS = [ Easy peasy. */ - { - type: 'odbc', - // SQL Server doesn't have true/false literals - query: `SELECT 1 AS "1", 2.2 AS "2", 1 AS "true", 'string' AS "string", CAST('2021-01-01' AS DATE) AS "date"`, - }, - { - type: 'odbc', - query: `INSERT INTO test (id, name) VALUES (1, 'name')`, - }, -]; + { + type: 'odbc', + // SQL Server doesn't have true/false literals + query: `SELECT 1 AS "1", 2.2 AS "2", 1 AS "true", 'string' AS "string", CAST('2021-01-01' AS DATE) AS "date"`, + }, + { + type: 'odbc', + query: `INSERT INTO test (id, name) VALUES (1, 'name')`, + }, + ]; -const vendorOverride = { - sqlserver: { - address: 'localhost', - username: 'sa', - password: '1StrongPwd!!', - database: 'master', - }, - odbc: { - address: 'localhost', - username: 'sa', - password: '1StrongPwd!!', - database: 'master', - extra: { - driver: 'ODBC Driver 18 for SQL Server', - params: 'TrustServerCertificate=yes;', + const vendorOverride = { + sqlserver: { + address: 'localhost', + username: 'sa', + password: '1StrongPwd!!', + database: 'master', }, - }, -}; + odbc: { + address: 'localhost', + username: 'sa', + password: '1StrongPwd!!', + database: 'master', + extra: { + driver: 'ODBC Driver 18 for SQL Server', + params: 'TrustServerCertificate=yes;', + }, + }, + }; -describe('basic sqlserver tests', () => { - for (const t of BASIC_TESTS) { - test( - t.type + ':' + t.query, - async () => { - await withDocker( - { - image: 'mcr.microsoft.com/mssql/server:2019-latest', - port: '1433', - env: { - ACCEPT_EULA: 'Y', - MSSQL_SA_PASSWORD: '1StrongPwd!!', + describe('basic sqlserver tests', () => { + for (const t of BASIC_TESTS) { + test( + t.type + ':' + t.query, + async () => { + await withDocker( + { + image: 'mcr.microsoft.com/mssql/server:2019-latest', + port: '1433', + env: { + ACCEPT_EULA: 'Y', + MSSQL_SA_PASSWORD: '1StrongPwd!!', + }, + cmds: [ + `/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "1StrongPwd!!" -Q "CREATE TABLE master.[dbo].test (id int PRIMARY KEY, name text);"`, + ], }, - cmds: [ - `/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "1StrongPwd!!" -Q "CREATE TABLE master.[dbo].test (id int PRIMARY KEY, name text);"`, - ], - }, - () => basicDatabaseTest(t, vendorOverride) - ); - }, - 360_000 - ); - } -}); + () => basicDatabaseTest(t, vendorOverride) + ); + }, + 360_000 + ); + } + }); +} diff --git a/ui/connectors/index.ts b/ui/connectors/index.ts index 4c1e2263..3127aba4 100644 --- a/ui/connectors/index.ts +++ b/ui/connectors/index.ts @@ -54,16 +54,17 @@ export const VENDORS: { id: 'mysql', details: GenericDetails, }, - sqlserver: { - name: 'SQL Server', - id: 'sqlserver', - details: GenericDetails, - }, - oracle: { - name: 'Oracle', - id: 'oracle', - details: GenericDetails, - }, + // TODO: Tests not working at the moment. + /* sqlserver: { + * name: 'SQL Server', + * id: 'sqlserver', + * details: GenericDetails, + * }, + * oracle: { + * name: 'Oracle', + * id: 'oracle', + * details: GenericDetails, + * }, */ sqlite: { name: 'SQLite', id: 'sqlite', @@ -124,11 +125,12 @@ export const VENDORS: { id: 'scylla', details: CassandraDetails, }, - mongo: { - name: 'MongoDB (Beta)', - id: 'mongo', - details: GenericDetails, - }, + // TODO: tests not working at the moment. + /* mongo: { + * name: 'MongoDB (Beta)', + * id: 'mongo', + * details: GenericDetails, + * }, */ athena: { name: 'AWS Athena', id: 'athena',