Skip to content

Commit 3a92200

Browse files
add extra unit tests
1 parent be60779 commit 3a92200

File tree

2 files changed

+392
-28
lines changed

2 files changed

+392
-28
lines changed

test/unit/connection.test.ts

Lines changed: 269 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,34 @@ const emptyResponse = {
3333
rows: 0
3434
};
3535

36+
class MockConnection extends ConnectionV2 {
37+
updateParameters(params: Record<string, string>) {
38+
this.parameters = {
39+
...this.parameters,
40+
...params
41+
};
42+
}
43+
}
44+
45+
// A hack to allow updating connection parameters stored internally
46+
async function mockConnect(connectionOptions: ConnectionOptions) {
47+
const context = {
48+
logger: new Logger(),
49+
httpClient: new NodeHttpClient(),
50+
apiEndpoint
51+
};
52+
const queryFormatter = new QueryFormatter();
53+
const auth = new Authenticator(context, connectionOptions);
54+
const connection = new MockConnection(
55+
queryFormatter,
56+
context,
57+
connectionOptions
58+
);
59+
await auth.authenticate();
60+
await connection.resolveEngineEndpoint();
61+
return connection;
62+
}
63+
3664
function resetServerHandlers(server: any) {
3765
server.use(
3866
rest.post(`https://id.fake.firebolt.io/oauth/token`, (req, res, ctx) => {
@@ -420,34 +448,6 @@ INFO: SYNTAX_ERROR - Unexpected character at {"failingLine":42,"startOffset":120
420448
})
421449
);
422450

423-
class MockConnection extends ConnectionV2 {
424-
updateParameters(params: Record<string, string>) {
425-
this.parameters = {
426-
...this.parameters,
427-
...params
428-
};
429-
}
430-
}
431-
432-
// A hack to allow updating connection parameters stored internally
433-
async function mockConnect(connectionOptions: ConnectionOptions) {
434-
const context = {
435-
logger: new Logger(),
436-
httpClient: new NodeHttpClient(),
437-
apiEndpoint
438-
};
439-
const queryFormatter = new QueryFormatter();
440-
const auth = new Authenticator(context, connectionOptions);
441-
const connection = new MockConnection(
442-
queryFormatter,
443-
context,
444-
connectionOptions
445-
);
446-
await auth.authenticate();
447-
await connection.resolveEngineEndpoint();
448-
return connection;
449-
}
450-
451451
const connection = await mockConnect(connectionParams);
452452
connection.updateParameters({ param: "value" });
453453

@@ -462,6 +462,247 @@ INFO: SYNTAX_ERROR - Unexpected character at {"failingLine":42,"startOffset":120
462462
expect(searchParamsUsed.get("database")).toEqual("dummy");
463463
});
464464

465+
it("handles remove parameters header", async () => {
466+
const connectionParams: ConnectionOptions = {
467+
auth: {
468+
client_id: "dummy",
469+
client_secret: "dummy"
470+
},
471+
database: "dummy",
472+
engineName: "dummy",
473+
account: "my_account"
474+
};
475+
476+
let searchParamsUsed = new URLSearchParams();
477+
server.use(
478+
rest.post(`https://some_engine.com`, async (req, res, ctx) => {
479+
const body = await req.text();
480+
if (body.startsWith("SELECT 1")) {
481+
// First query - return with remove parameters header
482+
return res(
483+
ctx.json(selectOneResponse),
484+
ctx.set("Firebolt-Remove-Parameters", "param1,param2")
485+
);
486+
}
487+
if (body.startsWith("SELECT 2")) {
488+
searchParamsUsed = req.url.searchParams;
489+
return res(ctx.json(selectOneResponse));
490+
}
491+
})
492+
);
493+
494+
const connection = await mockConnect(connectionParams);
495+
connection.updateParameters({
496+
param1: "value1",
497+
param2: "value2",
498+
param3: "value3"
499+
});
500+
501+
// Execute query that triggers remove parameters header
502+
await connection.execute("SELECT 1");
503+
504+
// Execute another query to check parameters
505+
await connection.execute("SELECT 2");
506+
507+
expect(searchParamsUsed.get("param1")).toEqual(null);
508+
expect(searchParamsUsed.get("param2")).toEqual(null);
509+
expect(searchParamsUsed.get("param3")).toEqual("value3");
510+
expect(searchParamsUsed.get("database")).toEqual("dummy");
511+
});
512+
513+
it("handles remove parameters header with whitespace", async () => {
514+
const connectionParams: ConnectionOptions = {
515+
auth: {
516+
client_id: "dummy",
517+
client_secret: "dummy"
518+
},
519+
database: "dummy",
520+
engineName: "dummy",
521+
account: "my_account"
522+
};
523+
524+
let searchParamsUsed = new URLSearchParams();
525+
server.use(
526+
rest.post(`https://some_engine.com`, async (req, res, ctx) => {
527+
const body = await req.text();
528+
if (body.startsWith("SELECT 1")) {
529+
// Return with remove parameters header containing whitespace
530+
return res(
531+
ctx.json(selectOneResponse),
532+
ctx.set("Firebolt-Remove-Parameters", " param1 , param2 , param3 ")
533+
);
534+
}
535+
if (body.startsWith("SELECT 2")) {
536+
searchParamsUsed = req.url.searchParams;
537+
return res(ctx.json(selectOneResponse));
538+
}
539+
})
540+
);
541+
542+
const connection = await mockConnect(connectionParams);
543+
connection.updateParameters({
544+
param1: "value1",
545+
param2: "value2",
546+
param3: "value3",
547+
param4: "value4"
548+
});
549+
550+
// Execute query that triggers remove parameters header
551+
await connection.execute("SELECT 1");
552+
553+
// Execute another query to check parameters
554+
await connection.execute("SELECT 2");
555+
556+
expect(searchParamsUsed.get("param1")).toEqual(null);
557+
expect(searchParamsUsed.get("param2")).toEqual(null);
558+
expect(searchParamsUsed.get("param3")).toEqual(null);
559+
expect(searchParamsUsed.get("param4")).toEqual("value4");
560+
expect(searchParamsUsed.get("database")).toEqual("dummy");
561+
});
562+
563+
it("handles remove parameters header with non-existent parameters", async () => {
564+
const connectionParams: ConnectionOptions = {
565+
auth: {
566+
client_id: "dummy",
567+
client_secret: "dummy"
568+
},
569+
database: "dummy",
570+
engineName: "dummy",
571+
account: "my_account"
572+
};
573+
574+
let searchParamsUsed = new URLSearchParams();
575+
server.use(
576+
rest.post(`https://some_engine.com`, async (req, res, ctx) => {
577+
const body = await req.text();
578+
if (body.startsWith("SELECT 1")) {
579+
// Remove both existing and non-existent parameters
580+
return res(
581+
ctx.json(selectOneResponse),
582+
ctx.set(
583+
"Firebolt-Remove-Parameters",
584+
"existing_param,non_existent_param"
585+
)
586+
);
587+
}
588+
if (body.startsWith("SELECT 2")) {
589+
searchParamsUsed = req.url.searchParams;
590+
return res(ctx.json(selectOneResponse));
591+
}
592+
})
593+
);
594+
595+
const connection = await mockConnect(connectionParams);
596+
connection.updateParameters({
597+
existing_param: "value1",
598+
other_param: "value2"
599+
});
600+
601+
// Execute query that triggers remove parameters header
602+
await connection.execute("SELECT 1");
603+
604+
// Execute another query to check parameters
605+
await connection.execute("SELECT 2");
606+
607+
expect(searchParamsUsed.get("existing_param")).toEqual(null);
608+
expect(searchParamsUsed.get("non_existent_param")).toEqual(null);
609+
expect(searchParamsUsed.get("other_param")).toEqual("value2");
610+
expect(searchParamsUsed.get("database")).toEqual("dummy");
611+
});
612+
613+
it("handles remove parameters header with single parameter", async () => {
614+
const connectionParams: ConnectionOptions = {
615+
auth: {
616+
client_id: "dummy",
617+
client_secret: "dummy"
618+
},
619+
database: "dummy",
620+
engineName: "dummy",
621+
account: "my_account"
622+
};
623+
624+
let searchParamsUsed = new URLSearchParams();
625+
server.use(
626+
rest.post(`https://some_engine.com`, async (req, res, ctx) => {
627+
const body = await req.text();
628+
if (body.startsWith("SELECT 1")) {
629+
// Remove single parameter
630+
return res(
631+
ctx.json(selectOneResponse),
632+
ctx.set("Firebolt-Remove-Parameters", "transaction_id")
633+
);
634+
}
635+
if (body.startsWith("SELECT 2")) {
636+
searchParamsUsed = req.url.searchParams;
637+
return res(ctx.json(selectOneResponse));
638+
}
639+
})
640+
);
641+
642+
const connection = await mockConnect(connectionParams);
643+
connection.updateParameters({
644+
transaction_id: "tx_123",
645+
other_param: "value"
646+
});
647+
648+
// Execute query that triggers remove parameters header
649+
await connection.execute("SELECT 1");
650+
651+
// Execute another query to check parameters
652+
await connection.execute("SELECT 2");
653+
654+
expect(searchParamsUsed.get("transaction_id")).toEqual(null);
655+
expect(searchParamsUsed.get("other_param")).toEqual("value");
656+
expect(searchParamsUsed.get("database")).toEqual("dummy");
657+
});
658+
659+
it("handles empty remove parameters header", async () => {
660+
const connectionParams: ConnectionOptions = {
661+
auth: {
662+
client_id: "dummy",
663+
client_secret: "dummy"
664+
},
665+
database: "dummy",
666+
engineName: "dummy",
667+
account: "my_account"
668+
};
669+
670+
let searchParamsUsed = new URLSearchParams();
671+
server.use(
672+
rest.post(`https://some_engine.com`, async (req, res, ctx) => {
673+
const body = await req.text();
674+
if (body.startsWith("SELECT 1")) {
675+
// Empty remove parameters header
676+
return res(
677+
ctx.json(selectOneResponse),
678+
ctx.set("Firebolt-Remove-Parameters", "")
679+
);
680+
}
681+
if (body.startsWith("SELECT 2")) {
682+
searchParamsUsed = req.url.searchParams;
683+
return res(ctx.json(selectOneResponse));
684+
}
685+
})
686+
);
687+
688+
const connection = await mockConnect(connectionParams);
689+
connection.updateParameters({
690+
param1: "value1",
691+
param2: "value2"
692+
});
693+
694+
// Execute query that triggers empty remove parameters header
695+
await connection.execute("SELECT 1");
696+
697+
// Execute another query to check parameters
698+
await connection.execute("SELECT 2");
699+
700+
// All parameters should still be present
701+
expect(searchParamsUsed.get("param1")).toEqual("value1");
702+
expect(searchParamsUsed.get("param2")).toEqual("value2");
703+
expect(searchParamsUsed.get("database")).toEqual("dummy");
704+
});
705+
465706
it("handles set statements correctly", async () => {
466707
let searchParamsUsed = new URLSearchParams();
467708
server.use(

0 commit comments

Comments
 (0)