diff --git a/package.json b/package.json index 61b663709b6e62324507aa60059a2db92d5d8528..79f87cb4d457fdf50473d7082131ee8e04011618 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "tslint": "tslint --project tsconfig.json", "tsfix": "tslint --project tsconfig.json --fix", "tsc": "tsc --project tsconfig.json", - "test": "mocha --require mocha-graphql-register --require ts-node/register test/**/*.test.ts" + "test": "mocha --require mocha-graphql-register --require ts-node/register test/**/*.test.ts --timeout 20000" }, "repository": { "type": "git", diff --git a/src/graphql/schema.js b/src/graphql/schema.ts similarity index 50% rename from src/graphql/schema.js rename to src/graphql/schema.ts index 77c88112ca5856a69e3fa1b398575fbd8393c6fb..12b34f9f0fb3b42122a2be73d7eaefbaa3450f62 100644 --- a/src/graphql/schema.js +++ b/src/graphql/schema.ts @@ -3,8 +3,8 @@ * @author akka vodol */ -import actionDefs from './typeDefs/actions.graphql'; -import objectDefs from './typeDefs/objects.graphql'; +const actionDefs = require('./typeDefs/actions.graphql'); +const objectDefs = require('./typeDefs/objects.graphql'); import { resolvers } from './resolvers'; const typeDefs = actionDefs.concat(objectDefs); @@ -13,7 +13,9 @@ const schema = { typeDefs, resolvers, logger: {log: e => console.log(e)}, - inheritResolversFromInterfaces: true + inheritResolversFromInterfaces: true, + //formatResponse: response => { console.log(JSON.stringify(response)); return response; }, + //formatError: error => {console.log(JSON.stringify(error)); return error; } }; export default schema; \ No newline at end of file diff --git a/test/resolvers/data/onplatal.ts b/test/resolvers/data/onplatal.ts new file mode 100644 index 0000000000000000000000000000000000000000..d1a3fdfcbaf2d7b755c28ae0195a29fb580b4b8d --- /dev/null +++ b/test/resolvers/data/onplatal.ts @@ -0,0 +1,41 @@ +/** + * @file Ce fichier charge tous les tests sans authentification + * @author ofacklam + */ + +import fs from 'fs'; +import path from 'path'; +import { TestCollection, TestSet } from "../testData"; +import { AuthorizationModel } from "../../../src/graphql/models/authorization"; +import { UserModel } from "../../../src/graphql/models/userModel"; +import { GroupModel } from "../../../src/graphql/models/groupModel"; +import { MessageModel } from "../../../src/graphql/models/messageModel"; +import { RequestModel } from "../../../src/graphql/models/requestModel"; + +let uid = AuthorizationModel.ONPLATALUSER; + +const tests : TestCollection = { + description: "On-platal user", + context : async ({ req }) => { + return { + request: req, + user: { uid: uid }, + models: { + auth: await AuthorizationModel.create(uid), + user: new UserModel(uid), + group: new GroupModel(uid), + message: new MessageModel(uid), + request: new RequestModel(uid) + } + }; + }, + tests : [] +} + +let dir = path.resolve(__dirname, './onplatal') +fs.readdirSync(dir).forEach(file => { + const testSet : TestSet = require(path.resolve(dir, file)).tests; + tests.tests.push(testSet); +}); + +export {tests}; \ No newline at end of file diff --git a/test/resolvers/data/onplatal/groups.ts b/test/resolvers/data/onplatal/groups.ts new file mode 100644 index 0000000000000000000000000000000000000000..7682bb21546467311a954c6fab83e52935210200 --- /dev/null +++ b/test/resolvers/data/onplatal/groups.ts @@ -0,0 +1,23 @@ +/** + * @file Ce fichier contient les tests des resolvers des groupes + * @author ofacklam +*/ + +import { TestSet } from '../../testData'; + +export const tests : TestSet = { + description: "Group type resolvers", + tests: [ + { + description: "group(gid)", + query: ` + query { + group(gid:"br") { + gid + } + } + `, + result: { "data": { "group": { "gid": "br" } } } + } + ] +} diff --git a/test/resolvers/data/onplatal/users.ts b/test/resolvers/data/onplatal/users.ts new file mode 100644 index 0000000000000000000000000000000000000000..4dc55f1eee01cb696029595364a382bd48567c92 --- /dev/null +++ b/test/resolvers/data/onplatal/users.ts @@ -0,0 +1,150 @@ +/** + * @file Ce fichier contient les tests des resolvers des users + * @author ofacklam +*/ + +import { TestSet } from '../../testData'; + +export const tests: TestSet = { + description: "User type resolvers", + tests: [ + { + description: "user(uid)", + query: ` + query { + user(uid: "oliver.facklam") { + uid + } + } + `, + result: { + "data": { + "user": { + "uid": "oliver.facklam" + } + } + } + }, + + { + description: "searchTOL(givenName)", + query: ` + query { + searchTOL(givenName: "Olivér") { + uid + } + } + `, + result: { + "data": { + "searchTOL": [ + { + "uid": "oliver.facklam" + } + ] + } + } + }, + + { + description: "searchTOL(lastName) partial", + query: ` + query { + searchTOL(lastName: "Fack") { + uid + } + } + `, + result: { + "data": { + "searchTOL": [ + { + "uid": "hugues.asofa-zeufack" + }, + { + "uid": "fabrice.zapfack" + }, + { + "uid": "jordan.lekeufack-sopze" + }, + { + "uid": "oliver.facklam" + } + ] + } + } + }, + + /*{ + description: "searchTOL(groups) triclassés", + query: ` + query { + searchTOL(groups: ["br", "faerix", "jtx"]) { + uid + } + } + `, + result: { + "data": { + "searchTOL": [ + { + "uid": "dubut.2003" + }, + { + "uid": "brodard.2004" + }, + { + "uid": "le-floch.2004" + }, + { + "uid": "rabie.2004" + }, + { + "uid": "pierre-etienne.marx" + }, + { + "uid": "lauriane.aufrant" + }, + { + "uid": "matthias.bry" + }, + { + "uid": "julia.chatain" + }, + { + "uid": "victor.berger" + }, + { + "uid": "augustin.lenormand" + }, + { + "uid": "timothee.darcet" + } + ] + } + } + },*/ + + { + description: "firstName, lastName, nickName", + query: ` + query { + user(uid: "oliver.facklam") { + givenName + lastName + nickname + } + } + `, + result: { + "data": { + "user": { + "givenName": "Olivér", + "lastName": "Facklam", + "nickname": null + } + } + } + }, + ] +} \ No newline at end of file diff --git a/test/resolvers/data/unauthenticated.ts b/test/resolvers/data/unauthenticated.ts new file mode 100644 index 0000000000000000000000000000000000000000..a606551678b0697004a461e6630797b37154b0e2 --- /dev/null +++ b/test/resolvers/data/unauthenticated.ts @@ -0,0 +1,41 @@ +/** + * @file Ce fichier charge tous les tests sans authentification + * @author ofacklam + */ + +import fs from 'fs'; +import path from 'path'; +import { TestCollection, TestSet } from "../testData"; +import { AuthorizationModel } from "../../../src/graphql/models/authorization"; +import { UserModel } from "../../../src/graphql/models/userModel"; +import { GroupModel } from "../../../src/graphql/models/groupModel"; +import { MessageModel } from "../../../src/graphql/models/messageModel"; +import { RequestModel } from "../../../src/graphql/models/requestModel"; + +let uid = AuthorizationModel.PUBLICUSER; + +const tests : TestCollection = { + description: "Public user", + context : async ({ req }) => { + return { + request: req, + user: { uid: uid }, + models: { + auth: await AuthorizationModel.create(uid), + user: new UserModel(uid), + group: new GroupModel(uid), + message: new MessageModel(uid), + request: new RequestModel(uid) + } + }; + }, + tests : [] +} + +let dir = path.resolve(__dirname, './unauthenticated') +fs.readdirSync(dir).forEach(file => { + const testSet : TestSet = require(path.resolve(dir, file)).tests; + tests.tests.push(testSet); +}); + +export {tests}; \ No newline at end of file diff --git a/test/resolvers/data/unauthenticated/users.ts b/test/resolvers/data/unauthenticated/users.ts new file mode 100644 index 0000000000000000000000000000000000000000..9321a578b3ee10bb7c7b01bb399719244273adba --- /dev/null +++ b/test/resolvers/data/unauthenticated/users.ts @@ -0,0 +1,44 @@ +/** + * @file Ce fichier contient les tests des resolvers des users + * @author ofacklam +*/ + +import { TestSet } from '../../testData'; + +export const tests: TestSet = { + description: "User type resolvers", + tests: [ + { + description: "user(uid) not authorized", + query: ` + query { + user(uid: "oliver.facklam") { + uid + } + } + `, + result: { + "data": { + "user": null + } + } + }, + + { + description: "searchTOL() not authorized", + query: ` + query { + searchTOL(givenName: "Olivér") { + uid + } + } + `, + result: { + "data": { + "searchTOL": null + } + } + } + ] +} + diff --git a/test/resolvers/resolvers.test.ts b/test/resolvers/resolvers.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae4b159139c45e6b4eb48cd7fd523ccc3e3c08dc --- /dev/null +++ b/test/resolvers/resolvers.test.ts @@ -0,0 +1,63 @@ +/** + * @file Ce fichier charge et execute tous les tests sur les resolvers + * @author ofacklam + */ + +import { expect } from 'chai'; +import fs from 'fs'; +import path from 'path'; +import { ApolloServer } from 'apollo-server-express'; +import { createTestClient } from 'apollo-server-testing'; + +//TODO : Set up a mock LDAP server (LDAP_URI = ... or TARGET_ENV=testing) + +import schema from '../../src/graphql/schema'; +import { TestCollection } from './testData'; + +const dir = path.resolve(__dirname, './data'); + +describe("GraphQL resolvers", function() { + fs.readdirSync(dir, {withFileTypes:true}) + .filter(item => !item.isDirectory()) + .forEach(file => { + const testCol : TestCollection = require(path.resolve(dir, file.name)).tests; + + describe(testCol.description, function() { + //contruct context and apollo server + const server = new ApolloServer({ + ...schema, + context: testCol.context + }); + const {query} = createTestClient(server); + + for (let testSet of testCol.tests) { + describe(testSet.description, function() { + for(let t of testSet.tests) { + it(t.description, async function() { + //silence the console + console.log = function () { }; + + //query + let res = await query({query: t.query}); + + //reset console + delete console.log; + + let final = {}; + final['data'] = res.data; + //if(res.errors !== undefined) final['errors'] = res.errors; + expect(final).to.deep.equal(t.result); + }) + } + }) + } + }) + }) + + beforeEach(function () { + + }); + afterEach(function () { + + }); +}) \ No newline at end of file diff --git a/test/resolvers/testData.d.ts b/test/resolvers/testData.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..b8a75520bb36fc0ee06ae7dd40947ae4009cab0a --- /dev/null +++ b/test/resolvers/testData.d.ts @@ -0,0 +1,23 @@ +/** + * @file Ce fichier définit le type de base pour les tests + * @author ofacklam +*/ + +import { Context } from "../../src/graphql/typeDefs/queries"; + +interface Test { + description : string, + query : string, + result +} + +interface TestSet { + description : string, + tests : Test[] +} + +interface TestCollection { + description : string, + context : ({req:any}) => Promise<Context>, + tests : TestSet[] +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index 15eb334306f0c1ec4be59c9578c67b8818a0bc3a..f56440ecafc710c1d2bdaa484fe07415dca8e68c 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,6 @@ -require('dotenv').config() +require('dotenv').config(); -const { credentialsConfig } = require('../src/ldap/config'); +import { credentialsLdapConfig as credentialsConfig } from '../src/ldap/internal/config'; process.env.PORT = process.env.TEST_PORT || 3001; // The port is changed so that the test suite can be ran without interfering with a running server @@ -11,70 +11,70 @@ const chai = require('chai'); const expect = chai.expect; -const { GraphQLClient } = require('graphql-request') +const { GraphQLClient } = require('graphql-request'); -const apiEndpoint = `http://localhost:${process.env.PORT || 3001}/graphql`; +const apiEndpoint = `http://localhost:${process.env.PORT}/graphql`; const auth = { - username : credentialsConfig.dn.split("=")[1].split(",")[0], - password : credentialsConfig.passwd + username : credentialsConfig.dn.split("=")[1].split(",")[0], + password : credentialsConfig.passwd }; const testList = require('./testData').testList; describe('test server API', function () { - let client; + let client; - it('Should authentify and initialize the client', async function (){ + it('Should authentify and initialize the client', async function (){ - const tempClient = new GraphQLClient(apiEndpoint); - const query = ` - mutation { - login(username : "${auth.username}", password: "${auth.password}" ) - } - `; + const tempClient = new GraphQLClient(apiEndpoint); + const query = ` + mutation { + login(username : "${auth.username}", password: "${auth.password}" ) + } + `; - const res = await tempClient.request(query); + const res = await tempClient.request(query); - expect(res).to.have.property('login'); + expect(res).to.have.property('login'); - const token = res.login; + const token = res.login; - client = new GraphQLClient(apiEndpoint, { - headers: { - mode : 'cors', // Don't know what that does, isn't necessary. Worth looking into - credentials : 'include', // Same - authorization: `Bearer ${token}` - } - }); + client = new GraphQLClient(apiEndpoint, { + headers: { + mode : 'cors', // Don't know what that does, isn't necessary. Worth looking into + credentials : 'include', // Same + authorization: `Bearer ${token}` + } + }); - }); + }); - it('Should query all groups to test the client', async function (){ - const query = ` - query { - allGroups { - name - } - } - `; + it('Should query all groups to test the client', async function (){ + const query = ` + query { + allGroups { + name + } + } + `; - const res = await client.request(query); + const res = await client.request(query); - expect(res).to.have.property('allGroups'); - expect(res.allGroups).to.be.an('array'); - expect(res.allGroups).to.have.lengthOf.above(3); - }); + expect(res).to.have.property('allGroups'); + expect(res.allGroups).to.be.an('array'); + expect(res.allGroups).to.have.lengthOf.above(3); + }); - for(const test of testList){ + for(const test of testList){ - it(test.description, async function (){ - const res = await client.request(test.query); - expect(res).to.be.deep.equal(test.result); - }); + it(test.description, async function (){ + const res = await client.request(test.query); + expect(res).to.be.deep.equal(test.result); + }); - } + } }); diff --git a/test/testData.js b/test/testData.js index f5a32126ab5754bd0c519edec0c7aa56f1ff720b..00496169990173c6a9737237e29dcd0fc0c4cc89 100644 --- a/test/testData.js +++ b/test/testData.js @@ -12,72 +12,72 @@ exports.testList = [ { - query : `query{allGroups{name}}`, - result: { - "allGroups": [ - { "name": "BR" }, - { "name": "JTX" }, - { "name": "Faërix" }, - { "name": "Bôbar" }, - { "name": "Kès" }, - { "name": "Subaïsse" }, - { "name": "X-Broadway" }, - { "name": "Œnologie" }, - { "name": "Tribunes de l'X" }, - { "name": "X-Finance" }, - { "name": "ASK" } - ] - }, - description : "Should query all groups" + query : `query{allGroups{name}}`, + result: { + "allGroups": [ + { "name": "BR" }, + { "name": "JTX" }, + { "name": "Faërix" }, + { "name": "Bôbar" }, + { "name": "Kès" }, + { "name": "Subaïsse" }, + { "name": "X-Broadway" }, + { "name": "Œnologie" }, + { "name": "Tribunes de l'X" }, + { "name": "X-Finance" }, + { "name": "ASK" } + ] + }, + description : "Should query all groups" }, { - query : ` - query{group(uid : "br"){ - uid, - name, - website - }}`, - result : { - "group": { - "uid": "br", - "name": "BR", - "website": "br.binets.fr" - } - }, - description : "Should query a single group" + query : ` + query{group(uid : "br"){ + uid, + name, + website + }}`, + result : { + "group": { + "uid": "br", + "name": "BR", + "website": "br.binets.fr" + } + }, + description : "Should query a single group" }, { - query : `query{ - allMessages{ - id, - title, - content - } - }`, - result : { - "allMessages": [ - { - "id": "11", - "title": "Fête de la lune", - "content": "La fête de la lune, c'est bientôt dans le grand hall !" - }, - { - "id": "12", - "title": "Perm BR du mardi soir", - "content": "La perm' BR c'est maintenant!" - }, - { - "id": "13", - "title": "Formation Git", - "content": "Aujourd'hui, on va parler du système de contrôle de versions Git, qui est particulièrement utile pour travailler à plusieurs sur des projets informatiques: PSC, code de PI ou de projet de MAP, site binet, quoi que ce soit!" - }, - { - "id": "14", - "title": "Formation Web", - "content": "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !" - } - ] - }, - description : "Should fetch all messages" + query : `query{ + allMessages{ + id, + title, + content + } + }`, + result : { + "allMessages": [ + { + "id": "11", + "title": "Fête de la lune", + "content": "La fête de la lune, c'est bientôt dans le grand hall !" + }, + { + "id": "12", + "title": "Perm BR du mardi soir", + "content": "La perm' BR c'est maintenant!" + }, + { + "id": "13", + "title": "Formation Git", + "content": "Aujourd'hui, on va parler du système de contrôle de versions Git, qui est particulièrement utile pour travailler à plusieurs sur des projets informatiques: PSC, code de PI ou de projet de MAP, site binet, quoi que ce soit!" + }, + { + "id": "14", + "title": "Formation Web", + "content": "Envie d'apprendre à faire un site Web en Django ? Alors viens en amphi Sauvy ce jeudi à 20h !" + } + ] + }, + description : "Should fetch all messages" } - ]; \ No newline at end of file +]; \ No newline at end of file