Skip to content

Commit ce53c3f

Browse files
author
Sylvestre Gug
committed
added mysql tests
1 parent 258733b commit ce53c3f

File tree

5 files changed

+223
-3
lines changed

5 files changed

+223
-3
lines changed

.env.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
NODE_ENV=test
2-
MYSQL_TEST_CREDENTIALS={"user":"root","host":"mysql","port":3306,"database":"mysql","ssl":"disabled"}
2+
MYSQL_CREDENTIALS=mysql://root@mysql:3306/mysql?sslMode=DISABLED
33
MSSQL_CREDENTIALS=Server=mssql,1433;Database=master;User Id=sa;Password=Pass@word;trustServerCertificate=true;

.env.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const MSSQL_CREDENTIALS = env("MSSQL_CREDENTIALS");
2+
export const MYSQL_CREDENTIALS = env("MYSQL_CREDENTIALS");
23
export const NODE_ENV = env("NODE_ENV");
34

45
function env(key, defaultValue) {

.eslintrc.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = {
1212
{
1313
files: ["*.test.js"],
1414
env: {
15-
jest: true
15+
mocha: true
1616
}
1717
}
1818
]

docker-compose.local.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ services:
44
mssql:
55
image: mcr.microsoft.com/azure-sql-edge
66
ports:
7-
- "1433:1433"
7+
- "1433:1433"
8+
9+
mysql:
10+
ports:
11+
- "3306:3306"

test/mysql.test.js

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import assert from "node:assert";
2+
import MockReq from "mock-req";
3+
import MockRes from "mock-res";
4+
import logger from "../middleware/logger.js";
5+
import mysql from "../lib/mysql.js";
6+
7+
import {MYSQL_CREDENTIALS} from "../.env.test.js";
8+
const index = logger(mysql(MYSQL_CREDENTIALS));
9+
10+
describe("MySQL", () => {
11+
describe("when checking", () => {
12+
it("should do MySQL credential check", async () => {
13+
const req = new MockReq({method: "POST", url: "/check"});
14+
const res = new MockRes();
15+
16+
try {
17+
await index(req, res);
18+
} catch (error) {
19+
assert.equal(
20+
/User has too permissive grants/.test(error.message),
21+
true
22+
);
23+
}
24+
});
25+
});
26+
27+
describe("when querying", () => {
28+
it("should resolves MySQL requests", async () => {
29+
const req = new MockReq({method: "POST", url: "/query"}).end({
30+
sql: `
31+
select c1
32+
from (select 'hello' as c1 union all select 2 as c1) as foo
33+
where c1 = ?`,
34+
params: ["hello"],
35+
});
36+
const res = new MockRes();
37+
await index(req, res);
38+
39+
const {data, schema} = res._getJSON();
40+
41+
assert.deepEqual(data, [{c1: "hello"}]);
42+
assert.deepEqual(schema, {
43+
type: "array",
44+
items: {
45+
type: "object",
46+
properties: {c1: {type: ["null", "string"]}},
47+
},
48+
});
49+
});
50+
51+
it("should handle MySQL errors", async () => {
52+
const req = new MockReq({method: "POST", url: "/query"}).end({
53+
sql: "SELECT * FROM users",
54+
});
55+
const res = new MockRes();
56+
57+
try {
58+
await index(req, res);
59+
} catch (error) {
60+
assert.equal(error.statusCode, 400);
61+
assert.equal(error.message, "Table 'mysql.users' doesn't exist");
62+
}
63+
});
64+
65+
it("should handle MySQL empty query", async () => {
66+
const req = new MockReq({method: "POST", url: "/query"}).end({
67+
sql: "",
68+
});
69+
const res = new MockRes();
70+
71+
try {
72+
await index(req, res);
73+
} catch (error) {
74+
assert.equal(error.statusCode, 400);
75+
assert.equal(error.message, "Query was empty");
76+
}
77+
});
78+
79+
it("should handle MySQL empty results", async () => {
80+
const req = new MockReq({method: "POST", url: "/query"}).end({
81+
sql: `SELECT 1 AS c1 LIMIT 0`,
82+
});
83+
const res = new MockRes();
84+
85+
await index(req, res);
86+
87+
const {data, schema} = res._getJSON();
88+
assert.deepEqual(data, []);
89+
assert.deepEqual(schema, {
90+
type: "array",
91+
items: {
92+
type: "object",
93+
properties: {c1: {type: ["null", "integer"], long: true}},
94+
},
95+
});
96+
});
97+
});
98+
99+
describe("when check the dataTypeSchema", () => {
100+
it("should provide the right MySQL types", async () => {
101+
const req = new MockReq({method: "POST", url: "/query"}).end({
102+
sql:
103+
"select 1 as c1, 3.14 as c2, 0xdeadbeef as c3, 'hello' as c4, DATE '2019-01-01' as c5, 1234567890 as c6",
104+
});
105+
const res = new MockRes();
106+
107+
await index(req, res);
108+
const {data, schema} = res._getJSON();
109+
assert.deepEqual(data, [
110+
{
111+
c1: 1,
112+
c2: 3.14,
113+
c3: {type: "Buffer", data: [222, 173, 190, 239]},
114+
c4: "hello",
115+
c5: "2019-01-01T00:00:00.000Z",
116+
c6: 1234567890,
117+
},
118+
]);
119+
assert.deepEqual(schema, {
120+
type: "array",
121+
items: {
122+
type: "object",
123+
properties: {
124+
c1: {type: ["null", "integer"], long: true},
125+
c2: {type: ["null", "number"], newdecimal: true},
126+
c3: {type: ["null", "object"], buffer: true},
127+
c4: {type: ["null", "string"]},
128+
c5: {type: ["null", "string"], date: true},
129+
c6: {type: ["null", "string"], bigint: true},
130+
},
131+
},
132+
});
133+
});
134+
});
135+
136+
describe("when streaming", () => {
137+
it("should handle MySQL stream requests", async () => {
138+
const req = new MockReq({method: "POST", url: "/query-stream"}).end({
139+
sql: `
140+
select c1
141+
from (select 'hello' as c1 union all select 2 as c1) as foo
142+
where c1 = ?`,
143+
params: ["hello"],
144+
});
145+
146+
const res = new MockRes();
147+
148+
await index(req, res);
149+
const response = res._getString();
150+
151+
assert.equal(
152+
response,
153+
JSON.stringify({
154+
type: "array",
155+
items: {
156+
type: "object",
157+
properties: {c1: {type: ["null", "string"]}},
158+
},
159+
}) +
160+
"\n" +
161+
JSON.stringify({c1: "hello"}) +
162+
"\n"
163+
);
164+
});
165+
166+
it("should handle MySQL stream errors", async () => {
167+
const req = new MockReq({method: "POST", url: "/query-stream"}).end({
168+
sql: "SELECT * FROM users",
169+
});
170+
const res = new MockRes();
171+
172+
try {
173+
await index(req, res);
174+
} catch (error) {
175+
assert.equal(error.statusCode, 400);
176+
assert.equal(error.message, "Table 'mysql.users' doesn't exist");
177+
}
178+
});
179+
180+
it("should hande MySQL stream empty query", async () => {
181+
const req = new MockReq({method: "POST", url: "/query-stream"}).end({
182+
sql: "",
183+
});
184+
const res = new MockRes();
185+
186+
try {
187+
await index(req, res);
188+
} catch (error) {
189+
assert.equal(error.statusCode, 400);
190+
assert.equal(error.message, "Query was empty");
191+
}
192+
});
193+
194+
it("MySQL stream empty results", async () => {
195+
const req = new MockReq({method: "POST", url: "/query-stream"}).end({
196+
sql: "SELECT 1 AS c1 LIMIT 0",
197+
});
198+
const res = new MockRes();
199+
200+
await index(req, res);
201+
const response = res._getString();
202+
203+
assert.equal(
204+
response,
205+
JSON.stringify({
206+
type: "array",
207+
items: {
208+
type: "object",
209+
properties: {c1: {type: ["null", "integer"], long: true}},
210+
},
211+
}) + "\n\n"
212+
);
213+
});
214+
});
215+
});

0 commit comments

Comments
 (0)