diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..5d68683d7 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,38 @@ +name: tests + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + run-tests: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [12.x, 14.x, 16.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + + - name: Install dependencies + run: npm install + + - name: Run docker compose + run: docker-compose up -d + + - name: Setup test db + run: node setup-test-db.js + + - name: Run tests + run: npm test + + - name: Run typing tests + run: npm run test-typings diff --git a/README.md b/README.md index 397bf677b..8169f64ba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/Vincit/objection.js.svg?branch=master)](https://travis-ci.org/Vincit/objection.js) [![Coverage Status](https://coveralls.io/repos/github/Vincit/objection.js/badge.svg?branch=master&service=github)](https://coveralls.io/github/Vincit/objection.js?branch=master) [![Join the chat at https://gitter.im/Vincit/objection.js](https://badges.gitter.im/Vincit/objection.js.svg)](https://gitter.im/Vincit/objection.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Tests](https://github.com/Vincit/objection.js/actions/workflows/test.yml/badge.svg)](https://github.com/Vincit/objection.js)[![Join the chat at https://gitter.im/Vincit/objection.js](https://badges.gitter.im/Vincit/objection.js.svg)](https://gitter.im/Vincit/objection.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # [Objection.js](https://vincit.github.io/objection.js) diff --git a/package.json b/package.json index 8e9f7886e..4c8e46f85 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,7 @@ "license": "MIT", "scripts": { "test": "npm run eslint && mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --exclude \"tests/unit/relations/files/**\"", - "test-travis": "nyc mocha --slow 100 --timeout 60000 --reporter spec --recursive tests --exclude \"tests/unit/relations/files/**\" && npm run test-typings", "test-fast": "mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --bail --exclude \"tests/unit/relations/files/**\"", - "test-opt": "mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --bail --trace_opt --trace_deopt --exclude \"tests/unit/relations/files/**\"", - "test-debug": "mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --inspect-brk --exclude \"tests/unit/relations/files/**\"", - "test-sqlite": "cross-env DATABASES=sqlite3 mocha --slow 10 --timeout 15000 --reporter spec --recursive tests --exclude \"tests/unit/relations/files/**\"", "test-typings": "tsc", "coveralls": "cat ./testCoverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", "perf": "mocha --slow 60000 --timeout 60000 --reporter spec --recursive perf", @@ -85,7 +81,7 @@ "pg": "^8.6.0", "prettier": "2.3.2", "sqlite3": "^5.0.2", - "typescript": "^4.3.5", + "typescript": "^4.4.4", "vuepress": "1.8.2" }, "nyc": { diff --git a/setup-test-db.js b/setup-test-db.js index eae77977a..9ce34a72d 100755 --- a/setup-test-db.js +++ b/setup-test-db.js @@ -1,56 +1,71 @@ const knex = require('knex'); // DATABASES environment variable can contain a comma separated list -// of databases to setup. -const DATABASES = (process.env.DATABASES && process.env.DATABASES.split(',')) || []; - -const knexes = []; -const commands = []; - -if (DATABASES.length === 0 || DATABASES.includes('postgres')) { - const postgres = knex({ - client: 'postgres', - - connection: { - user: 'postgres', - host: 'localhost', - database: 'postgres', - }, - }); - - knexes.push(postgres); - commands.push( - postgres.raw('DROP DATABASE IF EXISTS objection_test'), - postgres.raw('DROP USER IF EXISTS objection'), - postgres.raw('CREATE USER objection SUPERUSER'), - postgres.raw('CREATE DATABASE objection_test') - ); +// of databases to setup. Defaults to all databases. +const DATABASES = (process.env.DATABASES && process.env.DATABASES.split(',')) || [ + 'postgres', + 'mysql', +]; + +async function setup() { + if (DATABASES.includes('postgres')) { + const postgres = await createKnex({ + client: 'postgres', + + connection: { + user: 'postgres', + host: 'localhost', + database: 'postgres', + }, + }); + + await postgres.raw('DROP DATABASE IF EXISTS objection_test'); + await postgres.raw('DROP USER IF EXISTS objection'); + await postgres.raw('CREATE USER objection SUPERUSER'); + await postgres.raw('CREATE DATABASE objection_test'); + + await postgres.destroy(); + } + + if (DATABASES.includes('mysql')) { + const mysql = await createKnex({ + client: 'mysql', + + connection: { + user: 'root', + host: 'localhost', + }, + }); + + await mysql.raw('DROP DATABASE IF EXISTS objection_test'); + await mysql.raw('DROP USER IF EXISTS objection'); + await mysql.raw('CREATE USER objection'); + await mysql.raw('GRANT ALL PRIVILEGES ON *.* TO objection'); + await mysql.raw('CREATE DATABASE objection_test'); + + await mysql.destroy(); + } } -if (DATABASES.length === 0 || DATABASES.includes('mysql')) { - const mysql = knex({ - client: 'mysql', - - connection: { - user: 'root', - host: 'localhost', - }, - }); - - knexes.push(mysql); - commands.push( - mysql.raw('DROP DATABASE IF EXISTS objection_test'), - mysql.raw('DROP USER IF EXISTS objection'), - mysql.raw('CREATE USER objection'), - mysql.raw('GRANT ALL PRIVILEGES ON *.* TO objection'), - mysql.raw('CREATE DATABASE objection_test') - ); +async function createKnex(config) { + const startTime = new Date(); + + while (true) { + try { + const knexInstance = knex(config); + await knexInstance.raw('SELECT 1'); + return knexInstance; + } catch (err) { + const now = new Date(); + + if (now.getTime() - startTime.getTime() > 60000) { + process.exit(1); + } else { + console.log(`failed to connect to ${config.client}. Trying again soon`); + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + } + } } -commands - .reduce((promise, query) => { - return promise.then(() => query); - }, Promise.resolve()) - .then(() => { - return Promise.all(knexes.map((it) => it.destroy())); - }); +setup(); diff --git a/tests/ts/validation.ts b/tests/ts/validation.ts index c3b88e508..9b60460c8 100644 --- a/tests/ts/validation.ts +++ b/tests/ts/validation.ts @@ -38,25 +38,6 @@ import { Person } from './fixtures/person'; await Person.query().insert({ firstName: 'jennifer' }); } catch (err) { console.log(err instanceof ValidationError); // --> true - console.log(err.data); // --> {lastName: [{message: 'required property missing', ...}]} - } - - try { - await Person.query().insert({ firstName: 'jennifer' }); - } catch (err) { - let lastNameErrors = err.data.lastName; - - for (let i = 0; i < lastNameErrors.length; ++i) { - let lastNameError = lastNameErrors[i]; - - if (lastNameError.keyword === 'required') { - console.log('This field is required!'); - } else if (lastNameError.keyword === 'minLength') { - console.log('Must be longer than ' + lastNameError.params.limit); - } else { - console.log(lastNameError.message); // Fallback to default error message - } - } } // gh-1582