Skip to content

Commit fdfdb72

Browse files
author
Luke Melia
committed
Add realm-server tests for 'in' filter operator (postgres coverage)
Tests the 'in' filter via the _search HTTP endpoint against a postgres database, complementing the existing host tests that cover SQLite. Covers: multiple values, single value, empty array, null values, different fields, and negation with 'not'.
1 parent cef914f commit fdfdb72

1 file changed

Lines changed: 227 additions & 0 deletions

File tree

packages/realm-server/tests/realm-endpoints/search-test.ts

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,5 +920,232 @@ module(`realm-endpoints/${basename(__filename)}`, function () {
920920
});
921921
});
922922
});
923+
924+
module("'in' filter (postgres)", function () {
925+
let testRealm: Realm;
926+
let request: SuperTest<Test>;
927+
let realmHref: string;
928+
let searchPath: string;
929+
930+
function onRealmSetup(args: {
931+
testRealm: Realm;
932+
request: SuperTest<Test>;
933+
}) {
934+
testRealm = args.testRealm;
935+
request = args.request;
936+
let realmURL = new URL(testRealm.url);
937+
realmHref = realmURL.href;
938+
searchPath = `${realmURL.pathname.replace(/\/$/, '')}/_search`;
939+
}
940+
941+
function personType() {
942+
return {
943+
module: `${realmHref}person`,
944+
name: 'Person',
945+
};
946+
}
947+
948+
module('public readable realm', function (hooks) {
949+
setupPermissionedRealmCached(hooks, {
950+
permissions: {
951+
'*': ['read'],
952+
},
953+
realmURL: testRealmURLFor('in-test/'),
954+
fileSystem: {
955+
'person.gts': `
956+
import { contains, field, CardDef, Component } from 'https://cardstack.com/base/card-api';
957+
import StringField from 'https://cardstack.com/base/string';
958+
export class Person extends CardDef {
959+
static displayName = 'Person';
960+
@field firstName = contains(StringField);
961+
@field city = contains(StringField);
962+
@field cardTitle = contains(StringField, {
963+
computeVia: function (this: Person) {
964+
return this.firstName;
965+
},
966+
});
967+
static isolated = class Isolated extends Component<typeof this> {
968+
<template><h1><@fields.firstName /></h1></template>
969+
};
970+
}
971+
`,
972+
'mango.json': {
973+
data: {
974+
type: 'card',
975+
attributes: { firstName: 'Mango', city: 'Barksville' },
976+
meta: {
977+
adoptsFrom: { module: './person', name: 'Person' },
978+
},
979+
},
980+
},
981+
'vangogh.json': {
982+
data: {
983+
type: 'card',
984+
attributes: { firstName: 'Van Gogh', city: 'Barksville' },
985+
meta: {
986+
adoptsFrom: { module: './person', name: 'Person' },
987+
},
988+
},
989+
},
990+
'ringo.json': {
991+
data: {
992+
type: 'card',
993+
attributes: { firstName: 'Ringo', city: 'Waggington' },
994+
meta: {
995+
adoptsFrom: { module: './person', name: 'Person' },
996+
},
997+
},
998+
},
999+
},
1000+
onRealmSetup,
1001+
});
1002+
1003+
test(`can filter using 'in' with multiple values`, async function (assert) {
1004+
let response = await request
1005+
.post(searchPath)
1006+
.set('Accept', 'application/vnd.card+json')
1007+
.set('X-HTTP-Method-Override', 'QUERY')
1008+
.send({
1009+
filter: {
1010+
on: personType(),
1011+
in: { firstName: ['Mango', 'Ringo'] },
1012+
},
1013+
});
1014+
1015+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
1016+
assert.strictEqual(
1017+
response.body.meta.page.total,
1018+
2,
1019+
'total count is correct',
1020+
);
1021+
let ids = response.body.data.map((d: any) => d.id).sort();
1022+
assert.deepEqual(
1023+
ids,
1024+
[`${realmHref}mango`, `${realmHref}ringo`],
1025+
'correct cards returned',
1026+
);
1027+
});
1028+
1029+
test(`can filter using 'in' with a single value`, async function (assert) {
1030+
let response = await request
1031+
.post(searchPath)
1032+
.set('Accept', 'application/vnd.card+json')
1033+
.set('X-HTTP-Method-Override', 'QUERY')
1034+
.send({
1035+
filter: {
1036+
on: personType(),
1037+
in: { firstName: ['Mango'] },
1038+
},
1039+
});
1040+
1041+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
1042+
assert.strictEqual(
1043+
response.body.meta.page.total,
1044+
1,
1045+
'total count is correct',
1046+
);
1047+
assert.strictEqual(
1048+
response.body.data[0].id,
1049+
`${realmHref}mango`,
1050+
'correct card returned',
1051+
);
1052+
});
1053+
1054+
test(`can filter using 'in' with an empty array`, async function (assert) {
1055+
let response = await request
1056+
.post(searchPath)
1057+
.set('Accept', 'application/vnd.card+json')
1058+
.set('X-HTTP-Method-Override', 'QUERY')
1059+
.send({
1060+
filter: {
1061+
on: personType(),
1062+
in: { firstName: [] },
1063+
},
1064+
});
1065+
1066+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
1067+
assert.strictEqual(
1068+
response.body.meta.page.total,
1069+
0,
1070+
'returns no results for empty array',
1071+
);
1072+
});
1073+
1074+
test(`can filter using 'in' with null values`, async function (assert) {
1075+
let response = await request
1076+
.post(searchPath)
1077+
.set('Accept', 'application/vnd.card+json')
1078+
.set('X-HTTP-Method-Override', 'QUERY')
1079+
.send({
1080+
filter: {
1081+
on: personType(),
1082+
in: { firstName: ['Mango', null] },
1083+
},
1084+
});
1085+
1086+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
1087+
// Mango matches 'Mango', no cards have null firstName
1088+
assert.ok(
1089+
response.body.meta.page.total >= 1,
1090+
'returns at least the matching card',
1091+
);
1092+
let ids = response.body.data.map((d: any) => d.id);
1093+
assert.ok(
1094+
ids.includes(`${realmHref}mango`),
1095+
'Mango is in the results',
1096+
);
1097+
});
1098+
1099+
test(`can filter using 'in' on a different field`, async function (assert) {
1100+
let response = await request
1101+
.post(searchPath)
1102+
.set('Accept', 'application/vnd.card+json')
1103+
.set('X-HTTP-Method-Override', 'QUERY')
1104+
.send({
1105+
filter: {
1106+
on: personType(),
1107+
in: { city: ['Waggington'] },
1108+
},
1109+
});
1110+
1111+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
1112+
assert.strictEqual(
1113+
response.body.meta.page.total,
1114+
1,
1115+
'total count is correct',
1116+
);
1117+
assert.strictEqual(
1118+
response.body.data[0].id,
1119+
`${realmHref}ringo`,
1120+
'correct card returned',
1121+
);
1122+
});
1123+
1124+
test(`can negate an 'in' filter with 'not'`, async function (assert) {
1125+
let response = await request
1126+
.post(searchPath)
1127+
.set('Accept', 'application/vnd.card+json')
1128+
.set('X-HTTP-Method-Override', 'QUERY')
1129+
.send({
1130+
filter: {
1131+
on: personType(),
1132+
not: { in: { firstName: ['Mango', 'Ringo'] } },
1133+
},
1134+
});
1135+
1136+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
1137+
assert.strictEqual(
1138+
response.body.meta.page.total,
1139+
1,
1140+
'total count is correct',
1141+
);
1142+
assert.strictEqual(
1143+
response.body.data[0].id,
1144+
`${realmHref}vangogh`,
1145+
'correct card returned',
1146+
);
1147+
});
1148+
});
1149+
});
9231150
});
9241151
});

0 commit comments

Comments
 (0)