Add casting tests

This commit is contained in:
Alexandre Bodin 2021-10-27 14:59:13 +02:00
parent 674acadcc6
commit 4781d44ce8
2 changed files with 116 additions and 18 deletions

View File

@ -60,13 +60,17 @@ const castValue = (value, attribute) => {
return value;
};
const processAttributeWhere = (attribute, where, ctx) => {
const processAttributeWhere = (attribute, where, operator = '$eq') => {
if (_.isArray(where)) {
return where.map(sub => processAttributeWhere(attribute, sub, ctx));
return where.map(sub => processAttributeWhere(attribute, sub, operator));
}
if (!_.isPlainObject(where)) {
return castValue(where, attribute);
if (CAST_OPERATORS.includes(operator)) {
return castValue(where, attribute);
}
return where;
}
const filters = {};
@ -74,21 +78,11 @@ const processAttributeWhere = (attribute, where, ctx) => {
for (const key in where) {
const value = where[key];
if (isOperator(key)) {
if (!_.isPlainObject(value)) {
if (CAST_OPERATORS.includes(key)) {
filters[key] = castValue(value, attribute);
} else {
filters[key] = value;
}
continue;
}
filters[key] = processAttributeWhere(attribute, value, ctx);
continue;
if (!isOperator(key)) {
throw new Error(`Undefined attribute level operator ${key}`);
}
throw new Error(`Undefined attribute level operator ${key}`);
filters[key] = processAttributeWhere(attribute, value, key);
}
return filters;
@ -145,7 +139,7 @@ const processWhere = (where, ctx) => {
const attribute = meta.attributes[key];
if (!attribute) {
filters[qb.aliasColumn(key, alias)] = processAttributeWhere(null, value, ctx);
filters[qb.aliasColumn(key, alias)] = processAttributeWhere(null, value);
continue;
}
@ -179,7 +173,7 @@ const processWhere = (where, ctx) => {
const columnName = toColumnName(meta, key);
const aliasedColumnName = qb.aliasColumn(columnName, alias);
filters[aliasedColumnName] = processAttributeWhere(attribute, value, ctx);
filters[aliasedColumnName] = processAttributeWhere(attribute, value);
continue;
}

View File

@ -35,6 +35,9 @@ const product = {
big_rank: {
type: 'biginteger',
},
isChecked: {
type: 'boolean',
},
},
displayName: 'Product',
singularName: 'product',
@ -51,6 +54,7 @@ const productFixtures = [
decimal_field: 42.43,
rank: 42,
big_rank: '345678912983',
isChecked: true,
},
{
name: 'Product 2',
@ -59,6 +63,7 @@ const productFixtures = [
decimal_field: 91.22,
rank: 82,
big_rank: '926371623421',
isChecked: false,
},
{
name: 'Product 3',
@ -67,6 +72,7 @@ const productFixtures = [
decimal_field: 12.22,
rank: 91,
big_rank: '926372323421',
isChecked: true,
},
{
name: 'Product 4',
@ -75,6 +81,7 @@ const productFixtures = [
decimal_field: 12.22,
rank: 99,
big_rank: '999999999999',
isChecked: false,
},
{
name: 'Продукт 5, Product 5',
@ -83,6 +90,7 @@ const productFixtures = [
decimal_field: 142.43,
rank: 142,
big_rank: 345678912983,
isChecked: true,
},
];
@ -1376,4 +1384,100 @@ describe('Filtering API', () => {
expect(res.body.data).toEqual(expect.arrayContaining([data.product[4]]));
});
});
describe('Type casting', () => {
describe('Booleans', () => {
test.each(['1', 'true', true, 't'])('Cast truthy booleans %s', async val => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
filters: {
isChecked: val,
},
},
});
expect(res.body.data).toEqual(
expect.arrayContaining([data.product[0], data.product[2], data.product[4]])
);
});
test.each(['1', 'true', true, 't'])('Cast truthy booleans nested %s', async val => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
filters: {
isChecked: {
$eq: val,
},
},
},
});
expect(res.body.data).toEqual(
expect.arrayContaining([data.product[0], data.product[2], data.product[4]])
);
});
test.each(['1', 'true', true, 't'])('Cast truthy booleans in arrays %s', async val => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
filters: {
isChecked: {
$in: [val],
},
},
},
});
expect(res.body.data).toEqual(
expect.arrayContaining([data.product[0], data.product[2], data.product[4]])
);
});
test.each(['0', 'false', false, 'f'])('Cast truthy booleans %s', async val => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
filters: {
isChecked: val,
},
},
});
expect(res.body.data).toEqual(expect.arrayContaining([data.product[1], data.product[3]]));
});
test.each(['0', 'false', false, 'f'])('Cast truthy booleans nested %s', async val => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
filters: {
isChecked: {
$eq: val,
},
},
},
});
expect(res.body.data).toEqual(expect.arrayContaining([data.product[1], data.product[3]]));
});
test.each(['0', 'false', false, 'f'])('Cast truthy booleans in arrays %s', async val => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
filters: {
isChecked: {
$in: [val],
},
},
},
});
expect(res.body.data).toEqual(expect.arrayContaining([data.product[1], data.product[3]]));
});
});
});
});