Skip to content

Commit

Permalink
[Fix] Validate cloning as entity creation so field validations aren't…
Browse files Browse the repository at this point in the history
… skipped e.g. unique constraints (#20963)
  • Loading branch information
jhoward1994 authored Aug 9, 2024
1 parent d7fa025 commit fe88c78
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
7 changes: 3 additions & 4 deletions packages/core/strapi/src/services/entity-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,11 @@ const createDefaultImplementation = ({
}
const isDraft = contentTypesUtils.isDraft(entityToClone, model);

const validData = await entityValidator.validateEntityUpdate(
const validData = await entityValidator.validateEntityCreation(
model,
// Omit the id, the cloned entity id will be generated by the database
_.omit(_.merge(entityToClone, data), ['id']) as Partial<typeof data>,
{ isDraft },
entityToClone
_.omit(_.merge(entityToClone, data), ['id']),
{ isDraft }
);
const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));

Expand Down
64 changes: 64 additions & 0 deletions tests/e2e/tests/content-manager/cloning.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { test, expect } from '@playwright/test';
import { login } from '../../utils/login';
import { resetDatabaseAndImportDataFromPath } from '../../utils/dts-import';
import { findAndClose } from '../../utils/shared';
import { waitForRestart } from '../../utils/restart';

test.describe('Cloning', () => {
test.beforeEach(async ({ page }) => {
await resetDatabaseAndImportDataFromPath('with-admin.tar');
await page.goto('/admin');
await login({ page });
});

const CREATE_URL =
/\/admin\/content-manager\/collection-types\/api::article.article\/create(\?.*)?/;
const LIST_URL = /\/admin\/content-manager\/collection-types\/api::article.article(\?.*)?/;

test('A user should not be able to clone an entry of a content type that has a clashing unique field', async ({
page,
}) => {
/**
* Set up a unique field on the article content type
*/
await page.getByRole('link', { name: 'Content-Type Builder' }).click();
await page.getByRole('button', { name: 'Close' }).click();

await page.getByLabel('Edit title').click();
await page.getByRole('tab', { name: 'Advanced settings' }).click();
await page.getByLabel('Unique field').check();
await page.getByRole('button', { name: 'Finish' }).click();
await page.getByRole('button', { name: 'Save' }).click();
await waitForRestart(page);

await page.getByRole('link', { name: 'Content Manager' }).click();
await page.waitForURL(LIST_URL);

/**
* Create a new entry with a unique field
*/
await page.getByRole('link', { name: 'Create new entry' }).click();
await page.getByLabel('title(This value is common to all locales)').fill('unique');
await page.getByRole('button', { name: 'Save' }).click();
await findAndClose(page, 'Saved');

await page.getByRole('link', { name: 'Content Manager' }).click();
await page.waitForURL(LIST_URL);

/**
* Attempt to create a duplicate entry with the same unique field value
*/
await page.getByLabel('Duplicate item line 3').click();
await page.getByRole('link', { name: 'Create', exact: true }).click();
await page.waitForURL(CREATE_URL);
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByText('This attribute must be unique').first()).toBeVisible();

/**
* Update the unique field value to a new value
*/
await page.getByLabel('title(This value is common to all locales)').fill('Unique Update');
await page.getByRole('button', { name: 'Save' }).click();
await findAndClose(page, 'Saved');
});
});

0 comments on commit fe88c78

Please sign in to comment.