diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index c1963cf84d..c06cf8232c 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -21,6 +21,7 @@ jobs: - mysql - postgres - maria + - postgres10 # - sqlite3 node-version: # - 12-alpine diff --git a/api/package.json b/api/package.json index 805ab92ca5..2fe389a35e 100644 --- a/api/package.json +++ b/api/package.json @@ -209,6 +209,7 @@ "copyfiles": "2.4.1", "cross-env": "7.0.3", "jest": "27.3.1", + "knex-mock-client": "^1.6.1", "ts-jest": "27.0.7", "ts-node-dev": "1.1.8", "typescript": "4.5.2" diff --git a/api/src/tests/database/migrations/run.test.ts b/api/src/tests/database/migrations/run.test.ts new file mode 100644 index 0000000000..07075fae6b --- /dev/null +++ b/api/src/tests/database/migrations/run.test.ts @@ -0,0 +1,28 @@ +import knex, { Knex } from 'knex'; +import { getTracker, MockClient, Tracker } from 'knex-mock-client'; +import run from '../../../database/migrations/run'; + +describe('run', () => { + let db: jest.Mocked; + let tracker: Tracker; + + beforeAll(() => { + db = knex({ client: MockClient }) as jest.Mocked; + tracker = getTracker(); + }); + + afterEach(() => { + tracker.reset(); + }); + + describe('when passed the argument up', () => { + it('returns "Nothing To Updage" if no directus_migrations', async () => { + // note the difference between an empty array and ['Empty'] + tracker.on.select('directus_migrations').response(['Empty']); + await run(db, 'up').catch((e: Error) => { + expect(e).toBeInstanceOf(Error); + expect(e.message).toBe('Nothing to upgrade'); + }); + }); + }); +}); diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 76cef883b8..f508d5c951 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -55,9 +55,10 @@ npx directus database install Installs the initial Directus system tables on an empty database. Used internally by `bootstrap`. -It should be used only in specific cases, e.g. when you want to run something between `install` and `migrate`. You probably should call `directus database migrate:latest` afterwards manually. +It should be used only in specific cases, e.g. when you want to run something between `install` and `migrate`. You +probably should call `directus database migrate:latest` afterwards manually. -You may want to use `directus bootstrap` instead. +You may want to use `directus bootstrap` instead. ### Upgrade the Database diff --git a/package-lock.json b/package-lock.json index f440344606..8b916d247f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,20 +59,20 @@ }, "api": { "name": "directus", - "version": "9.2.0", + "version": "9.2.1", "license": "GPL-3.0-only", "dependencies": { "@aws-sdk/client-ses": "^3.40.0", - "@directus/app": "9.2.0", - "@directus/drive": "9.2.0", - "@directus/drive-azure": "9.2.0", - "@directus/drive-gcs": "9.2.0", - "@directus/drive-s3": "9.2.0", - "@directus/extensions-sdk": "9.2.0", - "@directus/format-title": "9.2.0", - "@directus/schema": "9.2.0", - "@directus/shared": "9.2.0", - "@directus/specs": "9.2.0", + "@directus/app": "9.2.1", + "@directus/drive": "9.2.1", + "@directus/drive-azure": "9.2.1", + "@directus/drive-gcs": "9.2.1", + "@directus/drive-s3": "9.2.1", + "@directus/extensions-sdk": "9.2.1", + "@directus/format-title": "9.2.1", + "@directus/schema": "9.2.1", + "@directus/shared": "9.2.1", + "@directus/specs": "9.2.1", "@godaddy/terminus": "^4.9.0", "@rollup/plugin-alias": "^3.1.2", "@rollup/plugin-virtual": "^2.0.3", @@ -184,6 +184,7 @@ "copyfiles": "2.4.1", "cross-env": "7.0.3", "jest": "27.3.1", + "knex-mock-client": "^1.6.1", "ts-jest": "27.0.7", "ts-node-dev": "1.1.8", "typescript": "4.5.2" @@ -303,12 +304,12 @@ }, "app": { "name": "@directus/app", - "version": "9.2.0", + "version": "9.2.1", "devDependencies": { - "@directus/docs": "9.2.0", - "@directus/extensions-sdk": "9.2.0", - "@directus/format-title": "9.2.0", - "@directus/shared": "9.2.0", + "@directus/docs": "9.2.1", + "@directus/extensions-sdk": "9.2.1", + "@directus/format-title": "9.2.1", + "@directus/shared": "9.2.1", "@fortawesome/fontawesome-svg-core": "1.2.36", "@fortawesome/free-brands-svg-icons": "5.15.4", "@fullcalendar/core": "5.10.1", @@ -443,7 +444,7 @@ }, "docs": { "name": "@directus/docs", - "version": "9.2.0", + "version": "9.2.1", "license": "ISC", "devDependencies": { "directory-tree": "3.0.1", @@ -26773,6 +26774,21 @@ } } }, + "node_modules/knex-mock-client": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/knex-mock-client/-/knex-mock-client-1.6.1.tgz", + "integrity": "sha512-BmP+3zGmgGEllTigslK+vtfMbCOFZP47X7DLVbWkDMsr0WXA7+/VM9z07U/fQEmQTlBiQQRQNAeZl7k82zO1ag==", + "dev": true, + "dependencies": { + "lodash.clonedeep": "^4.5.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "knex": "^0.95.5" + } + }, "node_modules/knex-schema-inspector": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/knex-schema-inspector/-/knex-schema-inspector-1.6.6.tgz", @@ -45026,11 +45042,11 @@ }, "packages/cli": { "name": "@directus/cli", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { - "@directus/format-title": "9.2.0", - "@directus/sdk": "9.2.0", + "@directus/format-title": "9.2.1", + "@directus/sdk": "9.2.1", "@types/yargs": "^17.0.0", "app-module-path": "^2.2.0", "chalk": "^4.1.0", @@ -45212,11 +45228,11 @@ } }, "packages/create-directus-extension": { - "version": "9.2.0", + "version": "9.2.1", "license": "GPL-3.0-only", "dependencies": { - "@directus/extensions-sdk": "9.2.0", - "@directus/shared": "9.2.0", + "@directus/extensions-sdk": "9.2.1", + "@directus/shared": "9.2.1", "inquirer": "^8.1.2" }, "bin": { @@ -45259,7 +45275,7 @@ "license": "0BSD" }, "packages/create-directus-project": { - "version": "9.2.0", + "version": "9.2.1", "license": "GPL-3.0-only", "dependencies": { "chalk": "^4.1.1", @@ -45295,7 +45311,7 @@ }, "packages/drive": { "name": "@directus/drive", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { "fs-extra": "^10.0.0", @@ -45314,11 +45330,11 @@ }, "packages/drive-azure": { "name": "@directus/drive-azure", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { "@azure/storage-blob": "^12.6.0", - "@directus/drive": "9.2.0", + "@directus/drive": "9.2.1", "normalize-path": "^3.0.0" }, "devDependencies": { @@ -45349,10 +45365,10 @@ }, "packages/drive-gcs": { "name": "@directus/drive-gcs", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { - "@directus/drive": "9.2.0", + "@directus/drive": "9.2.1", "@google-cloud/storage": "^5.8.5", "lodash": "4.17.21", "normalize-path": "^3.0.0" @@ -45372,10 +45388,10 @@ }, "packages/drive-s3": { "name": "@directus/drive-s3", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { - "@directus/drive": "9.2.0", + "@directus/drive": "9.2.1", "aws-sdk": "^2.928.0", "normalize-path": "^3.0.0" }, @@ -45420,9 +45436,9 @@ }, "packages/extensions-sdk": { "name": "@directus/extensions-sdk", - "version": "9.2.0", + "version": "9.2.1", "dependencies": { - "@directus/shared": "9.2.0", + "@directus/shared": "9.2.1", "@rollup/plugin-commonjs": "^21.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.0.0", @@ -45472,7 +45488,7 @@ }, "packages/format-title": { "name": "@directus/format-title", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "devDependencies": { "@rollup/plugin-commonjs": "21.0.1", @@ -45492,10 +45508,10 @@ }, "packages/gatsby-source-directus": { "name": "@directus/gatsby-source-directus", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { - "@directus/sdk": "9.2.0", + "@directus/sdk": "9.2.1", "chalk": "4.1.2", "gatsby-source-filesystem": "4.2.0", "gatsby-source-graphql": "4.2.0", @@ -45509,7 +45525,7 @@ }, "packages/schema": { "name": "@directus/schema", - "version": "9.2.0", + "version": "9.2.1", "license": "GPL-3.0", "dependencies": { "knex-schema-inspector": "^1.6.6", @@ -45522,7 +45538,7 @@ }, "packages/sdk": { "name": "@directus/sdk", - "version": "9.2.0", + "version": "9.2.1", "license": "MIT", "dependencies": { "axios": "^0.24.0" @@ -45551,7 +45567,7 @@ }, "packages/shared": { "name": "@directus/shared", - "version": "9.2.0", + "version": "9.2.1", "dependencies": { "axios": "*", "date-fns": "2.24.0", @@ -45610,7 +45626,7 @@ }, "packages/specs": { "name": "@directus/specs", - "version": "9.2.0", + "version": "9.2.1", "license": "GPL-3.0", "dependencies": { "openapi3-ts": "^2.0.1" @@ -47899,10 +47915,10 @@ "@directus/app": { "version": "file:app", "requires": { - "@directus/docs": "9.2.0", - "@directus/extensions-sdk": "9.2.0", - "@directus/format-title": "9.2.0", - "@directus/shared": "9.2.0", + "@directus/docs": "9.2.1", + "@directus/extensions-sdk": "9.2.1", + "@directus/format-title": "9.2.1", + "@directus/shared": "9.2.1", "@fortawesome/fontawesome-svg-core": "1.2.36", "@fortawesome/free-brands-svg-icons": "5.15.4", "@fullcalendar/core": "5.10.1", @@ -48004,8 +48020,8 @@ "@directus/cli": { "version": "file:packages/cli", "requires": { - "@directus/format-title": "9.2.0", - "@directus/sdk": "9.2.0", + "@directus/format-title": "9.2.1", + "@directus/sdk": "9.2.1", "@types/figlet": "1.5.4", "@types/fs-extra": "9.0.13", "@types/jest": "27.0.3", @@ -48176,7 +48192,7 @@ "version": "file:packages/drive-azure", "requires": { "@azure/storage-blob": "^12.6.0", - "@directus/drive": "9.2.0", + "@directus/drive": "9.2.1", "@types/fs-extra": "9.0.13", "@types/jest": "27.0.3", "@types/node": "16.11.9", @@ -48204,7 +48220,7 @@ "@directus/drive-gcs": { "version": "file:packages/drive-gcs", "requires": { - "@directus/drive": "9.2.0", + "@directus/drive": "9.2.1", "@google-cloud/storage": "^5.8.5", "@lukeed/uuid": "2.0.0", "@types/fs-extra": "9.0.13", @@ -48223,7 +48239,7 @@ "@directus/drive-s3": { "version": "file:packages/drive-s3", "requires": { - "@directus/drive": "9.2.0", + "@directus/drive": "9.2.1", "@lukeed/uuid": "2.0.0", "@types/fs-extra": "9.0.13", "@types/jest": "27.0.3", @@ -48253,7 +48269,7 @@ "@directus/extensions-sdk": { "version": "file:packages/extensions-sdk", "requires": { - "@directus/shared": "9.2.0", + "@directus/shared": "9.2.1", "@rollup/plugin-commonjs": "^21.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.0.0", @@ -48305,7 +48321,7 @@ "@directus/gatsby-source-directus": { "version": "file:packages/gatsby-source-directus", "requires": { - "@directus/sdk": "9.2.0", + "@directus/sdk": "9.2.1", "chalk": "4.1.2", "gatsby-source-filesystem": "4.2.0", "gatsby-source-graphql": "4.2.0", @@ -56747,8 +56763,8 @@ "create-directus-extension": { "version": "file:packages/create-directus-extension", "requires": { - "@directus/extensions-sdk": "9.2.0", - "@directus/shared": "9.2.0", + "@directus/extensions-sdk": "9.2.1", + "@directus/shared": "9.2.1", "inquirer": "^8.1.2" }, "dependencies": { @@ -58096,16 +58112,16 @@ "version": "file:api", "requires": { "@aws-sdk/client-ses": "^3.40.0", - "@directus/app": "9.2.0", - "@directus/drive": "9.2.0", - "@directus/drive-azure": "9.2.0", - "@directus/drive-gcs": "9.2.0", - "@directus/drive-s3": "9.2.0", - "@directus/extensions-sdk": "9.2.0", - "@directus/format-title": "9.2.0", - "@directus/schema": "9.2.0", - "@directus/shared": "9.2.0", - "@directus/specs": "9.2.0", + "@directus/app": "9.2.1", + "@directus/drive": "9.2.1", + "@directus/drive-azure": "9.2.1", + "@directus/drive-gcs": "9.2.1", + "@directus/drive-s3": "9.2.1", + "@directus/extensions-sdk": "9.2.1", + "@directus/format-title": "9.2.1", + "@directus/schema": "9.2.1", + "@directus/shared": "9.2.1", + "@directus/specs": "9.2.1", "@godaddy/terminus": "^4.9.0", "@keyv/redis": "^2.1.2", "@rollup/plugin-alias": "^3.1.2", @@ -58186,6 +58202,7 @@ "keyv": "^4.0.3", "keyv-memcache": "^1.2.5", "knex": "^0.95.11", + "knex-mock-client": "^1.6.1", "knex-schema-inspector": "1.6.6", "ldapjs": "^2.3.1", "liquidjs": "^9.25.0", @@ -64521,6 +64538,15 @@ } } }, + "knex-mock-client": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/knex-mock-client/-/knex-mock-client-1.6.1.tgz", + "integrity": "sha512-BmP+3zGmgGEllTigslK+vtfMbCOFZP47X7DLVbWkDMsr0WXA7+/VM9z07U/fQEmQTlBiQQRQNAeZl7k82zO1ag==", + "dev": true, + "requires": { + "lodash.clonedeep": "^4.5.0" + } + }, "knex-schema-inspector": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/knex-schema-inspector/-/knex-schema-inspector-1.6.6.tgz", diff --git a/package.json b/package.json index 68f73d76a2..867f2aea4a 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,10 @@ "pack": "node docker/pack", "release": "lerna version --force-publish --exact", "test": "lerna run test", - "test:e2e": "jest tests -c tests/jest.config.js", + "test:int": "jest tests -c tests/integration/jest.config.js", + "test:e2e": "jest tests -c tests/e2e/jest.config.js", "test:e2e:watch": "npm run test:e2e -- --watch", - "posttest:e2e:watch": "ts-node --project ./tests/tsconfig.json --transpile-only ./tests/setup/teardown.ts", + "posttest:e2e:watch": "ts-node --project ./tests/tsconfig.json --transpile-only ./tests/e2e/setup/teardown.ts", "cli": "cross-env NODE_ENV=development SERVE_APP=false DOTENV_CONFIG_PATH=api/.env ts-node -r dotenv/config --script-mode --transpile-only api/src/cli/run.ts" }, "engines": { diff --git a/tests/e2e/api/auth/login.test.ts b/tests/e2e/api/auth/login.test.ts new file mode 100644 index 0000000000..57d92e6ca4 --- /dev/null +++ b/tests/e2e/api/auth/login.test.ts @@ -0,0 +1,159 @@ +import knex, { Knex } from 'knex'; +import config from '../../config'; +import request from 'supertest'; +import { getDBsToTest } from '../../get-dbs-to-test'; + +describe('auth', () => { + describe('login', () => { + const databases = new Map(); + + beforeAll(async () => { + const vendors = getDBsToTest(); + + for (const vendor of vendors) { + databases.set(vendor, knex(config.knexConfig[vendor]!)); + } + }); + + afterAll(async () => { + for (const [_vendor, connection] of databases) { + await connection.destroy(); + } + }); + + describe('when correct credentials are provided', () => { + it.each(getDBsToTest())(`%p returns an access_token, expires and a refresh_token for admin`, async (vendor) => { + const url = `http://localhost:${config.ports[vendor]!}`; + + const response = await request(url) + .post(`/auth/login`) + .send({ email: 'test@admin.com', password: 'TestAdminPassword' }) + .expect('Content-Type', /application\/json/) + .expect(200); + + expect(response.body).toMatchObject({ + data: { + access_token: expect.any(String), + expires: expect.any(Number), + refresh_token: expect.any(String), + }, + }); + }); + it.each(getDBsToTest())(`%p returns an access_token, expires and a refresh_token for user`, async (vendor) => { + const url = `http://localhost:${config.ports[vendor]!}`; + + const response = await request(url) + .post(`/auth/login`) + .send({ + email: 'test@user.com', + password: 'TestUserPassword', + }) + .expect('Content-Type', /application\/json/) + .expect(200); + + expect(response.body).toMatchObject({ + data: { + access_token: expect.any(String), + expires: expect.any(Number), + refresh_token: expect.any(String), + }, + }); + }); + }); + describe('when incorrect credentials are provided', () => { + it.each(getDBsToTest())(`%p returns code: UNAUTHORIZED for incorrect password`, async (vendor) => { + const url = `http://localhost:${config.ports[vendor]!}`; + + const response = await request(url) + .post(`/auth/login`) + .send({ + email: 'test@admin.com', + password: 'IncorrectPassword', + }) + .expect('Content-Type', /application\/json/) + .expect(401); + expect(response.body).toStrictEqual({ + errors: [ + { + message: 'Invalid user credentials.', + extensions: { + code: 'INVALID_CREDENTIALS', + }, + }, + ], + }); + }); + it.each(getDBsToTest())(`%p returns code: UNAUTHORIZED for unregistered email`, async (vendor) => { + const url = `http://localhost:${config.ports[vendor]!}`; + + const response = await request(url) + .post(`/auth/login`) + .send({ + email: 'test@fake.com', + password: 'TestAdminPassword', + }) + .expect('Content-Type', /application\/json/) + .expect(401); + + expect(response.body).toStrictEqual({ + errors: [ + { + message: 'Invalid user credentials.', + extensions: { + code: 'INVALID_CREDENTIALS', + }, + }, + ], + }); + }); + it.each(getDBsToTest())(`%p returns code: INVALID_CREDENTIALS for invalid email`, async (vendor) => { + const url = `http://localhost:${config.ports[vendor]!}`; + + const response = await request(url) + .post(`/auth/login`) + .send({ + email: 'invalidEmail', + password: 'TestAdminPassword', + }) + .expect('Content-Type', /application\/json/) + .expect(400); + + expect(response.body).toStrictEqual({ + errors: [ + { + message: '"email" must be a valid email', + extensions: { + code: 'INVALID_PAYLOAD', + }, + }, + ], + }); + }); + it.each(getDBsToTest())( + `%p returns message: "password is required" when no password is provided`, + async (vendor) => { + const url = `http://localhost:${config.ports[vendor]!}`; + + const response = await request(url) + .post(`/auth/login`) + .send({ + email: 'test@admin.com', + }) + .expect('Content-Type', /application\/json/) + .expect(400); + + expect(response.body).toStrictEqual({ + errors: [ + { + message: '"password" is required', + extensions: { + code: 'INVALID_PAYLOAD', + }, + }, + ], + }); + } + ); + }); + }); +}); diff --git a/tests/api/items/filters.test.ts b/tests/e2e/api/items/filters.test.ts similarity index 100% rename from tests/api/items/filters.test.ts rename to tests/e2e/api/items/filters.test.ts diff --git a/tests/api/items/many-to-many.test.ts b/tests/e2e/api/items/many-to-many.test.ts similarity index 90% rename from tests/api/items/many-to-many.test.ts rename to tests/e2e/api/items/many-to-many.test.ts index 54dc5a68bf..ace6b8ade7 100644 --- a/tests/api/items/many-to-many.test.ts +++ b/tests/e2e/api/items/many-to-many.test.ts @@ -122,9 +122,16 @@ describe('/items', () => { expect(await databases.get(vendor)!('artists').select('name').where('id', artist.id)).toMatchObject([ { name: artist.name }, ]); - expect(await databases.get(vendor)!('events').select('cost').where('id', event.id)).toMatchObject([ - { cost: event.cost }, - ]); + if (vendor === 'postgres10') { + const cost = Math.round(event.cost * 10) / 10; + expect(await databases.get(vendor)!('events').select('cost').where('id', event.id)).toMatchObject([ + { cost: cost }, + ]); + } else { + expect(await databases.get(vendor)!('events').select('cost').where('id', event.id)).toMatchObject([ + { cost: event.cost }, + ]); + } }); }); describe('/:collection GET', () => { @@ -251,9 +258,16 @@ describe('/items', () => { }, }); for (let row = 0; row < response.data.data.length; row++) { - expect(response.data.data[row].events_id).toMatchObject({ - cost: event.cost, - }); + if (vendor === 'postgres10') { + const cost = Math.round(event.cost * 10) / 10; + expect(response.data.data[row].events_id).toMatchObject({ + cost: cost, + }); + } else { + expect(response.data.data[row].events_id).toMatchObject({ + cost: event.cost, + }); + } } expect(response.data.data.length).toBe(keys.length); }); @@ -300,7 +314,12 @@ describe('/items', () => { expect(await databases.get(vendor)!('artists_events').select('*').where('id', items[row].id)).toStrictEqual([]); } expect((await databases.get(vendor)!('artists').select('name').where('id', artist.id))[0].name).toBe(artist.name); - expect((await databases.get(vendor)!('events').select('cost').where('id', event.id))[0].cost).toBe(event.cost); + if (vendor === 'postgres10') { + const cost = Math.round(event.cost * 10) / 10; + expect((await databases.get(vendor)!('events').select('cost').where('id', event.id))[0].cost).toBe(cost); + } else { + expect((await databases.get(vendor)!('events').select('cost').where('id', event.id))[0].cost).toBe(event.cost); + } }); }); }); diff --git a/tests/api/items/no-relations.test.ts b/tests/e2e/api/items/no-relations.test.ts similarity index 99% rename from tests/api/items/no-relations.test.ts rename to tests/e2e/api/items/no-relations.test.ts index 190f10e75c..f48d501669 100644 --- a/tests/api/items/no-relations.test.ts +++ b/tests/e2e/api/items/no-relations.test.ts @@ -268,7 +268,7 @@ describe('/items', () => { Object.values(items).forEach((item: any) => { keys.push(item.id); }); - } else if (vendor !== 'postgres') { + } else if (vendor !== 'postgres' && vendor !== 'postgres10') { items = await seedTable(databases.get(vendor)!, 1, 'artists', artists, { raw: 'select id from artists order by id desc limit 10;', }); diff --git a/tests/api/items/one-to-many.test.ts b/tests/e2e/api/items/one-to-many.test.ts similarity index 100% rename from tests/api/items/one-to-many.test.ts rename to tests/e2e/api/items/one-to-many.test.ts diff --git a/tests/api/ping.test.ts b/tests/e2e/api/ping.test.ts similarity index 100% rename from tests/api/ping.test.ts rename to tests/e2e/api/ping.test.ts diff --git a/tests/api/schema.png b/tests/e2e/api/schema.png similarity index 100% rename from tests/api/schema.png rename to tests/e2e/api/schema.png diff --git a/tests/config.ts b/tests/e2e/config.ts similarity index 98% rename from tests/config.ts rename to tests/e2e/config.ts index 06b5e01be2..33feaa6052 100644 --- a/tests/config.ts +++ b/tests/e2e/config.ts @@ -22,9 +22,8 @@ export const processID = generateID(); export const CONTAINER_PERSISTENCE_FILE = '.e2e-containers.json'; -// TODO resolve path -const migrationsDir = './tests/setup/migrations'; -const seedsDir = './tests/setup/seeds'; +const migrationsDir = './tests/e2e/setup/migrations'; +const seedsDir = './tests/e2e/setup/seeds'; const config: Config = { containerConfig: { diff --git a/tests/get-dbs-to-test.ts b/tests/e2e/get-dbs-to-test.ts similarity index 100% rename from tests/get-dbs-to-test.ts rename to tests/e2e/get-dbs-to-test.ts diff --git a/tests/get-urls-to-test.ts b/tests/e2e/get-urls-to-test.ts similarity index 100% rename from tests/get-urls-to-test.ts rename to tests/e2e/get-urls-to-test.ts diff --git a/tests/jest.config.js b/tests/e2e/jest.config.js similarity index 74% rename from tests/jest.config.js rename to tests/e2e/jest.config.js index 13d9ca5868..25a4c7cb21 100644 --- a/tests/jest.config.js +++ b/tests/e2e/jest.config.js @@ -3,5 +3,5 @@ module.exports = { verbose: true, globalSetup: './setup/setup.ts', globalTeardown: './setup/teardown.ts', - modulePathIgnorePatterns: ['setup/utils'], + modulePathIgnorePatterns: ['./setup/utils'], }; diff --git a/tests/setup/global.ts b/tests/e2e/setup/global.ts similarity index 100% rename from tests/setup/global.ts rename to tests/e2e/setup/global.ts diff --git a/tests/setup/migrations/20211016054403_create_base_tables.js b/tests/e2e/setup/migrations/20211016054403_create_base_tables.js similarity index 100% rename from tests/setup/migrations/20211016054403_create_base_tables.js rename to tests/e2e/setup/migrations/20211016054403_create_base_tables.js diff --git a/tests/setup/migrations/20211016054421_create_relational_tables.js b/tests/e2e/setup/migrations/20211016054421_create_relational_tables.js similarity index 100% rename from tests/setup/migrations/20211016054421_create_relational_tables.js rename to tests/e2e/setup/migrations/20211016054421_create_relational_tables.js diff --git a/tests/setup/seeds/01_directus_collections.js b/tests/e2e/setup/seeds/01_directus_collections.js similarity index 100% rename from tests/setup/seeds/01_directus_collections.js rename to tests/e2e/setup/seeds/01_directus_collections.js diff --git a/tests/setup/seeds/02_directus_relations.js b/tests/e2e/setup/seeds/02_directus_relations.js similarity index 100% rename from tests/setup/seeds/02_directus_relations.js rename to tests/e2e/setup/seeds/02_directus_relations.js diff --git a/tests/setup/seeds/03_directus_roles.js b/tests/e2e/setup/seeds/03_directus_roles.js similarity index 64% rename from tests/setup/seeds/03_directus_roles.js rename to tests/e2e/setup/seeds/03_directus_roles.js index 2451866da5..ef78893a4f 100644 --- a/tests/setup/seeds/03_directus_roles.js +++ b/tests/e2e/setup/seeds/03_directus_roles.js @@ -1,5 +1,6 @@ exports.seed = async function (knex) { return await knex('directus_roles').insert([ { id: '5b935e65-d3db-4457-96f1-597e2fcfc7f3', name: 'TestAdmin', admin_access: true, app_access: true }, + { id: '214faee7-d6a6-4a4c-b1cd-f9e9bd0b6fb7', name: 'TestUser', admin_access: false, app_access: false }, ]); }; diff --git a/tests/e2e/setup/seeds/04_directus_users.js b/tests/e2e/setup/seeds/04_directus_users.js new file mode 100644 index 0000000000..644891b012 --- /dev/null +++ b/tests/e2e/setup/seeds/04_directus_users.js @@ -0,0 +1,22 @@ +const generateHash = require('../utils/generateHash'); + +exports.seed = async function (knex) { + return await knex('directus_users').insert([ + { + id: 'a8057636-9b70-4804-bfec-19c88d1a3273', + email: 'test@admin.com', + password: await generateHash.hash('TestAdminPassword'), + status: 'active', + role: '5b935e65-d3db-4457-96f1-597e2fcfc7f3', + token: 'AdminToken', + }, + { + id: 'cb8cd13b-037f-40ca-862a-ea1e1f4bfca2', + email: 'test@user.com', + password: await generateHash.hash('TestUserPassword'), + status: 'active', + role: '214faee7-d6a6-4a4c-b1cd-f9e9bd0b6fb7', + token: 'UserToken', + }, + ]); +}; diff --git a/tests/setup/setup.ts b/tests/e2e/setup/setup.ts similarity index 98% rename from tests/setup/setup.ts rename to tests/e2e/setup/setup.ts index 82407c14aa..413ea3507d 100644 --- a/tests/setup/setup.ts +++ b/tests/e2e/setup/setup.ts @@ -32,12 +32,12 @@ export default async (jestConfig: GlobalConfigTsJest): Promise => { title: 'Create Directus Docker Image', task: async (_, task) => { const result = await globby(['**/*', '!node_modules', '!**/node_modules', '!**/src', '!tests', '!**/tests'], { - cwd: path.resolve(__dirname, '..', '..'), + cwd: path.resolve(__dirname, '..', '..', '..'), }); const stream = await docker.buildImage( { - context: path.resolve(__dirname, '..', '..'), + context: path.resolve(__dirname, '..', '..', '..'), src: ['Dockerfile', ...result], }, { diff --git a/tests/setup/teardown.ts b/tests/e2e/setup/teardown.ts similarity index 100% rename from tests/setup/teardown.ts rename to tests/e2e/setup/teardown.ts diff --git a/tests/setup/utils/await-connection.ts b/tests/e2e/setup/utils/await-connection.ts similarity index 100% rename from tests/setup/utils/await-connection.ts rename to tests/e2e/setup/utils/await-connection.ts diff --git a/tests/setup/utils/factories.test.ts b/tests/e2e/setup/utils/factories.test.ts similarity index 100% rename from tests/setup/utils/factories.test.ts rename to tests/e2e/setup/utils/factories.test.ts diff --git a/tests/setup/utils/factories.ts b/tests/e2e/setup/utils/factories.ts similarity index 100% rename from tests/setup/utils/factories.ts rename to tests/e2e/setup/utils/factories.ts diff --git a/tests/e2e/setup/utils/generateHash.js b/tests/e2e/setup/utils/generateHash.js new file mode 100644 index 0000000000..625be228d5 --- /dev/null +++ b/tests/e2e/setup/utils/generateHash.js @@ -0,0 +1,10 @@ +const argon2 = require('argon2'); + +exports.hash = function (stringToHash) { + const buffer = 'string'; + const argon2HashConfigOptions = { test: 'test', associatedData: buffer }; // Disallow the HASH_RAW option, see https://github.com/directus/directus/discussions/7670#discussioncomment-1255805 + // test, if specified, must be passed as a Buffer to argon2.hash, see https://github.com/ranisalt/node-argon2/wiki/Options#test + if ('test' in argon2HashConfigOptions) + argon2HashConfigOptions.associatedData = Buffer.from(argon2HashConfigOptions.associatedData); + return argon2.hash(stringToHash, argon2HashConfigOptions); +}; diff --git a/tests/integration/jest.config.js b/tests/integration/jest.config.js new file mode 100644 index 0000000000..d50dfc1125 --- /dev/null +++ b/tests/integration/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + preset: 'ts-jest', + verbose: true, + setupFiles: ['dotenv/config'], +}; diff --git a/tests/setup/seeds/04_directus_users.js b/tests/setup/seeds/04_directus_users.js deleted file mode 100644 index 683a8f24ee..0000000000 --- a/tests/setup/seeds/04_directus_users.js +++ /dev/null @@ -1,12 +0,0 @@ -exports.seed = async function (knex) { - return await knex('directus_users').insert([ - { - id: 'a8057636-9b70-4804-bfec-19c88d1a3273', - email: 'test@admin.com', - password: 'TestAdminPassword', - status: 'active', - role: '5b935e65-d3db-4457-96f1-597e2fcfc7f3', - token: 'AdminToken', - }, - ]); -};