fix(content-releases): filter releases with entry attached (#19249)

* fix(content-releases): fix problem with filters of releases with entry not attached

* apply marks feedback
This commit is contained in:
Fernando Chávez 2024-01-18 16:26:59 +01:00 committed by GitHub
parent 053d9dad52
commit 2f7decb22b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 80 additions and 61 deletions

View File

@ -1,14 +1,16 @@
import releaseController from '../release';
const mockFindPage = jest.fn();
const mockFindManyForContentTypeEntry = jest.fn();
const mockFindManyWithContentTypeEntryAttached = jest.fn();
const mockFindManyWithoutContentTypeEntryAttached = jest.fn();
const mockCountActions = jest.fn();
jest.mock('../../utils', () => ({
getService: jest.fn(() => ({
findOne: jest.fn(() => ({ id: 1 })),
findPage: mockFindPage,
findManyForContentTypeEntry: mockFindManyForContentTypeEntry,
findManyWithContentTypeEntryAttached: mockFindManyWithContentTypeEntryAttached,
findManyWithoutContentTypeEntryAttached: mockFindManyWithoutContentTypeEntryAttached,
countActions: mockCountActions,
getContentTypesDataForActions: jest.fn(),
})),
@ -19,7 +21,7 @@ describe('Release controller', () => {
describe('findMany', () => {
it('should call findPage', async () => {
mockFindPage.mockResolvedValue({ results: [], pagination: {} });
mockFindManyForContentTypeEntry.mockResolvedValue([]);
mockFindManyWithContentTypeEntryAttached.mockResolvedValue([]);
const userAbility = {
can: jest.fn(),
};
@ -53,9 +55,9 @@ describe('Release controller', () => {
expect(mockFindPage).toHaveBeenCalled();
});
it('should call findManyForContentTypeEntry', async () => {
it('should call findManyWithoutContentTypeEntryAttached', async () => {
mockFindPage.mockResolvedValue({ results: [], pagination: {} });
mockFindManyForContentTypeEntry.mockResolvedValue([]);
mockFindManyWithContentTypeEntryAttached.mockResolvedValue([]);
const userAbility = {
can: jest.fn(),
};
@ -86,7 +88,7 @@ describe('Release controller', () => {
// @ts-expect-error partial context
await releaseController.findMany(ctx);
expect(mockFindManyForContentTypeEntry).toHaveBeenCalled();
expect(mockFindManyWithoutContentTypeEntryAttached).toHaveBeenCalled();
});
});
describe('create', () => {

View File

@ -40,9 +40,9 @@ const releaseController = {
const hasEntryAttached: GetContentTypeEntryReleases.Request['query']['hasEntryAttached'] =
typeof query.hasEntryAttached === 'string' ? JSON.parse(query.hasEntryAttached) : false;
const data = await releaseService.findManyForContentTypeEntry(contentTypeUid, entryId, {
hasEntryAttached,
});
const data = hasEntryAttached
? await releaseService.findManyWithContentTypeEntryAttached(contentTypeUid, entryId)
: await releaseService.findManyWithoutContentTypeEntryAttached(contentTypeUid, entryId);
ctx.body = { data };
} else {

View File

@ -279,8 +279,8 @@ describe('release service', () => {
});
});
describe('findManyForContentTypeEntry', () => {
it('should format the return value correctly when hasEntryAttached is true', async () => {
describe('findManyWithContentTypeEntryAttached', () => {
it('should format the return value correctly', async () => {
const strapiMock = {
...baseStrapiMock,
db: {
@ -294,12 +294,9 @@ describe('release service', () => {
// @ts-expect-error Ignore missing properties
const releaseService = createReleaseService({ strapi: strapiMock });
const releases = await releaseService.findManyForContentTypeEntry(
const releases = await releaseService.findManyWithContentTypeEntryAttached(
'api::contentType.contentType',
1,
{
hasEntryAttached: true,
}
1
);
expect(releases).toEqual([{ name: 'test release', action: { type: 'publish' } }]);

View File

@ -79,60 +79,80 @@ const createReleaseService = ({ strapi }: { strapi: LoadedStrapi }) => ({
});
},
async findManyForContentTypeEntry(
async findManyWithContentTypeEntryAttached(
contentTypeUid: GetContentTypeEntryReleases.Request['query']['contentTypeUid'],
entryId: GetContentTypeEntryReleases.Request['query']['entryId'],
{
hasEntryAttached,
}: { hasEntryAttached?: GetContentTypeEntryReleases.Request['query']['hasEntryAttached'] } = {
hasEntryAttached: false,
}
entryId: GetContentTypeEntryReleases.Request['query']['entryId']
) {
const whereActions = hasEntryAttached
? {
// Find all Releases where the content type entry is present
actions: {
target_type: contentTypeUid,
target_id: entryId,
},
}
: {
// Find all Releases where the content type entry is not present
$or: [
{
$not: {
actions: {
target_type: contentTypeUid,
target_id: entryId,
},
},
},
{
actions: null,
},
],
};
const populateAttachedAction = hasEntryAttached
? {
// Filter the action to get only the content type entry
actions: {
where: {
target_type: contentTypeUid,
target_id: entryId,
},
},
}
: {};
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
where: {
...whereActions,
actions: {
target_type: contentTypeUid,
target_id: entryId,
},
releasedAt: {
$null: true,
},
},
populate: {
...populateAttachedAction,
// Filter the action to get only the content type entry
actions: {
where: {
target_type: contentTypeUid,
target_id: entryId,
},
},
},
});
return releases.map((release) => {
if (release.actions?.length) {
const [actionForEntry] = release.actions;
// Remove the actions key to replace it with an action key
delete release.actions;
return {
...release,
action: actionForEntry,
};
}
return release;
});
},
async findManyWithoutContentTypeEntryAttached(
contentTypeUid: GetContentTypeEntryReleases.Request['query']['contentTypeUid'],
entryId: GetContentTypeEntryReleases.Request['query']['entryId']
) {
// We get the list of releases where the entry is present
const releasesRelated = await strapi.db.query(RELEASE_MODEL_UID).findMany({
where: {
releasedAt: {
$null: true,
},
actions: {
target_type: contentTypeUid,
target_id: entryId,
},
},
});
const releases = await strapi.db.query(RELEASE_MODEL_UID).findMany({
where: {
$or: [
{
id: {
$notIn: releasesRelated.map((release) => release.id),
},
},
{
actions: null,
},
],
releasedAt: {
$null: true,
},
},
});