mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 10:23:34 +00:00
test for circular references
This commit is contained in:
parent
2528ae5637
commit
26fba9f4be
@ -45,4 +45,20 @@ describe('sortConnectArray', () => {
|
||||
'There was a problem connecting relation with id 1 at position {"after":2}. The relation with id 2 needs to be connected first.'
|
||||
);
|
||||
});
|
||||
|
||||
test('error with circular references', () => {
|
||||
const sortConnect = () =>
|
||||
sortConnectArray(
|
||||
[
|
||||
{ id: 2, position: { after: 1 } },
|
||||
{ id: 3, position: { after: 1 } },
|
||||
{ id: 1, position: { after: 3 } },
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
expect(sortConnect).toThrowError(
|
||||
'A circular reference was found in the connect array. One relation is trying to connect before/after another one that is trying to connect before/after it'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -44,47 +44,58 @@ const sortConnectArray = (connectArr, initialArr = [], strictSort = true) => {
|
||||
if (!needsSorting) return connectArr;
|
||||
|
||||
// Iterate over connectArr and populate sortedConnect
|
||||
connectArr.forEach((rel, idx) => {
|
||||
const pushRelation = (rel) => {
|
||||
sortedConnect.push(rel);
|
||||
relInArray[rel.id] = true;
|
||||
};
|
||||
try {
|
||||
connectArr.forEach((rel, idx) => {
|
||||
const pushRelation = (rel) => {
|
||||
sortedConnect.push(rel);
|
||||
relInArray[rel.id] = true;
|
||||
};
|
||||
|
||||
const computeRelation = (rel) => {
|
||||
const adjacentRelId = rel.position?.before || rel.position?.after;
|
||||
const computeRelation = (rel) => {
|
||||
const adjacentRelId = rel.position?.before || rel.position?.after;
|
||||
|
||||
// This connect has already been computed
|
||||
if (idx in computedIdx) return;
|
||||
// This connect has already been computed
|
||||
if (idx in computedIdx) return;
|
||||
|
||||
if (!adjacentRelId || relInArray[adjacentRelId]) {
|
||||
return pushRelation(rel);
|
||||
}
|
||||
if (!adjacentRelId || relInArray[adjacentRelId]) {
|
||||
return pushRelation(rel);
|
||||
}
|
||||
|
||||
// Look if id is referenced elsewhere in the array
|
||||
const adjacentRelIdx = firstSeen[adjacentRelId];
|
||||
if (adjacentRelIdx) {
|
||||
const adjacentRel = connectArr[adjacentRelIdx];
|
||||
// Mark adjacent relation idx as computed,
|
||||
// so it is not computed again later in the loop
|
||||
computedIdx[adjacentRelIdx] = true;
|
||||
computeRelation(adjacentRel);
|
||||
pushRelation(rel);
|
||||
} else if (strictSort) {
|
||||
// If we reach this point, it means that the adjacent relation is not in the connect array
|
||||
// and it is not in the database. This should not happen.
|
||||
throw new InvalidRelationError(
|
||||
`There was a problem connecting relation with id ${rel.id} at position ${JSON.stringify(
|
||||
rel.position
|
||||
)}. The relation with id ${adjacentRelId} needs to be connected first.`
|
||||
);
|
||||
} else {
|
||||
// We are in non-strict mode so we can push the relation.
|
||||
pushRelation({ id: rel.id, position: { end: true } });
|
||||
}
|
||||
};
|
||||
// Look if id is referenced elsewhere in the array
|
||||
const adjacentRelIdx = firstSeen[adjacentRelId];
|
||||
if (adjacentRelIdx) {
|
||||
const adjacentRel = connectArr[adjacentRelIdx];
|
||||
// Mark adjacent relation idx as computed,
|
||||
// so it is not computed again later in the loop
|
||||
computedIdx[adjacentRelIdx] = true;
|
||||
computeRelation(adjacentRel);
|
||||
pushRelation(rel);
|
||||
} else if (strictSort) {
|
||||
// If we reach this point, it means that the adjacent relation is not in the connect array
|
||||
// and it is not in the database. This should not happen.
|
||||
throw new InvalidRelationError(
|
||||
`There was a problem connecting relation with id ${rel.id} at position ${JSON.stringify(
|
||||
rel.position
|
||||
)}. The relation with id ${adjacentRelId} needs to be connected first.`
|
||||
);
|
||||
} else {
|
||||
// We are in non-strict mode so we can push the relation.
|
||||
pushRelation({ id: rel.id, position: { end: true } });
|
||||
}
|
||||
};
|
||||
|
||||
computeRelation(rel);
|
||||
});
|
||||
computeRelation(rel);
|
||||
});
|
||||
} catch (err) {
|
||||
// If it is a RangeError, there is a circular dependency in the connect array.
|
||||
if (err instanceof RangeError)
|
||||
throw new InvalidRelationError(
|
||||
'A circular reference was found in the connect array. ' +
|
||||
'One relation is trying to connect before/after another one that is trying to connect before/after it'
|
||||
);
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
return sortedConnect;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user