reiso
Version:
537 lines • 37.9 kB
JavaScript
;
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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