diff --git a/.gitignore b/.gitignore index f6f4b425d..864ac9246 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ main .r.logs.log server.log */_tmp* +*/node_modules diff --git a/README.md b/README.md index 77f0651ba..63bd12686 100644 --- a/README.md +++ b/README.md @@ -148,10 +148,18 @@ Changes to `.js` files are handled by Node server([react-scripts](https://github ## Test +### Backend unit tests ```bash make test ``` +### Backend integration tests +1. Build the API Server: `make build` +2. Follow [these instructions](#Run-locally) to target existing OpenShift project (**Note:** the project must not contain existing mobile clients) +3. Install dependencies: `cd integration_tests && npm install` +4. Run the tests: `npm test` + + ## Generate the API definition for the CRD If you are changing the type definition of (MobileClient)[./pkg/apis/aerogear/v1alpha1/types.go], you should run the following command to regenerate some of the files. diff --git a/integration_tests/mobile_clients/index.js b/integration_tests/mobile_clients/index.js new file mode 100644 index 000000000..b9dce909f --- /dev/null +++ b/integration_tests/mobile_clients/index.js @@ -0,0 +1,66 @@ +const assert = require('assert') +const sendRequest = require('../util/sendRequest') + +const template = { + name: "integration-test-client", + appIdentifier: "integration.test", + clientType: "android" +} + +describe('initially', () => { + it('should have no mobile clients present', async () => { + const res = await sendRequest('GET', 'mobileclients') + assert.equal(res.status, 200) + assert.equal(res.data.items.length, 0) + }); +}); + +describe('when creating a new client', () => { + let res; + it('should be created without error', async () => { + res = await sendRequest('POST', 'mobileclients', template) + assert.equal(res.status, 200) + }); + + it('created client should have required metadata', () => { + assert.equal(res.data.metadata.name, template.name) + assert.equal(res.data.spec.name, template.name) + assert.equal(res.data.spec.clientType, template.clientType) + assert.equal(res.data.spec.appIdentifier, template.appIdentifier) + assert.equal(res.data.status.clientId, template.name) + }); + +}); + +describe('when listing a client', () => { + let res; + it('should be listed without error', async () => { + res = await sendRequest('GET', 'mobileclients') + assert.equal(res.status, 200) + }); + + it('listed client should have required metadata', () => { + const listedClientData = res.data.items[0] + assert.equal(listedClientData.metadata.name, template.name) + assert.equal(listedClientData.spec.name, template.name) + assert.equal(listedClientData.spec.clientType, template.clientType) + assert.equal(listedClientData.spec.appIdentifier, template.appIdentifier) + assert.equal(listedClientData.status.clientId, template.name) + }); + +}); + +describe('when deleting a client', () => { + let res; + it('should be deleted without error', async () => { + res = await sendRequest('DELETE', `mobileclients/${template.name}`) + assert.equal(res.status, 200) + }); + + it('deleted client should be no longer present in the list', async () => { + res = await sendRequest('GET', 'mobileclients') + assert.equal(res.status, 200) + assert.equal(res.data.items.length, 0) + }); + +}); diff --git a/integration_tests/package-lock.json b/integration_tests/package-lock.json new file mode 100644 index 000000000..a64b9b125 --- /dev/null +++ b/integration_tests/package-lock.json @@ -0,0 +1,221 @@ +{ + "name": "mdc-integration-tests", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "axios": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "dev": true, + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "follow-redirects": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", + "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/integration_tests/package.json b/integration_tests/package.json new file mode 100644 index 000000000..87eab8a84 --- /dev/null +++ b/integration_tests/package.json @@ -0,0 +1,12 @@ +{ + "name": "mdc-integration-tests", + "description": "Integration tests for MDC", + "version": "0.0.1", + "scripts": { + "test": "mocha ." + }, + "devDependencies": { + "axios": "^0.18.0", + "mocha": "^5.2.0" + } +} diff --git a/integration_tests/runner.test.js b/integration_tests/runner.test.js new file mode 100644 index 000000000..e159db758 --- /dev/null +++ b/integration_tests/runner.test.js @@ -0,0 +1,30 @@ +const { exec } = require('child_process') + +process.env.NAMESPACE = process.env.NAMESPACE || "mdc-integration-testing" +process.env.KUBERNETES_CONFIG = process.env.KUBERNETES_CONFIG || `${process.env.HOME}/.kube/config` + +let goOutput + +// Spin up backend server on port 4000 +before( function(done) { + this.timeout(10000) + goOutput = exec('../mobile-developer-console') + goOutput.stdout.on('data', data => { + console.log(data.toString()) + }) + goOutput.stderr.on('data', data => { + const message = data.toString() + console.log(message) + if (message.indexOf("Starting application") > -1) { + done() + } + }) +}); + +after(() => { + goOutput.kill("SIGINT") +}) + +describe('Mobile Clients', () => { + require('./mobile_clients') +}); diff --git a/integration_tests/util/sendRequest.js b/integration_tests/util/sendRequest.js new file mode 100644 index 000000000..609abbda9 --- /dev/null +++ b/integration_tests/util/sendRequest.js @@ -0,0 +1,18 @@ +const axios = require('axios') + +const api = "http://localhost:4000/api" + +const sendRequest = async (method, path, data) => { + let headers + if (method === "POST") { + headers = {'Content-Type': 'application/json'} + } + return await axios({ + url: `${api}/${path}`, + method, + data, + headers + }) +} + +module.exports = sendRequest