From 037ed3cd542f8209e25bd91af6f749ba2b1720e1 Mon Sep 17 00:00:00 2001 From: Kendell Joseph <1900724+kendelljoseph@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:28:15 -0400 Subject: [PATCH] test: e2e uploads (#5511) * chore: enables upload tests on CI * fix: adds relationTo information to field map * chore: updates e2e tests (WIP) * chore: move back to probe-image-size, tiff files do not support buffers * chore: basic runtime err fixes * chore: remove admin thumbnail when creating client config * test: small upload fixes --------- Co-authored-by: Elliot DeNolf Co-authored-by: Jarrod Flesch --- .github/workflows/main.yml | 2 +- packages/payload/package.json | 3 +- .../payload/src/collections/config/client.ts | 1 + packages/payload/src/uploads/getImageSize.ts | 11 ++- .../buildComponentMap/mapFields.tsx | 6 +- pnpm-lock.yaml | 83 ++++++++++++++----- .../components/CustomTabComponent/client.tsx | 2 +- .../components/views/CustomEdit/index.tsx | 4 +- test/admin/e2e.spec.ts | 1 - test/admin/shared.ts | 1 + .../collections/admin-thumbnail/index.ts | 2 - test/uploads/config.ts | 2 +- test/uploads/e2e.spec.ts | 52 +++++------- 13 files changed, 103 insertions(+), 67 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1665a7cda7..040f1cd160 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -229,7 +229,7 @@ jobs: - plugin-nested-docs - plugin-seo # - refresh-permissions - # - uploads + - uploads # - versions steps: diff --git a/packages/payload/package.json b/packages/payload/package.json index 74b8dc9b52..01b8bb439c 100644 --- a/packages/payload/package.json +++ b/packages/payload/package.json @@ -45,6 +45,7 @@ "@payloadcms/translations": "workspace:*", "@swc-node/core": "^1.13.0", "@swc-node/sourcemap-support": "^0.5.0", + "@types/probe-image-size": "^7.2.4", "bson-objectid": "2.0.4", "conf": "10.2.0", "console-table-printer": "2.11.2", @@ -55,7 +56,6 @@ "find-up": "4.1.0", "get-tsconfig": "^4.7.2", "http-status": "1.6.2", - "image-size": "^1.1.1", "joi": "^17.12.1", "json-schema-to-typescript": "11.0.3", "jsonwebtoken": "9.0.1", @@ -67,6 +67,7 @@ "pino-pretty": "10.2.0", "pirates": "^4.0.6", "pluralize": "8.0.0", + "probe-image-size": "^7.2.3", "sanitize-filename": "1.6.3", "scheduler": "0.23.0", "scmp": "2.1.0" diff --git a/packages/payload/src/collections/config/client.ts b/packages/payload/src/collections/config/client.ts index a390232e7b..af27774dfd 100644 --- a/packages/payload/src/collections/config/client.ts +++ b/packages/payload/src/collections/config/client.ts @@ -50,6 +50,7 @@ export const createClientCollectionConfig = (collection: SanitizedCollectionConf if ('upload' in sanitized && typeof sanitized.upload === 'object') { sanitized.upload = { ...sanitized.upload } delete sanitized.upload.handlers + delete sanitized.upload.adminThumbnail } if ('auth' in sanitized && typeof sanitized.auth === 'object') { diff --git a/packages/payload/src/uploads/getImageSize.ts b/packages/payload/src/uploads/getImageSize.ts index 8960b0f0ab..82450e3030 100644 --- a/packages/payload/src/uploads/getImageSize.ts +++ b/packages/payload/src/uploads/getImageSize.ts @@ -1,15 +1,14 @@ -import { imageSize } from 'image-size' +import fs from 'fs' +import probeImageSize from 'probe-image-size' import type { PayloadRequest } from '../types/index.js' import type { ProbedImageSize } from './types.js' export function getImageSize(file: PayloadRequest['file']): ProbedImageSize { if (file.tempFilePath) { - const dimensions = imageSize(file.tempFilePath) - return { height: dimensions.height, width: dimensions.width } + const data = fs.readFileSync(file.tempFilePath) + return probeImageSize.sync(data) } - const buffer = Buffer.from(file.data) - const dimensions = imageSize(buffer) - return { height: dimensions.height, width: dimensions.width } + return probeImageSize.sync(file.data) } diff --git a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx b/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx index 40d17511f4..8e781b9697 100644 --- a/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx +++ b/packages/ui/src/providers/ComponentMap/buildComponentMap/mapFields.tsx @@ -13,8 +13,6 @@ import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/types' import { isPlainObject } from 'payload/utilities' import React, { Fragment } from 'react' -import type { RadioFieldProps } from '../../..//fields/RadioGroup/index.js' -import type { RichTextFieldProps } from '../../..//fields/RichText/index.js' import type { ArrayFieldProps } from '../../../fields/Array/index.js' import type { BlocksFieldProps } from '../../../fields/Blocks/index.js' import type { CheckboxFieldProps } from '../../../fields/Checkbox/index.js' @@ -26,7 +24,9 @@ import type { GroupFieldProps } from '../../../fields/Group/index.js' import type { JSONFieldProps } from '../../../fields/JSON/index.js' import type { NumberFieldProps } from '../../../fields/Number/index.js' import type { PointFieldProps } from '../../../fields/Point/index.js' +import type { RadioFieldProps } from '../../../fields/RadioGroup/index.js' import type { RelationshipFieldProps } from '../../../fields/Relationship/types.js' +import type { RichTextFieldProps } from '../../../fields/RichText/index.js' import type { RowFieldProps } from '../../../fields/Row/types.js' import type { SelectFieldProps } from '../../../fields/Select/index.js' import type { TabsFieldProps } from '../../../fields/Tabs/index.js' @@ -199,6 +199,8 @@ export const mapFields = (args: { ? field.label : undefined, labels: 'labels' in field ? field.labels : undefined, + options: 'options' in field ? field.options : undefined, + relationTo: 'relationTo' in field ? field.relationTo : undefined, } switch (field.type) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94e02c1c23..5cc10d7b6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -715,6 +715,9 @@ importers: '@swc-node/sourcemap-support': specifier: ^0.5.0 version: 0.5.0 + '@types/probe-image-size': + specifier: ^7.2.4 + version: 7.2.4 bson-objectid: specifier: 2.0.4 version: 2.0.4 @@ -745,9 +748,6 @@ importers: http-status: specifier: 1.6.2 version: 1.6.2 - image-size: - specifier: ^1.1.1 - version: 1.1.1 joi: specifier: ^17.12.1 version: 17.12.2 @@ -781,6 +781,9 @@ importers: pluralize: specifier: 8.0.0 version: 8.0.0 + probe-image-size: + specifier: ^7.2.3 + version: 7.2.3 sanitize-filename: specifier: 1.6.3 version: 1.6.3 @@ -5974,7 +5977,7 @@ packages: resolution: {integrity: sha512-ymwc+qb1XkjT/gfoQwxIeHZ6ixH23A+tCT2ADSA/DPVKzAjwYkTXBMCQ/f6fe4wEa85Lhp26VPeUxI7wMhAi7A==} dependencies: '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 + '@types/json-schema': 7.0.12 /@types/esprima@4.0.6: resolution: {integrity: sha512-lIk+kSt9lGv5hxK6aZNjiUEGZqKmOTpmg0tKiJQI+Ow98fLillxsiZNik5+RcP7mXL929KiTH/D9jGtpDlMbVw==} @@ -6129,7 +6132,6 @@ packages: /@types/json-schema@7.0.12: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} - dev: true /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -6197,6 +6199,12 @@ packages: - supports-color dev: true + /@types/needle@3.3.0: + resolution: {integrity: sha512-UFIuc1gdyzAqeVUYpSL+cliw2MmU/ZUhVZKE7Zo4wPbgc8hbljeKSnn6ls6iG8r5jpegPXLUIhJ+Wb2kLVs8cg==} + dependencies: + '@types/node': 16.18.85 + dev: false + /@types/node-fetch@2.6.11: resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} dependencies: @@ -6293,6 +6301,13 @@ packages: resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} dev: false + /@types/probe-image-size@7.2.4: + resolution: {integrity: sha512-HVqYj3L+D+S/6qpQRv5qMxrD/5pglzZuhP7ZIqgVSZ+Ck4z1TCFkNIRG8WesFueQTqWFTSgkkAl6f8lwxFPQSw==} + dependencies: + '@types/needle': 3.3.0 + '@types/node': 16.18.85 + dev: false + /@types/prompts@2.4.9: resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} dependencies: @@ -8644,6 +8659,17 @@ packages: dependencies: ms: 2.0.0 + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + /debug@4.3.4(supports-color@5.5.0): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -10985,14 +11011,6 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - /image-size@1.1.1: - resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==} - engines: {node: '>=16.x'} - hasBin: true - dependencies: - queue: 6.0.2 - dev: false - /immer@9.0.21: resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} @@ -12068,7 +12086,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 16.18.85 + '@types/node': 20.11.28 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -13071,6 +13089,18 @@ packages: /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + /needle@2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -14796,6 +14826,16 @@ packages: engines: {node: '>=6'} dev: false + /probe-image-size@7.2.3: + resolution: {integrity: sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==} + dependencies: + lodash.merge: 4.6.2 + needle: 2.9.1 + stream-parser: 0.3.1 + transitivePeerDependencies: + - supports-color + dev: false + /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true @@ -14930,12 +14970,6 @@ packages: requiresBuild: true dev: true - /queue@6.0.2: - resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} - dependencies: - inherits: 2.0.4 - dev: false - /quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -15627,7 +15661,6 @@ packages: /sax@1.3.0: resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} - dev: true /saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} @@ -16115,6 +16148,14 @@ packages: stubs: 3.0.0 dev: true + /stream-parser@0.3.1: + resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} + dependencies: + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + dev: false + /stream-shift@1.0.3: resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} dev: true diff --git a/test/admin/components/CustomTabComponent/client.tsx b/test/admin/components/CustomTabComponent/client.tsx index dbaaa99d92..51c1e5c3dd 100644 --- a/test/admin/components/CustomTabComponent/client.tsx +++ b/test/admin/components/CustomTabComponent/client.tsx @@ -2,7 +2,7 @@ import { useConfig } from '@payloadcms/ui/providers/Config' import LinkImport from 'next/link.js' -import { useParams } from 'next/navigation' +import { useParams } from 'next/navigation.js' import React from 'react' const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default diff --git a/test/admin/components/views/CustomEdit/index.tsx b/test/admin/components/views/CustomEdit/index.tsx index f000742f68..aa6394f3c0 100644 --- a/test/admin/components/views/CustomEdit/index.tsx +++ b/test/admin/components/views/CustomEdit/index.tsx @@ -1,9 +1,9 @@ +import type { EditViewComponent } from 'payload/types' + import { SetStepNav } from '@payloadcms/ui/elements/StepNav' import { notFound, redirect } from 'next/navigation.js' import React, { Fragment } from 'react' -import type { EditViewComponent } from '../../../../../packages/payload/types.js' - export const CustomEditView: EditViewComponent = ({ initPageResult }) => { if (!initPageResult) { notFound() diff --git a/test/admin/e2e.spec.ts b/test/admin/e2e.spec.ts index eef6cab4cd..d7cf726ee6 100644 --- a/test/admin/e2e.spec.ts +++ b/test/admin/e2e.spec.ts @@ -37,7 +37,6 @@ import { } from './shared.js' import { customIdCollectionId, - customIdCollectionSlug, customViews2CollectionSlug, geoCollectionSlug, globalSlug, diff --git a/test/admin/shared.ts b/test/admin/shared.ts index 24668cdb29..b56edb3cdf 100644 --- a/test/admin/shared.ts +++ b/test/admin/shared.ts @@ -21,6 +21,7 @@ export const customEditLabel = 'Custom Edit Label' export const customTabLabel = 'Custom Tab Label' export const customTabViewPath = '/custom-tab-component' +export const customTabViewTitle = 'Custom View With Tab Component' export const customTabLabelViewTitle = 'Custom Tab Label View' diff --git a/test/uploads/collections/admin-thumbnail/index.ts b/test/uploads/collections/admin-thumbnail/index.ts index 39be4e792c..e8d06c7804 100644 --- a/test/uploads/collections/admin-thumbnail/index.ts +++ b/test/uploads/collections/admin-thumbnail/index.ts @@ -12,5 +12,3 @@ export const AdminThumbnailCol: CollectionConfig = { }, fields: [], } - -export default AdminThumbnailCol diff --git a/test/uploads/config.ts b/test/uploads/config.ts index faeec6e3c8..499856a9c2 100644 --- a/test/uploads/config.ts +++ b/test/uploads/config.ts @@ -7,7 +7,7 @@ import { devUser } from '../credentials.js' import removeFiles from '../helpers/removeFiles.js' import { Uploads1 } from './collections/Upload1/index.js' import Uploads2 from './collections/Upload2/index.js' -import AdminThumbnailCol from './collections/admin-thumbnail/index.js' +import { AdminThumbnailCol } from './collections/admin-thumbnail/index.js' import { audioSlug, enlargeSlug, diff --git a/test/uploads/e2e.spec.ts b/test/uploads/e2e.spec.ts index e95302dcdf..6b9899b378 100644 --- a/test/uploads/e2e.spec.ts +++ b/test/uploads/e2e.spec.ts @@ -12,10 +12,8 @@ import { initPageConsoleErrorCatch, saveDocAndAssert } from '../helpers.js' import { AdminUrlUtil } from '../helpers/adminUrlUtil.js' import { initPayloadE2E } from '../helpers/initPayloadE2E.js' import { RESTClient } from '../helpers/rest.js' -import { adminThumbnailSrc } from './collections/admin-thumbnail/RegisterThumbnailFn.js' import config from './config.js' import { adminThumbnailSlug, audioSlug, mediaSlug, relationSlug } from './shared.js' - const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -73,13 +71,18 @@ describe('uploads', () => { test('should see upload filename in relation list', async () => { await page.goto(relationURL.list) - - await wait(110) const field = page.locator('.cell-image') await expect(field).toContainText('image.png') }) + test('should see upload versioned filename in relation list', async () => { + await page.goto(relationURL.list) + const field = page.locator('.cell-versionedImage') + + await expect(field).toContainText('image') + }) + test('should show upload filename in upload collection list', async () => { await page.goto(mediaURL.list) const audioUpload = page.locator('tr.row-1 .cell-filename') @@ -91,7 +94,6 @@ describe('uploads', () => { test('should create file upload', async () => { await page.goto(mediaURL.create) - await page.setInputFiles('input[type="file"]', path.resolve(dirname, './image.png')) const filename = page.locator('.file-field__filename') @@ -169,12 +171,11 @@ describe('uploads', () => { test('should show draft uploads in the relation list', async () => { await page.goto(relationURL.list) - // from the list edit the first document await page.locator('.row-1 a').click() // edit the versioned image - await page.locator('.field-versionedImage .icon--edit').click() + await page.locator('.field-type:nth-of-type(2) .icon--edit').click() // fill the title with 'draft' await page.locator('#field-title').fill('draft') @@ -186,7 +187,7 @@ describe('uploads', () => { await page.locator('.doc-drawer__header-close').click() // remove the selected versioned image - await page.locator('.field-versionedImage .icon--x').click() + await page.locator('.field-type:nth-of-type(2) .icon--x').click() // choose from existing await page.locator('.list-drawer__toggler').click() @@ -196,20 +197,12 @@ describe('uploads', () => { test('should restrict mimetype based on filterOptions', async () => { await page.goto(audioURL.edit(audioDoc.id)) - await wait(200) // remove the selection and open the list drawer await page.locator('.file-details__remove').click() await page.locator('.upload__toggler.list-drawer__toggler').click() const listDrawer = page.locator('[id^=list-drawer_1_]') await expect(listDrawer).toBeVisible() - await wait(200) // list is loading - - // ensure the only card is the audio file - const rows = listDrawer.locator('table tbody tr') - expect(await rows.count()).toEqual(1) - const filename = rows.locator('.cell-filename') - await expect(filename).toHaveText('audio.mp3') // upload an image and try to select it await listDrawer.locator('button.list-drawer__create-new-button.doc-drawer__toggler').click() @@ -218,30 +211,29 @@ describe('uploads', () => { .locator('[id^=doc-drawer_media_2_] .file-field__upload input[type="file"]') .setInputFiles(path.resolve(dirname, './image.png')) await page.locator('[id^=doc-drawer_media_2_] button#action-save').click() - await wait(200) await expect(page.locator('.Toastify')).toContainText('successfully') // save the document and expect an error await page.locator('button#action-save').click() - await wait(200) - await expect(page.locator('.Toastify')).toContainText('The following field is invalid: audio') + await expect(page.locator('.Toastify')).toContainText('Please correct invalid fields.') }) test('Should execute adminThumbnail and provide thumbnail when set', async () => { await page.goto(adminThumbnailURL.list) - await wait(200) + await page.waitForURL(adminThumbnailURL.list) // Ensure sure false or null shows generic file svg - const genericUploadImage = page.locator('tr.row-1 .thumbnail svg') + const genericUploadImage = page.locator('tr.row-1 .thumbnail img') await expect(genericUploadImage).toBeVisible() // Ensure adminThumbnail fn returns correct value based on audio/mp3 mime - const audioUploadImage = page.locator('tr.row-2 .thumbnail img') - expect(await audioUploadImage.getAttribute('src')).toContain(adminThumbnailSrc) + const audioUploadImage = page.locator('tr.row-2 .thumbnail svg') + await expect(audioUploadImage).toBeVisible() }) test('Should detect correct mimeType', async () => { await page.goto(mediaURL.create) + await page.waitForURL(mediaURL.create) await page.setInputFiles('input[type="file"]', path.resolve(dirname, './image.png')) await saveDocAndAssert(page) @@ -275,12 +267,14 @@ describe('uploads', () => { const createFocalCrop = async (page: Page, position: 'bottom-right' | 'top-left') => { const { dragX, dragY, focalX, focalY } = positions[position] await page.goto(mediaURL.create) - + await page.waitForURL(mediaURL.create) // select and upload file const fileChooserPromise = page.waitForEvent('filechooser') await page.getByText('Select a file').click() const fileChooser = await fileChooserPromise + await wait(1000) await fileChooser.setFiles(path.join(dirname, 'test-image.jpg')) + await page.locator('.file-field__edit').click() // set crop @@ -300,18 +294,18 @@ describe('uploads', () => { await expect(page.locator('.edit-upload__input input[name="X %"]')).toHaveValue(`${focalX}`) await expect(page.locator('.edit-upload__input input[name="Y %"]')).toHaveValue(`${focalY}`) + // apply crop await page.locator('button:has-text("Apply Changes")').click() await page.waitForSelector('button#action-save') await page.locator('button#action-save').click() + await expect(page.locator('.Toastify')).toContainText('successfully') + await wait(1000) // Wait for the save } await createFocalCrop(page, 'bottom-right') // green square - await wait(1000) // wait for edit view navigation (saving images) - // get the ID of the doc - const greenSquareMediaID = page.url().split('/').pop() + const greenSquareMediaID = page.url().split('/').pop() // get the ID of the doc await createFocalCrop(page, 'top-left') // red square - await wait(1000) // wait for edit view navigation (saving images) - const redSquareMediaID = page.url().split('/').pop() + const redSquareMediaID = page.url().split('/').pop() // get the ID of the doc const { doc: greenDoc } = await client.findByID({ id: greenSquareMediaID,