UNPKG

reiso

Version:
537 lines 37.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const React = require("react"); const ws = require("ws"); const { spawn } = require('child_process'); const path = require('path'); const mobx_1 = require("mobx"); const mobx_react_1 = require("mobx-react"); const ApolloClient = require("apollo-client"); const ApolloLinkWS = require("apollo-link-ws"); const ApolloCache = require("apollo-cache-inmemory"); const apollo_server_1 = require("apollo-server"); const graphql_1 = require("graphql"); const apollo_fetch_1 = require("apollo-fetch"); const findFreePorts = require('find-free-ports'); const cheerio = require('cheerio'); require("fetch-everywhere"); require("reflect-metadata"); const Config_1 = require("../../Modules/Config"); const Log = require("../../Modules/Log"); const Error = require("../../Modules/Error"); const Server_1 = require("../../Server/Server"); const Router = require("../../Modules/Router"); const Query = require("../../Modules/Query"); const Hook = require("../../Modules/ServerHook"); const Model = require("../../Modules/Model"); exports.uploadType = new graphql_1.GraphQLScalarType({ name: 'Upload', serialize: value => { return value; }, parseValue: value => { return value; }, parseLiteral: ast => { if (ast.kind !== graphql_1.Kind.STRING) { throw new Error.LogError(null, 'debug', 'Upload can only parse strings got a: ' + ast.kind, "UP0", 422); } return ast.value; } }); let port; let portWS; let host = "127.0.0.1"; const server = new Server_1.Server(); describe("Module/Server", () => { let hook; function setTestGraphQLModel() { let TestInput = class TestInput { }; tslib_1.__decorate([ Query.InputField("integer", { nullable: true }), tslib_1.__metadata("design:type", Number) ], TestInput.prototype, "int", void 0); tslib_1.__decorate([ Query.InputField("float"), tslib_1.__metadata("design:type", Number) ], TestInput.prototype, "float", void 0); tslib_1.__decorate([ Query.InputField("string", { nullable: true }), tslib_1.__metadata("design:type", String) ], TestInput.prototype, "str", void 0); TestInput = tslib_1.__decorate([ Query.Input("TestInput") ], TestInput); let TestSubstructure = class TestSubstructure { }; tslib_1.__decorate([ Query.Field("integer"), tslib_1.__metadata("design:type", Number) ], TestSubstructure.prototype, "int", void 0); tslib_1.__decorate([ Query.Field("float"), tslib_1.__metadata("design:type", Number) ], TestSubstructure.prototype, "float", void 0); tslib_1.__decorate([ Query.Field("string"), tslib_1.__metadata("design:type", String) ], TestSubstructure.prototype, "str", void 0); TestSubstructure = tslib_1.__decorate([ Query.Structure("TestSubstructure") ], TestSubstructure); let TestResult = class TestResult { constructor() { this.int = 33; } async sub(str, sub, empty) { const res1 = new TestSubstructure(); const res2 = new TestSubstructure(); await Query.Publish('test', { test: sub.int }); res1.str = str; res2.float = sub.float; res2.int = sub.int; res2.str = sub.str; return [res1, res2]; } }; tslib_1.__decorate([ Query.Field("integer"), tslib_1.__metadata("design:type", Number) ], TestResult.prototype, "int", void 0); tslib_1.__decorate([ Query.Field("float"), tslib_1.__metadata("design:type", Number) ], TestResult.prototype, "float", void 0); tslib_1.__decorate([ Query.Field("string"), tslib_1.__metadata("design:type", String) ], TestResult.prototype, "str", void 0); tslib_1.__decorate([ Query.Field(type => TestSubstructure, { array: true }), tslib_1.__param(0, Query.Arg("string", 'str')), tslib_1.__param(1, Query.Arg(type => TestInput, 'sub')), tslib_1.__param(2, Query.Arg('integer', 'empty', { nullable: true })), tslib_1.__metadata("design:type", Function), tslib_1.__metadata("design:paramtypes", [String, TestInput, Number]), tslib_1.__metadata("design:returntype", Promise) ], TestResult.prototype, "sub", null); TestResult = tslib_1.__decorate([ Query.Structure("TestResult") ], TestResult); let Test = class Test { }; tslib_1.__decorate([ Query.Field("integer"), tslib_1.__metadata("design:type", Number) ], Test.prototype, "int", void 0); tslib_1.__decorate([ Query.Field("float"), tslib_1.__metadata("design:type", Number) ], Test.prototype, "float", void 0); tslib_1.__decorate([ Query.Field("string"), tslib_1.__metadata("design:type", String) ], Test.prototype, "str", void 0); tslib_1.__decorate([ Query.Field(type => TestResult, { substructure: true }), tslib_1.__metadata("design:type", TestResult) ], Test.prototype, "sub", void 0); Test = tslib_1.__decorate([ Query.Query("test"), Query.Structure("Test") ], Test); Query.Subscription(type => TestSubstructure, function (id, context) { if (hook) hook(); return Query.Subscribe('test', function (data) { return data && data.test === id; }); }, { name: 'test', args: [Query.SubscriptionArg('integer', 'id')] })(async function subscription(id, context, data) { const res = new TestSubstructure(); res.int = id; return res; }); } beforeAll(async () => { [port, portWS] = await findFreePorts(2); Config_1.setConfig({ default: { "logConsole": null, "logLogstash": null, "port": port, "portWS": portWS, "globalPort": port, "globalPortWS": portWS, "host": host, "graphiql": true, "translation": "./translation.json", "uploadDir": "./test/uploads/", "publicDir": "./test/public/", "defaultLanguage": "en", "languages": ["en", "ru"], "quotaLimit": 100, "maxFileSize": 50, "redisPubSub": { "Main": { "port": 6379, "host": "redis", "password": "" } } } }); process.env.MODE = 'server'; Log.init(); Log.LoggerManager.addLogger({ log(level, line) { console.error(level, line); }, getLevel() { return 'error'; } }); Router.DeclareHtml()(Router.withRouter(function html(props) { return React.createElement("div", null, props.children); })); }); beforeEach(async () => { Router.cleanRoutes(); Query.clearModel(); Hook.clearWebHook(); Model.clearModels(); }); afterEach(async () => { await server.stop(); }); it("start & render", async () => { Router.route('/*', data => { return React.createElement("div", { "data-test": "test" }, "Test"); }); await server.start(); let res = await fetch(`http://${host}:${port}/`); let body = await res.text(); let $ = cheerio.load(body, { decodeEntities: false }); expect($('[data-test=test]').text()).toBe('Test'); }); it("router", async () => { Router.route('/*', data => { return React.createElement("div", { "data-test": "test" }, "test"); }); await server.start(); let res = await fetch(`http://${host}:${port}/`); let body = await res.text(); let $ = cheerio.load(body, { decodeEntities: false }); expect($('[data-test=test]').text()).toBe('test'); }); it("mobx", async () => { let TestModel = class TestModel { constructor(initialState) { this.id = Math.random(); this.data = "test"; if (initialState) { this.id = initialState.id; this.data = initialState.data; } } toJson() { return { data: 'test' }; } }; tslib_1.__decorate([ mobx_1.observable, tslib_1.__metadata("design:type", Object) ], TestModel.prototype, "id", void 0); tslib_1.__decorate([ mobx_1.observable, tslib_1.__metadata("design:type", String) ], TestModel.prototype, "data", void 0); TestModel = tslib_1.__decorate([ Model.model('test'), tslib_1.__metadata("design:paramtypes", [Object]) ], TestModel); const Test = mobx_react_1.inject('test')(mobx_react_1.observer(function (props) { return React.createElement("div", { "data-test": "test" }, props.test.data); })); Router.route('/*', data => { return React.createElement(Test, null); }); await server.start(); let res = await fetch(`http://${host}:${port}/`); let body = await res.text(); let $ = cheerio.load(body, { decodeEntities: false }); expect($('[data-test=test]').text()).toBe('test'); }); it("graphql", async () => { setTestGraphQLModel(); await server.start(); const fetch = apollo_fetch_1.createApolloFetch({ uri: `http://${host}:${port}/graphql` }); let res = await fetch({ query: `query Test($str: String!, $sub: TestInput!) { test { int, str, sub { int, float, sub(str: $str, sub: $sub) { int, float, str } } } }`, variables: { str: "Hello", sub: { int: 12, float: 21.2, str: 'World' } } }); expect(JSON.stringify(res)).toBe(JSON.stringify(JSON.parse(JSON.stringify({ "data": { "test": { "int": null, "str": null, "sub": { "int": 33, "float": null, "sub": [ { "int": null, "float": null, "str": "Hello" }, { "int": 12, "float": 21.2, "str": "World" } ] } } } })))); }); it("webhook", async () => { const data = { test: 'Test' }; Hook.RegisterWebHook({ path: 'test' }, (params, body, context) => { expect(JSON.stringify(body)).toBe(JSON.stringify(data)); return data; }); Hook.RegisterWebHook({ path: 'authtest', isAuth: () => true, auth: (username, password, params, body, context) => username == 'test' && password == 'test' }, (params, body, context) => { expect(JSON.stringify(body)).toBe(JSON.stringify(data)); return data; }); await server.start(); let res = await fetch(`http://${host}:${port}/wh/test`, { method: 'POST', body: JSON.stringify(data), headers: { "Content-Type": "application/json" } }); let body = await res.text(); expect(body).toBe(JSON.stringify(data)); res = await fetch(`http://${host}:${port}/wh/authtest`, { method: 'POST', body: JSON.stringify(data), headers: { "Authorization": "Basic " + new Buffer('test' + ":" + 'test').toString("base64"), "Content-Type": "application/json" } }); body = await res.text(); expect(body).toBe(JSON.stringify(data)); res = await fetch(`http://${host}:${port}/wh/authtest`, { method: 'POST', body: JSON.stringify(data), headers: { "Authorization": "Basic " + new Buffer('test' + ":" + 'not').toString("base64"), "Content-Type": "application/json" } }); body = await res.text(); expect(body).toBe('Unauthorized'); }); it("websocket", async () => { setTestGraphQLModel(); await server.start(); const wsAddress = "ws://" + host + ":" + portWS + "/"; const context = {}; const wsLink = new ApolloLinkWS.WebSocketLink({ uri: wsAddress, webSocketImpl: ws, options: { reconnect: false, connectionParams: context } }); const cache = new ApolloCache.InMemoryCache(); const fetch = apollo_fetch_1.createApolloFetch({ uri: `http://${host}:${port}/graphql` }); let catched = false; await new Promise(async (r, e) => { const gqlClient = new ApolloClient.ApolloClient({ link: wsLink, cache, ssrMode: true, queryDeduplication: true, defaultOptions: { watchQuery: { fetchPolicy: 'cache-and-network', errorPolicy: 'ignore', }, query: { fetchPolicy: 'cache-and-network', errorPolicy: 'all', }, mutate: { errorPolicy: 'all' } } }); await new Promise(h => { hook = h; gqlClient.subscribe({ query: apollo_server_1.gql `subscription TestSub($id: Int!) { test(id: $id) { int, float, str } }`, variables: { id: 12 } }).subscribe(value => { catched = true; expect(JSON.stringify(value)).toBe(JSON.stringify({ "data": { "test": { "int": 12, "float": null, "str": null, "__typename": "TestSubstructure" } } })); r(); }, error => { e(error); }); }); const req = `query Test($str: String!, $sub: TestInput!) { test { int, str, sub { int, float, sub(str: $str, sub: $sub) { int, float, str } } } }`; await Promise.all([ await fetch({ query: req, variables: { str: "HelloIgnore", sub: { int: 10, float: 21.2, str: 'World' } } }), await fetch({ query: req, variables: { str: "Hello", sub: { int: 12, float: 21.2, str: 'World' } } }) ]); }); wsLink.subscriptionClient.client.close(); expect(catched).toBeTruthy(); }); it("upload", async () => { setTestGraphQLModel(); let catched = false; let UploadRoot = class UploadRoot { async do(fileId, context) { let file = context.files.find(f => f.fieldname == fileId); catched = true; expect(context.files.length).toBe(1); expect(file.originalname).toBe('test.txt'); } }; tslib_1.__decorate([ Query.Field("string", { name: "do" }), tslib_1.__param(0, Query.Arg(type => exports.uploadType, 'file')), tslib_1.__metadata("design:type", Function), tslib_1.__metadata("design:paramtypes", [String, Object]), tslib_1.__metadata("design:returntype", Promise) ], UploadRoot.prototype, "do", null); UploadRoot = tslib_1.__decorate([ Query.Mutation({ name: 'upload' }), Query.Structure('UploadRoot') ], UploadRoot); await server.start(); await new Promise((r, e) => { var cp = spawn('node_modules/.bin/cross-env', [`HOST_CONFIG=${JSON.stringify({ host, port, portWS })}`, 'node_modules/.bin/jest', '--config', 'browser.jest.json', "--testPathPattern", "src\\/Test\\/Browser\\/Upload\\.(ts?|tsx?)$"], { stdio: ['pipe'], cwd: path.resolve(__dirname, '../../..') }); cp.stdout.on('data', function (data) { console.log(data.toString()); }); cp.stderr.on('data', function (data) { console.log(data.toString()); }); cp.on('close', function (code) { if (code === 0) { r(); } else { e("Client testing has sent an error code: " + code); } }); }); expect(catched).toBeTruthy(); }, 20000); // TODO: Make a DDOS Test // it("ddos", async () => { // }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL1Rlc3QvU2VydmVyL1NlcnZlci50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0JBQStCO0FBQy9CLHlCQUEwQjtBQUMxQixNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBQzNDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUU3QiwrQkFBa0M7QUFDbEMsMkNBQThDO0FBQzlDLDhDQUE4QztBQUM5QywrQ0FBK0M7QUFDL0MscURBQXFEO0FBQ3JELGlEQUFvQztBQUNwQyxxQ0FBa0Q7QUFFbEQsK0NBQWlEO0FBQ2pELE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQ2pELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNuQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUM1Qiw0QkFBMEI7QUFFMUIsaURBQWlEO0FBQ2pELHlDQUF5QztBQUN6Qyw2Q0FBNkM7QUFFN0MsZ0RBQTZDO0FBQzdDLCtDQUErQztBQUMvQyw2Q0FBNkM7QUFDN0MsaURBQWlEO0FBQ2pELDZDQUE2QztBQUdoQyxRQUFBLFVBQVUsR0FBRyxJQUFJLDJCQUFpQixDQUFDO0lBQzVDLElBQUksRUFBRSxRQUFRO0lBQ2QsU0FBUyxFQUFFLEtBQUssQ0FBQyxFQUFFO1FBQ2YsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUNELFVBQVUsRUFBRSxLQUFLLENBQUMsRUFBRTtRQUNoQixPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBQ0QsWUFBWSxFQUFFLEdBQUcsQ0FBQyxFQUFFO1FBQ2hCLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxjQUFJLENBQUMsTUFBTSxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLElB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