Skip to content

Commit 918e1d9

Browse files
committed
add tests for api-gw preagg jobs endpoint
1 parent 6032ff9 commit 918e1d9

File tree

2 files changed

+94
-7
lines changed

2 files changed

+94
-7
lines changed

packages/cubejs-api-gateway/src/gateway.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ class ApiGateway {
856856
try {
857857
await this.assertApiScope('jobs', req?.context?.securityContext);
858858

859-
if (!query) {
859+
if (!query || Object.keys(query).length === 0) {
860860
throw new UserError('No job description provided');
861861
}
862862

@@ -906,11 +906,6 @@ class ApiGateway {
906906
): Promise<string[]> {
907907
let jobs: string[] = [];
908908

909-
// For the sake of type check, as contexts are checked in preAggregationsJobs()
910-
if (!selector.contexts) {
911-
return jobs;
912-
}
913-
914909
// There might be a few contexts but dateRange if present is still the same
915910
// so let's normalize it only once.
916911
// It's expected that selector.dateRange is provided in local time (without timezone)
@@ -919,7 +914,7 @@ class ApiGateway {
919914
const start = parseLocalDate([{ val: selector.dateRange[0] }], 'UTC');
920915
const end = parseLocalDate([{ val: selector.dateRange[1] }], 'UTC');
921916
if (!start || !end) {
922-
throw new Error(`Cannot parse selector date range ${selector.dateRange}`);
917+
throw new UserError(`Cannot parse selector date range ${selector.dateRange}`);
923918
}
924919
selector.dateRange = [start, end];
925920
}

packages/cubejs-api-gateway/test/index.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
DataSourceStorageMock,
1818
AdapterApiMock
1919
} from './mocks';
20+
import { ApiScopesTuple } from '../src/types/auth';
2021

2122
const logger = (type, message) => console.log({ type, ...message });
2223

@@ -61,6 +62,7 @@ async function createApiGateway(
6162

6263
process.env.NODE_ENV = 'unknown';
6364
const app = express();
65+
app.use(express.json());
6466
apiGateway.initApp(app);
6567

6668
return {
@@ -982,6 +984,96 @@ describe('API Gateway', () => {
982984
});
983985
});
984986

987+
describe('/v1/pre-aggregations/jobs', () => {
988+
const scheduledRefreshContextsFactory = () => ([
989+
{ securityContext: { foo: 'bar' } },
990+
{ securityContext: { bar: 'foo' } }
991+
]);
992+
993+
const scheduledRefreshTimeZonesFactory = () => (['UTC', 'America/Los_Angeles']);
994+
995+
const appPrepareFactory = async (scope: string[]) => {
996+
const playgroundAuthSecret = 'test12345';
997+
const { app } = await createApiGateway(
998+
new AdapterApiMock(),
999+
new DataSourceStorageMock(),
1000+
{
1001+
basePath: '/test',
1002+
playgroundAuthSecret,
1003+
refreshScheduler: () => new RefreshSchedulerMock(),
1004+
scheduledRefreshContexts: () => Promise.resolve(scheduledRefreshContextsFactory()),
1005+
scheduledRefreshTimeZones: scheduledRefreshTimeZonesFactory,
1006+
contextToApiScopes: () => Promise.resolve(<ApiScopesTuple>scope)
1007+
}
1008+
);
1009+
const token = generateAuthToken({ uid: 5, scope }, {}, playgroundAuthSecret);
1010+
const tokenUser = generateAuthToken({ uid: 5, scope }, {}, API_SECRET);
1011+
1012+
return { app, token, tokenUser };
1013+
};
1014+
1015+
test('no input', async () => {
1016+
const { app, tokenUser } = await appPrepareFactory(['graphql', 'data', 'meta', 'jobs']);
1017+
1018+
const req = request(app).post('/test/v1/pre-aggregations/jobs')
1019+
.set('Content-type', 'application/json')
1020+
.set('Authorization', `Bearer ${tokenUser}`);
1021+
1022+
const res = await req;
1023+
expect(res.status).toEqual(400);
1024+
expect(res.body.error).toEqual('No job description provided');
1025+
});
1026+
1027+
test('invalid input action', async () => {
1028+
const { app, tokenUser } = await appPrepareFactory(['graphql', 'data', 'meta', 'jobs']);
1029+
1030+
const req = request(app).post('/test/v1/pre-aggregations/jobs')
1031+
.set('Content-type', 'application/json')
1032+
.set('Authorization', `Bearer ${tokenUser}`)
1033+
.send({ action: 'patch' });
1034+
1035+
const res = await req;
1036+
expect(res.status).toEqual(400);
1037+
expect(res.body.error.includes('Invalid Job query format')).toBeTruthy();
1038+
});
1039+
1040+
test('invalid input date range', async () => {
1041+
const { app, tokenUser } = await appPrepareFactory(['graphql', 'data', 'meta', 'jobs']);
1042+
1043+
let req = request(app).post('/test/v1/pre-aggregations/jobs')
1044+
.set('Content-type', 'application/json')
1045+
.set('Authorization', `Bearer ${tokenUser}`)
1046+
.send({
1047+
action: 'post',
1048+
selector: {
1049+
contexts: [{ securityContext: {} }],
1050+
timezones: ['UTC', 'America/Los_Angeles'],
1051+
dateRange: ['invalid string', '2020-02-20']
1052+
}
1053+
});
1054+
1055+
let res = await req;
1056+
expect(res.status).toEqual(400);
1057+
expect(res.body.error.includes('Cannot parse selector date range')).toBeTruthy();
1058+
1059+
req = request(app).post('/test/v1/pre-aggregations/jobs')
1060+
.set('Content-type', 'application/json')
1061+
.set('Authorization', `Bearer ${tokenUser}`)
1062+
.send({
1063+
action: 'post',
1064+
selector: {
1065+
contexts: [{ securityContext: {} }],
1066+
timezones: ['UTC', 'America/Los_Angeles'],
1067+
dateRange: ['2020-02-20', 'invalid string']
1068+
}
1069+
});
1070+
1071+
res = await req;
1072+
expect(res.status).toEqual(400);
1073+
expect(res.body.error.includes('Cannot parse selector date range')).toBeTruthy();
1074+
});
1075+
});
1076+
9851077
describe('healtchecks', () => {
9861078
test('readyz (standalone)', async () => {
9871079
const { app, adapterApi } = await createApiGateway();

0 commit comments

Comments
 (0)