trader-server
Version:
OData server for testing strategies, simulating and real trading.
440 lines (408 loc) • 19.4 kB
text/typescript
/// <reference types="mocha" />
import { TestServer, Foobar } from './test.model';
import { ODataServer, NotImplementedError } from "../lib/index";
import { testFactory } from './server.spec'
import { Product, Category } from "./model/model";
import * as fs from "fs";
import * as path from "path";
import * as streamBuffers from "stream-buffers";
const { expect } = require("chai");
const extend = require("extend");
let categories = require("./model/categories");
let products = require("./model/products");
function createTestFactory(it) {
return function createTest(testcase: string, server: typeof ODataServer, command: string, compare: any, body?: any) {
it(`${testcase} (${command})`, () => {
let test = command.split(" ");
return server.execute(test.slice(1).join(" "), test[0], body).then((result) => {
expect(result).to.deep.equal(compare);
});
});
}
}
const createTest: any = createTestFactory(it);
createTest.only = createTestFactory(it.only);
describe("OData execute", () => {
testFactory(createTest);
it("should update foobar's foo property ", () => {
return TestServer.execute("/EntitySet(1)/foo", "PUT", {
foo: "PUT"
}).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/EntitySet(1)", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: {
"@odata.context": "http://localhost/$metadata#EntitySet/$entity",
"@odata.id": "http://localhost/EntitySet(1)",
"@odata.editLink": "http://localhost/EntitySet(1)",
id: 1,
foo: "PUT"
},
elementType: Foobar,
contentType: "application/json"
});
});
});
});
it("should delete foobar's foo property ", () => {
return TestServer.execute("/EntitySet(1)/foo", "DELETE").then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/EntitySet(1)", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: {
"@odata.context": "http://localhost/$metadata#EntitySet/$entity",
"@odata.id": "http://localhost/EntitySet(1)",
"@odata.editLink": "http://localhost/EntitySet(1)",
id: 1,
foo: null
},
elementType: Foobar,
contentType: "application/json"
});
});
});
});
it("should delta update foobar's foo property ", () => {
return TestServer.execute("/EntitySet(1)/foo", "PATCH", {
foo: "bar"
}).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/EntitySet(1)", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: {
"@odata.context": "http://localhost/$metadata#EntitySet/$entity",
"@odata.id": "http://localhost/EntitySet(1)",
"@odata.editLink": "http://localhost/EntitySet(1)",
id: 1,
foo: "bar"
},
elementType: Foobar,
contentType: "application/json"
});
});
});
});
it("should create product reference on category", () => {
return TestServer.execute("/Categories('578f2baa12eaebabec4af28e')/Products('578f2b8c12eaebabec4af242')/$ref", "POST").then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af242')/Category", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: extend({
"@odata.context": "http://localhost/$metadata#Categories/$entity"
}, categories.filter(category => category._id.toString() == "578f2baa12eaebabec4af28e").map(category => extend({
"@odata.id": `http://localhost/Categories('${category._id}')`
}, category))[0]
),
elementType: Category,
contentType: "application/json"
})
});
});
});
it("should delete product reference on category", () => {
return TestServer.execute("/Categories('578f2baa12eaebabec4af28e')/Products('578f2b8c12eaebabec4af242')/$ref", "DELETE").then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af242')/Category", "GET").then((result) => {
throw new Error("Category reference should be deleted.");
}, (err) => {
expect(err.name).to.equal("ResourceNotFoundError");
});;
});
});
it("should update product reference on category", () => {
return TestServer.execute("/Categories('578f2baa12eaebabec4af28d')/Products('578f2b8c12eaebabec4af242')/$ref", "PUT").then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af242')/Category", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: extend({
"@odata.context": "http://localhost/$metadata#Categories/$entity"
}, categories.filter(category => category._id.toString() == "578f2baa12eaebabec4af28d").map(category => extend({
"@odata.id": `http://localhost/Categories('${category._id}')`
}, category))[0]
),
elementType: Category,
contentType: "application/json"
})
});
});
});
it("should delete product reference on category by ref id", () => {
return TestServer.execute("/Categories('578f2baa12eaebabec4af28b')/Products/$ref?$id=http://localhost/Products('578f2b8c12eaebabec4af284')", "DELETE").then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af284')/Category", "GET").then((result) => {
throw new Error("Category reference should be deleted.");
}, (err) => {
expect(err.name).to.equal("ResourceNotFoundError");
});
});
});
it("should delta update product reference on category", () => {
return TestServer.execute("/Categories('578f2baa12eaebabec4af28b')/Products('578f2b8c12eaebabec4af284')/$ref", "PATCH").then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af284')/Category", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: extend({
"@odata.context": "http://localhost/$metadata#Categories/$entity"
}, categories.filter(category => category._id.toString() == "578f2baa12eaebabec4af28b").map(category => extend({
"@odata.id": `http://localhost/Categories('${category._id}')`
}, category))[0]
),
elementType: Category,
contentType: "application/json"
})
});
});
});
it("should create category reference on product", () => {
return TestServer.execute("/Products('578f2b8c12eaebabec4af286')/Category/$ref", "POST", {
"@odata.id": "http://localhost/Categories(categoryId='578f2baa12eaebabec4af28c')"
}).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af286')/Category", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: extend({
"@odata.context": "http://localhost/$metadata#Categories/$entity"
}, categories.filter(category => category._id.toString() == "578f2baa12eaebabec4af28c").map(category => extend({
"@odata.id": `http://localhost/Categories('${category._id}')`
}, category))[0]
),
elementType: Category,
contentType: "application/json"
})
});
});
});
it("should delete category reference on product", () => {
return TestServer.execute("/Products('578f2b8c12eaebabec4af286')/Category/$ref", "DELETE", {
"@odata.id": "http://localhost/Categories('578f2baa12eaebabec4af28c')"
}).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af286')/Category", "GET").then((result) => {
throw new Error("Category reference should be deleted.");
}, (err) => {
expect(err.name).to.equal("ResourceNotFoundError");
});
});
});
it("should update category reference on product", () => {
return TestServer.execute("/Products('578f2b8c12eaebabec4af286')/Category/$ref", "PUT", {
"@odata.id": "http://localhost/Categories(categoryId='578f2baa12eaebabec4af289')"
}).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
return TestServer.execute("/Products('578f2b8c12eaebabec4af286')/Category", "GET").then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: extend({
"@odata.context": "http://localhost/$metadata#Categories/$entity"
}, categories.filter(category => category._id.toString() == "578f2baa12eaebabec4af289").map(category => extend({
"@odata.id": `http://localhost/Categories('${category._id}')`
}, category))[0]
),
elementType: Category,
contentType: "application/json"
})
});
});
});
describe("Execute parameter is object", () => {
it("should update foobar's foo property ", () => {
let context: any = {};
context.url = '/EntitySet(1)/foo';
context.method = 'PUT';
return TestServer.execute(context, { foo: "PUT" }).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
let ctx: any = {};
ctx.url = '/EntitySet(1)';
ctx.method = 'GET';
return TestServer.execute(ctx).then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: {
"@odata.context": "http://localhost/$metadata#EntitySet/$entity",
"@odata.id": "http://localhost/EntitySet(1)",
"@odata.editLink": "http://localhost/EntitySet(1)",
id: 1,
foo: "PUT"
},
elementType: Foobar,
contentType: "application/json"
});
});
});
});
it("should delta update foobar's foo property ", () => {
let context: any = {};
context.url = '/EntitySet(1)/foo';
context.method = 'PATCH';
context.body = { foo: "bar" };
return TestServer.execute(context).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
let ctx: any = {};
ctx.url = '/EntitySet(1)';
ctx.method = 'GET';
return TestServer.execute(ctx).then((result) => {
expect(result).to.deep.equal({
statusCode: 200,
body: {
"@odata.context": "http://localhost/$metadata#EntitySet/$entity",
"@odata.id": "http://localhost/EntitySet(1)",
"@odata.editLink": "http://localhost/EntitySet(1)",
id: 1,
foo: "bar"
},
elementType: Foobar,
contentType: "application/json"
});
});
});
});
});
describe("Stream properties", () => {
it("stream property POST", () => {
let readableStrBuffer = new streamBuffers.ReadableStreamBuffer();
readableStrBuffer.put('tmp.png');
return TestServer.execute("/ImagesControllerEntitySet(1)/Data", "POST", readableStrBuffer).then((result) => {
readableStrBuffer.stop();
expect(result).to.deep.equal({
statusCode: 204
});
});
});
it("stream property GET", () => {
let writableStrBuffer = new streamBuffers.WritableStreamBuffer();
return TestServer.execute({
url: "/ImagesControllerEntitySet(1)/Data",
method: "GET",
response: writableStrBuffer
}).then(_ => {
expect(writableStrBuffer.getContentsAsString()).to.equal("tmp.png");
});
});
it("stream property with ODataStream POST", () => {
return TestServer.execute("/ImagesControllerEntitySet(1)/Data2", "POST", fs.createReadStream(path.join(__dirname, "fixtures", "logo_jaystack.png"))).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
expect(fs.readFileSync(path.join(__dirname, "fixtures", "logo_jaystack.png"))).to.deep.equal(fs.readFileSync(path.join(__dirname, "fixtures", "tmp.png")));
if (fs.existsSync(path.join(__dirname, "fixtures", "tmp.png"))) {
fs.unlinkSync(path.join(__dirname, "fixtures", "tmp.png"));
}
});
});
it("stream property with ODataStream GET", (done) => {
let tmp = fs.createWriteStream(path.join(__dirname, "fixtures", "tmp.png"))
tmp.on("open", _ => {
TestServer.execute({
url: "/ImagesControllerEntitySet(1)/Data2",
method: "GET",
response: tmp
}).then(_ => {
expect(fs.readFileSync(path.join(__dirname, "fixtures", "tmp.png"))).to.deep.equal(fs.readFileSync(path.join(__dirname, "fixtures", "logo_jaystack.png")));
try {
if (fs.existsSync(path.join(__dirname, "fixtures", "tmp.png"))) {
fs.unlinkSync(path.join(__dirname, "fixtures", "tmp.png"));
}
done();
} catch (err) {
done(err);
}
}, done);
}).on("error", done);
});
it("should return 204 after POST Data2 using generator function that yields stream", () => {
return TestServer.execute("/Images2ControllerEntitySet(1)/Data2", "POST", fs.createReadStream(path.join(__dirname, "fixtures", "logo_jaystack.png"))).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
expect(fs.readFileSync(path.join(__dirname, "fixtures", "logo_jaystack.png"))).to.deep.equal(fs.readFileSync(path.join(__dirname, "fixtures", "tmp.png")));
if (fs.existsSync(path.join(__dirname, "fixtures", "tmp.png"))) {
fs.unlinkSync(path.join(__dirname, "fixtures", "tmp.png"));
}
});
});
it("should return 200 after GET Data2 using generator function that yields stream", (done) => {
let tmp = fs.createWriteStream(path.join(__dirname, "fixtures", "tmp.png"))
tmp.on("open", _ => {
TestServer.execute({
url: "/Images2ControllerEntitySet(1)/Data2",
method: "GET",
response: tmp
}).then(_ => {
expect(fs.readFileSync(path.join(__dirname, "fixtures", "tmp.png"))).to.deep.equal(fs.readFileSync(path.join(__dirname, "fixtures", "logo_jaystack.png")));
try {
if (fs.existsSync(path.join(__dirname, "fixtures", "tmp.png"))) {
fs.unlinkSync(path.join(__dirname, "fixtures", "tmp.png"));
}
done();
} catch (err) {
done(err);
}
}, done);
}).on("error", done);
});
});
describe("Media entity", () => {
it("media entity POST", () => {
let readableStrBuffer = new streamBuffers.ReadableStreamBuffer();
readableStrBuffer.put('tmp.mp3');
return TestServer.execute("/MusicControllerEntitySet(1)/$value", "POST", readableStrBuffer).then((result) => {
expect(result).to.deep.equal({
statusCode: 204
});
});
});
});
describe("Not implemented error", () => {
it("should return not implemented error", () => {
return TestServer.execute("/EntitySet", "GET").then(() => {
try {
throw new NotImplementedError();
} catch (err) {
expect(err.message).to.equal("Not implemented.");
}
});
});
});
describe("Non existent entity", () => {
it('should return cannot read property node error', () => {
return TestServer.execute("/NonExistent", "GET")
.then((result) => {})
.catch(err => {
expect(err.message).to.equal("Cannot read property 'node' of undefined");
});
});
});
});