feat: e2e test upload (#755)
This commit is contained in:
27
test/e2e/auth/payload-types.ts
Normal file
27
test/e2e/auth/payload-types.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
enableAPIKey?: boolean;
|
||||
apiKey?: string;
|
||||
apiKeyIndex?: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
_verified?: boolean;
|
||||
_verificationToken?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
33
test/e2e/collections/payload-types.ts
Normal file
33
test/e2e/collections/payload-types.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "posts".
|
||||
*/
|
||||
export interface Post {
|
||||
id: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
35
test/e2e/fields-array/payload-types.ts
Normal file
35
test/e2e/fields-array/payload-types.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "fields-array".
|
||||
*/
|
||||
export interface FieldsArray {
|
||||
id: string;
|
||||
readOnlyArray?: {
|
||||
text?: string;
|
||||
id?: string;
|
||||
}[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { expect, test } from '@playwright/test';
|
||||
import payload from '../../../src';
|
||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
||||
import { initPayloadE2E, initPayloadTest } from '../../helpers/configHelpers';
|
||||
import { login, saveDocAndAssert } from '../helpers';
|
||||
import type {
|
||||
FieldsRelationship as CollectionWithRelationships,
|
||||
@@ -36,12 +36,7 @@ describe('fields - relationship', () => {
|
||||
let relationWithTitle: RelationWithTitle;
|
||||
|
||||
beforeAll(async ({ browser }) => {
|
||||
const { serverURL } = await initPayloadTest({
|
||||
__dirname,
|
||||
init: {
|
||||
local: false,
|
||||
},
|
||||
});
|
||||
const { serverURL } = await initPayloadE2E(__dirname);
|
||||
await clearAllDocs();
|
||||
|
||||
url = new AdminUrlUtil(serverURL, slug);
|
||||
|
||||
94
test/e2e/fields-relationship/payload-types.ts
Normal file
94
test/e2e/fields-relationship/payload-types.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "fields-relationship".
|
||||
*/
|
||||
export interface FieldsRelationship {
|
||||
id: string;
|
||||
relationship?: string | RelationOne;
|
||||
relationshipHasMany?: (string | RelationOne)[];
|
||||
relationshipMultiple?:
|
||||
| {
|
||||
value: string | RelationOne;
|
||||
relationTo: 'relation-one';
|
||||
}
|
||||
| {
|
||||
value: string | RelationTwo;
|
||||
relationTo: 'relation-two';
|
||||
};
|
||||
relationshipHasManyMultiple?: (
|
||||
| {
|
||||
value: string | RelationOne;
|
||||
relationTo: 'relation-one';
|
||||
}
|
||||
| {
|
||||
value: string | RelationTwo;
|
||||
relationTo: 'relation-two';
|
||||
}
|
||||
)[];
|
||||
relationshipRestricted?: string | RelationRestricted;
|
||||
relationshipWithTitle?: string | RelationWithTitle;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "relation-one".
|
||||
*/
|
||||
export interface RelationOne {
|
||||
id: string;
|
||||
name?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "relation-two".
|
||||
*/
|
||||
export interface RelationTwo {
|
||||
id: string;
|
||||
name?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "relation-restricted".
|
||||
*/
|
||||
export interface RelationRestricted {
|
||||
id: string;
|
||||
name?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "relation-with-title".
|
||||
*/
|
||||
export interface RelationWithTitle {
|
||||
id: string;
|
||||
name?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
32
test/e2e/fields/payload-types.ts
Normal file
32
test/e2e/fields/payload-types.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "text-fields".
|
||||
*/
|
||||
export interface TextField {
|
||||
id: string;
|
||||
text: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
33
test/e2e/localization/payload-types.ts
Normal file
33
test/e2e/localization/payload-types.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "localized-posts".
|
||||
*/
|
||||
export interface LocalizedPost {
|
||||
id: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
1
test/e2e/uploads/.gitignore
vendored
Normal file
1
test/e2e/uploads/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/media
|
||||
102
test/e2e/uploads/config.ts
Normal file
102
test/e2e/uploads/config.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { buildConfig } from '../buildConfig';
|
||||
import { devUser } from '../../credentials';
|
||||
import getFileByPath from '../../../src/uploads/getFileByPath';
|
||||
|
||||
export const mediaSlug = 'media';
|
||||
|
||||
export const relationSlug = 'relation';
|
||||
|
||||
const mockModulePath = path.resolve(__dirname, './mocks/mockFSModule.js');
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
webpack: (config) => ({
|
||||
...config,
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...config.resolve.alias,
|
||||
fs: mockModulePath,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
// upload: {},
|
||||
collections: [
|
||||
{
|
||||
slug: relationSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
relationTo: 'media',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: mediaSlug,
|
||||
upload: {
|
||||
staticURL: '/media',
|
||||
staticDir: './media',
|
||||
imageSizes: [
|
||||
{
|
||||
name: 'maintainedAspectRatio',
|
||||
width: 1024,
|
||||
height: null,
|
||||
crop: 'center',
|
||||
},
|
||||
{
|
||||
name: 'tablet',
|
||||
width: 640,
|
||||
height: 480,
|
||||
crop: 'left top',
|
||||
},
|
||||
{
|
||||
name: 'mobile',
|
||||
width: 320,
|
||||
height: 240,
|
||||
crop: 'left top',
|
||||
},
|
||||
{
|
||||
name: 'icon',
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
],
|
||||
},
|
||||
fields: [
|
||||
],
|
||||
},
|
||||
],
|
||||
onInit: async (payload) => {
|
||||
// delete files in /media
|
||||
const mediaDir = path.resolve(__dirname, './media');
|
||||
fs.readdirSync(mediaDir).forEach((f) => fs.rmSync(`${mediaDir}/${f}`));
|
||||
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: devUser.email,
|
||||
password: devUser.password,
|
||||
},
|
||||
});
|
||||
// Create image
|
||||
const filePath = path.resolve(__dirname, './image.png');
|
||||
const file = getFileByPath(filePath);
|
||||
|
||||
const { id: uploadedImage } = await payload.create({
|
||||
collection: mediaSlug,
|
||||
data: {},
|
||||
file,
|
||||
});
|
||||
|
||||
await payload.create({
|
||||
collection: relationSlug,
|
||||
data: {
|
||||
image: uploadedImage,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
88
test/e2e/uploads/index.spec.ts
Normal file
88
test/e2e/uploads/index.spec.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
||||
import { initPayloadE2E } from '../../helpers/configHelpers';
|
||||
import { login, saveDocAndAssert } from '../helpers';
|
||||
import { relationSlug, mediaSlug } from './config';
|
||||
import type { Media } from './payload-types';
|
||||
import wait from '../../../src/utilities/wait';
|
||||
import payload from '../../../src';
|
||||
|
||||
const { beforeAll, describe } = test;
|
||||
|
||||
let mediaURL: AdminUrlUtil;
|
||||
let relationURL: AdminUrlUtil;
|
||||
|
||||
describe('uploads', () => {
|
||||
let page: Page;
|
||||
let mediaDoc: Media;
|
||||
|
||||
beforeAll(async ({ browser }) => {
|
||||
const { serverURL } = await initPayloadE2E(__dirname);
|
||||
|
||||
mediaURL = new AdminUrlUtil(serverURL, mediaSlug);
|
||||
relationURL = new AdminUrlUtil(serverURL, relationSlug);
|
||||
|
||||
const context = await browser.newContext();
|
||||
page = await context.newPage();
|
||||
|
||||
const findMedia = await payload.find({
|
||||
collection: mediaSlug,
|
||||
depth: 0,
|
||||
pagination: false,
|
||||
});
|
||||
mediaDoc = findMedia.docs[0] as Media;
|
||||
|
||||
await login({ page, serverURL });
|
||||
});
|
||||
|
||||
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 show upload filename in upload collection list', async () => {
|
||||
await page.goto(mediaURL.list);
|
||||
|
||||
const media = page.locator('.upload-card__filename');
|
||||
await wait(110);
|
||||
|
||||
await expect(media).toHaveText('image.png');
|
||||
});
|
||||
|
||||
test('should create file upload', async () => {
|
||||
await page.goto(mediaURL.create);
|
||||
|
||||
await page.setInputFiles('input[type="file"]', './image.png');
|
||||
|
||||
const filename = page.locator('.file-field__filename');
|
||||
|
||||
await expect(filename).toContainText('.png');
|
||||
|
||||
await page.locator('.form-submit button').click();
|
||||
|
||||
await saveDocAndAssert(page);
|
||||
});
|
||||
|
||||
test('should show resized images', async () => {
|
||||
await page.goto(mediaURL.edit(mediaDoc.id));
|
||||
|
||||
await page.locator('.btn.file-details__toggle-more-info').click();
|
||||
|
||||
const maintainedAspectRatioMeta = page.locator('.file-details__sizes .file-meta').nth(0);
|
||||
await expect(maintainedAspectRatioMeta).toContainText('1024x1024');
|
||||
|
||||
const tabletMeta = page.locator('.file-details__sizes .file-meta').nth(1);
|
||||
await expect(tabletMeta).toContainText('640x480');
|
||||
|
||||
const mobileMeta = page.locator('.file-details__sizes .file-meta').nth(2);
|
||||
await expect(mobileMeta).toContainText('320x240');
|
||||
|
||||
const iconMeta = page.locator('.file-details__sizes .file-meta').nth(3);
|
||||
await expect(iconMeta).toContainText('16x16');
|
||||
});
|
||||
});
|
||||
4
test/e2e/uploads/mocks/mockFSModule.js
Normal file
4
test/e2e/uploads/mocks/mockFSModule.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
readdirSync: () => {},
|
||||
rmSync: () => {},
|
||||
};
|
||||
81
test/e2e/uploads/payload-types.ts
Normal file
81
test/e2e/uploads/payload-types.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "relation".
|
||||
*/
|
||||
export interface Relation {
|
||||
id: string;
|
||||
image?: string | Media;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "media".
|
||||
*/
|
||||
export interface Media {
|
||||
id: string;
|
||||
url?: string;
|
||||
filename?: string;
|
||||
mimeType?: string;
|
||||
filesize?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
sizes?: {
|
||||
maintainedAspectRatio?: {
|
||||
url?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
mimeType?: string;
|
||||
filesize?: number;
|
||||
filename?: string;
|
||||
};
|
||||
tablet?: {
|
||||
url?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
mimeType?: string;
|
||||
filesize?: number;
|
||||
filename?: string;
|
||||
};
|
||||
mobile?: {
|
||||
url?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
mimeType?: string;
|
||||
filesize?: number;
|
||||
filename?: string;
|
||||
};
|
||||
icon?: {
|
||||
url?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
mimeType?: string;
|
||||
filesize?: number;
|
||||
filename?: string;
|
||||
};
|
||||
};
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
31
test/e2e/versions/payload-types.ts
Normal file
31
test/e2e/versions/payload-types.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/* tslint:disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload CMS.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "slugname".
|
||||
*/
|
||||
export interface Slugname {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
email?: string;
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpiration?: string;
|
||||
loginAttempts?: number;
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
Reference in New Issue
Block a user