test: refactor all test directories into one
This commit is contained in:
@@ -2,8 +2,9 @@ module.exports = {
|
|||||||
verbose: true,
|
verbose: true,
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
testMatch: [
|
testMatch: [
|
||||||
'**/test/int/**/*spec.ts',
|
'**/test/**/*int.spec.ts',
|
||||||
],
|
],
|
||||||
|
globalSetup: './test/jest.setup.ts',
|
||||||
testTimeout: 15000,
|
testTimeout: 15000,
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/webpack/mocks/fileMock.js',
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/webpack/mocks/fileMock.js',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { PlaywrightTestConfig } from '@playwright/test';
|
|||||||
const config: PlaywrightTestConfig = {
|
const config: PlaywrightTestConfig = {
|
||||||
// Look for test files in the "tests" directory, relative to this configuration file
|
// Look for test files in the "tests" directory, relative to this configuration file
|
||||||
testDir: 'test',
|
testDir: 'test',
|
||||||
testMatch: 'e2e.spec.ts',
|
testMatch: '*e2e.spec.ts',
|
||||||
workers: 999,
|
workers: 999,
|
||||||
timeout: 600000,
|
timeout: 600000,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import { APIError } from '.';
|
|
||||||
|
|
||||||
describe('Errors', () => {
|
|
||||||
describe('APIError', () => {
|
|
||||||
it('should handle an error message', () => {
|
|
||||||
const error = new APIError('my message', 400, false);
|
|
||||||
expect(error.message).toStrictEqual('my message');
|
|
||||||
});
|
|
||||||
|
|
||||||
// it('should handle an array', () => {
|
|
||||||
// const errors = [
|
|
||||||
// {
|
|
||||||
// error: 'some error description',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// error: 'some error description 2',
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
// const error = new APIError(errors, 400, false);
|
|
||||||
// expect(error.message).toStrictEqual(JSON.stringify(errors));
|
|
||||||
// });
|
|
||||||
|
|
||||||
// it('should handle an object', () => {
|
|
||||||
// const myFancyErrorObject = { someProp: 'someDetail ' };
|
|
||||||
// const error = new APIError(myFancyErrorObject, 400, false);
|
|
||||||
// expect(error.message).toStrictEqual(JSON.stringify(myFancyErrorObject));
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import merge from 'deepmerge';
|
|
||||||
import path from 'path';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
import { CollectionConfig } from '../../collections/config/types';
|
|
||||||
import { Config, SanitizedConfig, InitOptions } from '../../config/types';
|
|
||||||
import { buildConfig } from '../../config/build';
|
|
||||||
import payload from '../..';
|
|
||||||
|
|
||||||
|
|
||||||
const Admins: CollectionConfig = {
|
|
||||||
slug: 'admins',
|
|
||||||
auth: true,
|
|
||||||
fields: [
|
|
||||||
// Email added by default
|
|
||||||
{
|
|
||||||
name: 'name',
|
|
||||||
type: 'text',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const baseConfig: Config = {
|
|
||||||
serverURL: 'http://localhost:3000',
|
|
||||||
admin: {
|
|
||||||
user: Admins.slug,
|
|
||||||
},
|
|
||||||
collections: [
|
|
||||||
Admins,
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export function generateTestConfig(overrides?: Partial<Config>): SanitizedConfig {
|
|
||||||
return buildConfig(merge(baseConfig, overrides));
|
|
||||||
}
|
|
||||||
|
|
||||||
type InitPayloadTestOptions = { initOptions?: Partial<InitOptions> }
|
|
||||||
export function initPayloadTest(dirName: string, initOptions?: InitPayloadTestOptions): void {
|
|
||||||
process.env.PAYLOAD_CONFIG_PATH = path.resolve(dirName, './payload.config.ts');
|
|
||||||
|
|
||||||
payload.init({
|
|
||||||
local: true,
|
|
||||||
mongoURL: `mongodb://localhost/${uuid()}`,
|
|
||||||
secret: uuid(),
|
|
||||||
// TODO: Figure out how to handle express
|
|
||||||
...initOptions,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const openAccess: CollectionConfig['access'] = {
|
|
||||||
read: () => true,
|
|
||||||
create: () => true,
|
|
||||||
delete: () => true,
|
|
||||||
update: () => true,
|
|
||||||
};
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { devUser } from '../../credentials';
|
import { devUser } from '../credentials';
|
||||||
import { buildConfig } from '../buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
import type { ReadOnlyCollection } from './payload-types';
|
|
||||||
|
|
||||||
export const slug = 'access-controls';
|
export const slug = 'access-controls';
|
||||||
export const readOnlySlug = 'read-only-collection';
|
export const readOnlySlug = 'read-only-collection';
|
||||||
export const restrictedSlug = 'restricted';
|
export const restrictedSlug = 'restricted';
|
||||||
|
export const restrictedVersionsSlug = 'restricted-versions';
|
||||||
|
|
||||||
export default buildConfig({
|
export default buildConfig({
|
||||||
collections: [
|
collections: [
|
||||||
@@ -45,6 +45,19 @@ export default buildConfig({
|
|||||||
delete: () => false,
|
delete: () => false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: restrictedVersionsSlug,
|
||||||
|
versions: true,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
access: {
|
||||||
|
readVersions: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
onInit: async (payload) => {
|
onInit: async (payload) => {
|
||||||
await payload.create({
|
await payload.create({
|
||||||
@@ -62,11 +75,18 @@ export default buildConfig({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await payload.create<ReadOnlyCollection>({
|
await payload.create({
|
||||||
collection: readOnlySlug,
|
collection: readOnlySlug,
|
||||||
data: {
|
data: {
|
||||||
name: 'read-only',
|
name: 'read-only',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await payload.create({
|
||||||
|
collection: restrictedVersionsSlug,
|
||||||
|
data: {
|
||||||
|
name: 'versioned',
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadE2E } from '../../helpers/configHelpers';
|
import { initPayloadE2E } from '../helpers/configHelpers';
|
||||||
import { login } from '../helpers';
|
import { login } from '../helpers';
|
||||||
import { readOnlySlug, restrictedSlug, slug } from './config';
|
import { restrictedVersionsSlug, readOnlySlug, restrictedSlug, slug } from './config';
|
||||||
import type { ReadOnlyCollection } from './payload-types';
|
import type { ReadOnlyCollection, RestrictedVersion } from './payload-types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Access Control
|
* TODO: Access Control
|
||||||
* prevent user from logging in (canAccessAdmin)
|
* prevent user from logging in (canAccessAdmin)
|
||||||
* no version controls is no access
|
|
||||||
*
|
*
|
||||||
* FSK: 'should properly prevent / allow public users from reading a restricted field'
|
* FSK: 'should properly prevent / allow public users from reading a restricted field'
|
||||||
*
|
*
|
||||||
@@ -24,6 +23,7 @@ describe('access control', () => {
|
|||||||
let url: AdminUrlUtil;
|
let url: AdminUrlUtil;
|
||||||
let restrictedUrl: AdminUrlUtil;
|
let restrictedUrl: AdminUrlUtil;
|
||||||
let readoOnlyUrl: AdminUrlUtil;
|
let readoOnlyUrl: AdminUrlUtil;
|
||||||
|
let restrictedVersionsUrl: AdminUrlUtil;
|
||||||
|
|
||||||
beforeAll(async ({ browser }) => {
|
beforeAll(async ({ browser }) => {
|
||||||
const { serverURL } = await initPayloadE2E(__dirname);
|
const { serverURL } = await initPayloadE2E(__dirname);
|
||||||
@@ -31,6 +31,7 @@ describe('access control', () => {
|
|||||||
url = new AdminUrlUtil(serverURL, slug);
|
url = new AdminUrlUtil(serverURL, slug);
|
||||||
restrictedUrl = new AdminUrlUtil(serverURL, restrictedSlug);
|
restrictedUrl = new AdminUrlUtil(serverURL, restrictedSlug);
|
||||||
readoOnlyUrl = new AdminUrlUtil(serverURL, readOnlySlug);
|
readoOnlyUrl = new AdminUrlUtil(serverURL, readOnlySlug);
|
||||||
|
restrictedVersionsUrl = new AdminUrlUtil(serverURL, restrictedVersionsSlug);
|
||||||
|
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
page = await context.newPage();
|
page = await context.newPage();
|
||||||
@@ -121,7 +122,7 @@ describe('access control', () => {
|
|||||||
await expect(page.locator(`#card-${readOnlySlug}`)).not.toHaveClass('card__actions');
|
await expect(page.locator(`#card-${readOnlySlug}`)).not.toHaveClass('card__actions');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('edit view should not have buttons', async () => {
|
test('edit view should not have actions buttons', async () => {
|
||||||
await page.goto(readoOnlyUrl.edit(existingDoc.id));
|
await page.goto(readoOnlyUrl.edit(existingDoc.id));
|
||||||
await expect(page.locator('.collection-edit__collection-actions li')).toHaveCount(0);
|
await expect(page.locator('.collection-edit__collection-actions li')).toHaveCount(0);
|
||||||
});
|
});
|
||||||
@@ -131,6 +132,24 @@ describe('access control', () => {
|
|||||||
await expect(page.locator('#field-name')).toBeDisabled();
|
await expect(page.locator('#field-name')).toBeDisabled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('readVersions', () => {
|
||||||
|
let existingDoc: RestrictedVersion;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
existingDoc = await payload.create<RestrictedVersion>({
|
||||||
|
collection: restrictedVersionsSlug,
|
||||||
|
data: {
|
||||||
|
name: 'name',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('versions sidebar should not show', async () => {
|
||||||
|
await page.goto(restrictedVersionsUrl.edit(existingDoc.id));
|
||||||
|
await expect(page.locator('.versions-count')).not.toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function createDoc(data: any): Promise<{ id: string }> {
|
async function createDoc(data: any): Promise<{ id: string }> {
|
||||||
@@ -35,6 +35,16 @@ export interface ReadOnlyCollection {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "restricted-versions".
|
||||||
|
*/
|
||||||
|
export interface RestrictedVersion {
|
||||||
|
id: string;
|
||||||
|
name?: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "users".
|
* via the `definition` "users".
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import type { Array as ArrayCollection } from './payload-types';
|
import type { Array as ArrayCollection } from './payload-types';
|
||||||
|
|
||||||
69
test/auth/e2e.spec.ts
Normal file
69
test/auth/e2e.spec.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import type { Page } from '@playwright/test';
|
||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
|
import { firstRegister } from '../helpers';
|
||||||
|
import { slug } from './config';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Auth
|
||||||
|
* change password
|
||||||
|
* unlock
|
||||||
|
* generate api key
|
||||||
|
* log out
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { beforeAll, describe } = test;
|
||||||
|
let url: AdminUrlUtil;
|
||||||
|
|
||||||
|
// describe('authentication', () => {
|
||||||
|
// let page: Page;
|
||||||
|
|
||||||
|
// beforeAll(async ({ browser }) => {
|
||||||
|
// const { serverURL } = await initPayloadTest({
|
||||||
|
// __dirname,
|
||||||
|
// init: {
|
||||||
|
// local: false,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// // await clearDocs(); // Clear any seeded data from onInit
|
||||||
|
|
||||||
|
// url = new AdminUrlUtil(serverURL, slug);
|
||||||
|
|
||||||
|
// const context = await browser.newContext();
|
||||||
|
// page = await context.newPage();
|
||||||
|
|
||||||
|
// await firstRegister({ page, serverURL });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('Authentication', () => {
|
||||||
|
// test(should login and logout', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should logout', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should allow change password', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should reset password', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should lockout after reaching max login attempts', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should prevent login for locked user', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should unlock user', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should not login without verify', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// test(should allow generate api keys', () => {
|
||||||
|
// expect(1).toEqual(1);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
37
test/buildConfig.ts
Normal file
37
test/buildConfig.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import merge from 'deepmerge';
|
||||||
|
import { Config, SanitizedConfig } from '../src/config/types';
|
||||||
|
import { buildConfig as buildPayloadConfig } from '../src/config/build';
|
||||||
|
|
||||||
|
|
||||||
|
const baseConfig: Config = {
|
||||||
|
typescript: {
|
||||||
|
outputFile: process.env.PAYLOAD_TS_OUTPUT_PATH,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function buildConfig(overrides?: Partial<Config>): SanitizedConfig {
|
||||||
|
if (process.env.NODE_ENV === 'test') {
|
||||||
|
baseConfig.admin = {
|
||||||
|
...baseConfig.admin || {},
|
||||||
|
webpack: (config) => {
|
||||||
|
const existingConfig = typeof overrides?.admin?.webpack === 'function' ? overrides.admin.webpack(config) : config;
|
||||||
|
return {
|
||||||
|
...existingConfig,
|
||||||
|
cache: {
|
||||||
|
type: 'memory',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(process.env.PAYLOAD_DISABLE_ADMIN);
|
||||||
|
if (process.env.PAYLOAD_DISABLE_ADMIN === 'true') {
|
||||||
|
console.log('disabling admin');
|
||||||
|
if (typeof baseConfig.admin !== 'object') baseConfig.admin = {};
|
||||||
|
baseConfig.admin.disable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return buildPayloadConfig(merge(baseConfig, overrides || {}));
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import { RESTClient } from '../../helpers/rest';
|
import { RESTClient } from '../helpers/rest';
|
||||||
import type { Post } from './payload-types';
|
import type { Post } from './payload-types';
|
||||||
|
|
||||||
const collection = config.collections[0]?.slug;
|
const collection = config.collections[0]?.slug;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { CollectionConfig } from '../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../src/collections/config/types';
|
||||||
import { devUser } from '../../credentials';
|
import { devUser } from '../credentials';
|
||||||
import { buildConfig } from '../buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
import type { Post } from './payload-types';
|
import type { Post } from './payload-types';
|
||||||
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import type { Relation } from './config';
|
import type { Relation } from './config';
|
||||||
import config, { slug, relationSlug } from './config';
|
import config, { slug, relationSlug } from './config';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import { RESTClient } from '../../helpers/rest';
|
import { RESTClient } from '../helpers/rest';
|
||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
|
||||||
import type { Post } from './payload-types';
|
import type { Post } from './payload-types';
|
||||||
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
|
|
||||||
let client: RESTClient;
|
let client: RESTClient;
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
import { devUser } from '../../credentials';
|
import { devUser } from '../credentials';
|
||||||
import { buildConfig } from '../buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
|
|
||||||
export const slug = 'posts';
|
export const slug = 'posts';
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadE2E } from '../../helpers/configHelpers';
|
import { initPayloadE2E } from '../helpers/configHelpers';
|
||||||
import { login, saveDocAndAssert } from '../helpers';
|
import { login, saveDocAndAssert } from '../helpers';
|
||||||
import type { Post } from './config';
|
import type { Post } from './config';
|
||||||
import { slug } from './config';
|
import { slug } from './config';
|
||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
import wait from '../../../src/utilities/wait';
|
import wait from '../../src/utilities/wait';
|
||||||
|
|
||||||
const { afterEach, beforeAll, beforeEach, describe } = test;
|
const { afterEach, beforeAll, beforeEach, describe } = test;
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import payload from '../../src';
|
import payload from '../../src';
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
import type { Page } from '@playwright/test';
|
|
||||||
import { expect, test } from '@playwright/test';
|
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
|
||||||
import { firstRegister } from '../helpers';
|
|
||||||
import { slug } from './config';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Auth
|
|
||||||
* change password
|
|
||||||
* unlock
|
|
||||||
* generate api key
|
|
||||||
* log out
|
|
||||||
*/
|
|
||||||
|
|
||||||
const { beforeAll, describe } = test;
|
|
||||||
let url: AdminUrlUtil;
|
|
||||||
|
|
||||||
describe('authentication', () => {
|
|
||||||
let page: Page;
|
|
||||||
|
|
||||||
beforeAll(async ({ browser }) => {
|
|
||||||
const { serverURL } = await initPayloadTest({
|
|
||||||
__dirname,
|
|
||||||
init: {
|
|
||||||
local: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// await clearDocs(); // Clear any seeded data from onInit
|
|
||||||
|
|
||||||
url = new AdminUrlUtil(serverURL, slug);
|
|
||||||
|
|
||||||
const context = await browser.newContext();
|
|
||||||
page = await context.newPage();
|
|
||||||
|
|
||||||
await firstRegister({ page, serverURL });
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Authentication', () => {
|
|
||||||
test('should login and logout', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should logout', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should allow change password', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should reset password', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should lockout after reaching max login attempts', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should prevent login for locked user', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should unlock user', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should not login without verify', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
test('should allow generate api keys', () => {
|
|
||||||
expect(1).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import merge from 'deepmerge';
|
|
||||||
import { buildConfig as buildPayloadConfig } from '../../src/config/build';
|
|
||||||
import type { Config, SanitizedConfig } from '../../src/config/types';
|
|
||||||
|
|
||||||
export function buildConfig(overrides?: Partial<Config>): SanitizedConfig {
|
|
||||||
const baseConfig: Config = {
|
|
||||||
typescript: {
|
|
||||||
outputFile: process.env.PAYLOAD_TS_OUTPUT_PATH,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if (process.env.NODE_ENV === 'test') {
|
|
||||||
baseConfig.admin = {
|
|
||||||
webpack: (config) => ({
|
|
||||||
...config,
|
|
||||||
cache: {
|
|
||||||
type: 'memory',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildPayloadConfig(merge(baseConfig, overrides || {}));
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import wait from '../../../src/utilities/wait';
|
import wait from '../../src/utilities/wait';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import { firstRegister } from '../helpers';
|
import { firstRegister } from '../helpers';
|
||||||
import { slug } from './config';
|
import { slug } from './config';
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { CollectionConfig } from '../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../src/collections/config/types';
|
||||||
import { buildConfig } from '../buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
import { devUser } from '../../credentials';
|
import { devUser } from '../credentials';
|
||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
|
|
||||||
export const slug = 'fields-relationship';
|
export const slug = 'fields-relationship';
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadE2E, initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadE2E } from '../helpers/configHelpers';
|
||||||
import { login, saveDocAndAssert } from '../helpers';
|
import { login, saveDocAndAssert } from '../helpers';
|
||||||
import type {
|
import type {
|
||||||
FieldsRelationship as CollectionWithRelationships,
|
FieldsRelationship as CollectionWithRelationships,
|
||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
relationWithTitleSlug,
|
relationWithTitleSlug,
|
||||||
slug,
|
slug,
|
||||||
} from './config';
|
} from './config';
|
||||||
import wait from '../../../src/utilities/wait';
|
import wait from '../../src/utilities/wait';
|
||||||
|
|
||||||
const { beforeAll, describe } = test;
|
const { beforeAll, describe } = test;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CollectionConfig } from '../../../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../../src/collections/config/types';
|
||||||
|
|
||||||
const ArrayFields: CollectionConfig = {
|
const ArrayFields: CollectionConfig = {
|
||||||
slug: 'array-fields',
|
slug: 'array-fields',
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CollectionConfig } from '../../../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../../src/collections/config/types';
|
||||||
|
|
||||||
const BlockFields: CollectionConfig = {
|
const BlockFields: CollectionConfig = {
|
||||||
slug: 'block-fields',
|
slug: 'block-fields',
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CollectionConfig } from '../../../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../../src/collections/config/types';
|
||||||
|
|
||||||
const CollapsibleFields: CollectionConfig = {
|
const CollapsibleFields: CollectionConfig = {
|
||||||
slug: 'collapsible-fields',
|
slug: 'collapsible-fields',
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CollectionConfig } from '../../../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../../src/collections/config/types';
|
||||||
|
|
||||||
const RichTextFields: CollectionConfig = {
|
const RichTextFields: CollectionConfig = {
|
||||||
slug: 'rich-text-fields',
|
slug: 'rich-text-fields',
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CollectionConfig } from '../../../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../../src/collections/config/types';
|
||||||
|
|
||||||
const SelectFields: CollectionConfig = {
|
const SelectFields: CollectionConfig = {
|
||||||
slug: 'select-fields',
|
slug: 'select-fields',
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CollectionConfig } from '../../../../../src/collections/config/types';
|
import type { CollectionConfig } from '../../../../src/collections/config/types';
|
||||||
|
|
||||||
const TextFields: CollectionConfig = {
|
const TextFields: CollectionConfig = {
|
||||||
slug: 'text-fields',
|
slug: 'text-fields',
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { buildConfig } from '../buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
import { devUser } from '../../credentials';
|
import { devUser } from '../credentials';
|
||||||
import ArrayFields, { arrayDoc } from './collections/Array';
|
import ArrayFields, { arrayDoc } from './collections/Array';
|
||||||
import BlockFields, { blocksDoc } from './collections/Blocks';
|
import BlockFields, { blocksDoc } from './collections/Blocks';
|
||||||
import CollapsibleFields, { collapsibleDoc } from './collections/Collapsible';
|
import CollapsibleFields, { collapsibleDoc } from './collections/Collapsible';
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadE2E } from '../../helpers/configHelpers';
|
import { initPayloadE2E } from '../helpers/configHelpers';
|
||||||
import { login } from '../helpers';
|
import { login } from '../helpers';
|
||||||
import { textDoc } from './collections/Text';
|
import { textDoc } from './collections/Text';
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
import wait from '../../src/utilities/wait';
|
import wait from '../src/utilities/wait';
|
||||||
import { devUser } from '../credentials';
|
import { devUser } from './credentials';
|
||||||
|
|
||||||
type FirstRegisterArgs = {
|
type FirstRegisterArgs = {
|
||||||
page: Page,
|
page: Page,
|
||||||
@@ -28,6 +28,7 @@ export async function initPayloadTest(options: Options): Promise<{ serverURL: st
|
|||||||
...options.init || {},
|
...options.init || {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
process.env.PAYLOAD_DISABLE_ADMIN = 'true';
|
||||||
process.env.PAYLOAD_CONFIG_PATH = path.resolve(options.__dirname, './config.ts');
|
process.env.PAYLOAD_CONFIG_PATH = path.resolve(options.__dirname, './config.ts');
|
||||||
|
|
||||||
const port = await getPort();
|
const port = await getPort();
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import merge from 'deepmerge';
|
|
||||||
import { buildConfig as buildPayloadConfig } from '../../src/config/build';
|
|
||||||
import type { Config, SanitizedConfig } from '../../src/config/types';
|
|
||||||
|
|
||||||
export function buildConfig(overrides?: Partial<Config>): SanitizedConfig {
|
|
||||||
const baseConfig: Config = {
|
|
||||||
typescript: {
|
|
||||||
outputFile: process.env.PAYLOAD_TS_OUTPUT_PATH,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'test') {
|
|
||||||
baseConfig.admin = {
|
|
||||||
disable: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildPayloadConfig(merge(baseConfig, overrides || {}));
|
|
||||||
}
|
|
||||||
@@ -1,438 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import FormData from 'form-data';
|
|
||||||
import { GraphQLClient } from 'graphql-request';
|
|
||||||
import { promisify } from 'util';
|
|
||||||
import getConfig from '../../config/load';
|
|
||||||
import { email, password } from '../../mongoose/testCredentials';
|
|
||||||
|
|
||||||
const stat = promisify(fs.stat);
|
|
||||||
|
|
||||||
require('isomorphic-fetch');
|
|
||||||
|
|
||||||
const config = getConfig();
|
|
||||||
const api = `${config.serverURL}${config.routes.api}`;
|
|
||||||
|
|
||||||
let client;
|
|
||||||
let token;
|
|
||||||
let headers;
|
|
||||||
|
|
||||||
describe('Collections - Uploads', () => {
|
|
||||||
beforeAll(async (done) => {
|
|
||||||
const response = await fetch(`${api}/admins/login`, {
|
|
||||||
body: JSON.stringify({
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
({ token } = data);
|
|
||||||
headers = {
|
|
||||||
Authorization: `JWT ${token}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('REST', () => {
|
|
||||||
const mediaDir = path.join(__dirname, '../../../demo', 'media');
|
|
||||||
beforeAll(async () => {
|
|
||||||
// Clear demo/media directory
|
|
||||||
const mediaDirExists = await fileExists(mediaDir);
|
|
||||||
if (!mediaDirExists) return;
|
|
||||||
fs.readdir(mediaDir, (err, files) => {
|
|
||||||
if (err) throw err;
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
|
||||||
for (const file of files) {
|
|
||||||
fs.unlink(path.join(mediaDir, file), (unlinkErr) => {
|
|
||||||
if (unlinkErr) throw unlinkErr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('create', () => {
|
|
||||||
it('creates', async () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/image.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', 'test media');
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
const response = await fetch(`${api}/media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
|
|
||||||
// Check for files
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'image.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'image-16x16.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'image-320x240.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'image-640x480.png'))).toBe(true);
|
|
||||||
|
|
||||||
// Check api response
|
|
||||||
expect(data).toMatchObject({
|
|
||||||
doc: {
|
|
||||||
alt: 'test media',
|
|
||||||
filename: 'image.png',
|
|
||||||
mimeType: 'image/png',
|
|
||||||
sizes: {
|
|
||||||
icon: {
|
|
||||||
filename: 'image-16x16.png',
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
},
|
|
||||||
mobile: {
|
|
||||||
filename: 'image-320x240.png',
|
|
||||||
width: 320,
|
|
||||||
height: 240,
|
|
||||||
},
|
|
||||||
tablet: {
|
|
||||||
filename: 'image-640x480.png',
|
|
||||||
width: 640,
|
|
||||||
height: 480,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// We have a hook to check if upload sizes
|
|
||||||
// are properly bound to the Payload `req`.
|
|
||||||
// This field should be automatically set
|
|
||||||
// if they are found.
|
|
||||||
foundUploadSizes: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates images that do not require all sizes', async () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/small.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', 'test media');
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
const response = await fetch(`${api}/media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'small.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'small-16x16.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'small-320x240.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'small-640x480.png'))).toBe(false);
|
|
||||||
|
|
||||||
// Check api response
|
|
||||||
expect(data).toMatchObject({
|
|
||||||
doc: {
|
|
||||||
alt: 'test media',
|
|
||||||
filename: 'small.png',
|
|
||||||
mimeType: 'image/png',
|
|
||||||
sizes: {
|
|
||||||
icon: {
|
|
||||||
filename: 'small-16x16.png',
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// We have a hook to check if upload sizes
|
|
||||||
// are properly bound to the Payload `req`.
|
|
||||||
// This field should be automatically set
|
|
||||||
// if they are found.
|
|
||||||
foundUploadSizes: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates media without storing a file', async () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/image.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', 'test media');
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
|
|
||||||
const response = await fetch(`${api}/unstored-media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
|
|
||||||
// Check for files
|
|
||||||
expect(await !fileExists(path.join(mediaDir, 'image.png'))).toBe(false);
|
|
||||||
expect(await !fileExists(path.join(mediaDir, 'image-640x480.png'))).toBe(false);
|
|
||||||
|
|
||||||
// Check api response
|
|
||||||
expect(data).toMatchObject({
|
|
||||||
doc: {
|
|
||||||
alt: 'test media',
|
|
||||||
filename: 'image.png',
|
|
||||||
mimeType: 'image/png',
|
|
||||||
sizes: {
|
|
||||||
tablet: {
|
|
||||||
filename: 'image-640x480.png',
|
|
||||||
width: 640,
|
|
||||||
height: 480,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates with same name', async () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/samename.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', 'test media');
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
|
|
||||||
const firstResponse = await fetch(`${api}/media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(firstResponse.status).toBe(201);
|
|
||||||
|
|
||||||
const sameForm = new FormData();
|
|
||||||
sameForm.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/samename.png')),
|
|
||||||
);
|
|
||||||
sameForm.append('alt', 'test media');
|
|
||||||
sameForm.append('locale', 'en');
|
|
||||||
|
|
||||||
const response = await fetch(`${api}/media`, {
|
|
||||||
body: sameForm as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
// Check for files
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'samename-1.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'samename-1-16x16.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'samename-1-320x240.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'samename-1-640x480.png'))).toBe(true);
|
|
||||||
|
|
||||||
expect(data).toMatchObject({
|
|
||||||
doc: {
|
|
||||||
alt: 'test media',
|
|
||||||
filename: 'samename-1.png',
|
|
||||||
mimeType: 'image/png',
|
|
||||||
sizes: {
|
|
||||||
icon: {
|
|
||||||
filename: 'samename-1-16x16.png',
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
},
|
|
||||||
mobile: {
|
|
||||||
filename: 'samename-1-320x240.png',
|
|
||||||
width: 320,
|
|
||||||
height: 240,
|
|
||||||
},
|
|
||||||
tablet: {
|
|
||||||
filename: 'samename-1-640x480.png',
|
|
||||||
width: 640,
|
|
||||||
height: 480,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('update', async () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/update.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', 'test media');
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
|
|
||||||
const response = await fetch(`${api}/media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
expect(response.status).toBe(201);
|
|
||||||
|
|
||||||
const updateFormData = new FormData();
|
|
||||||
const newAlt = 'my new alt';
|
|
||||||
|
|
||||||
updateFormData.append('filename', data.doc.filename);
|
|
||||||
updateFormData.append('alt', newAlt);
|
|
||||||
const updateResponse = await fetch(`${api}/media/${data.doc.id}`, {
|
|
||||||
body: updateFormData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'put',
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const updateResponseData = await updateResponse.json();
|
|
||||||
expect(updateResponse.status).toBe(200);
|
|
||||||
|
|
||||||
// Check that files weren't affected
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'update.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'update-16x16.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'update-320x240.png'))).toBe(true);
|
|
||||||
expect(await fileExists(path.join(mediaDir, 'update-640x480.png'))).toBe(true);
|
|
||||||
|
|
||||||
// Check api response
|
|
||||||
expect(updateResponseData).toMatchObject({
|
|
||||||
doc: {
|
|
||||||
alt: newAlt,
|
|
||||||
filename: 'update.png',
|
|
||||||
mimeType: 'image/png',
|
|
||||||
sizes: {
|
|
||||||
icon: {
|
|
||||||
filename: 'update-16x16.png',
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
},
|
|
||||||
mobile: {
|
|
||||||
filename: 'update-320x240.png',
|
|
||||||
width: 320,
|
|
||||||
height: 240,
|
|
||||||
},
|
|
||||||
tablet: {
|
|
||||||
filename: 'update-640x480.png',
|
|
||||||
width: 640,
|
|
||||||
height: 480,
|
|
||||||
},
|
|
||||||
maintainedAspectRatio: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('delete', async () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/delete.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', 'test media');
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
|
|
||||||
const createResponse = await fetch(`${api}/media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
|
|
||||||
const createData = await createResponse.json();
|
|
||||||
expect(createResponse.status).toBe(201);
|
|
||||||
const docId = createData.doc.id;
|
|
||||||
|
|
||||||
const response = await fetch(`${api}/media/${docId}`, {
|
|
||||||
headers,
|
|
||||||
method: 'delete',
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
expect(response.status).toBe(200);
|
|
||||||
expect(data.id).toBe(docId);
|
|
||||||
|
|
||||||
const imageExists = await fileExists(path.join(mediaDir, 'delete.png'));
|
|
||||||
expect(imageExists).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('GraphQL', () => {
|
|
||||||
// graphql cannot submit formData to create files, we only need to test getting relationship data on upload fields
|
|
||||||
let media;
|
|
||||||
let image;
|
|
||||||
const alt = 'alt text';
|
|
||||||
beforeAll(async (done) => {
|
|
||||||
client = new GraphQLClient(`${api}${config.routes.graphQL}`, {
|
|
||||||
headers: { Authorization: `JWT ${token}` },
|
|
||||||
});
|
|
||||||
|
|
||||||
// create media using REST
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(
|
|
||||||
'file',
|
|
||||||
fs.createReadStream(path.join(__dirname, '../../..', 'tests/api/assets/image.png')),
|
|
||||||
);
|
|
||||||
formData.append('alt', alt);
|
|
||||||
formData.append('locale', 'en');
|
|
||||||
const mediaResponse = await fetch(`${api}/media`, {
|
|
||||||
body: formData as unknown as BodyInit,
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
const mediaData = await mediaResponse.json();
|
|
||||||
media = mediaData.doc;
|
|
||||||
|
|
||||||
// create image that relates to media
|
|
||||||
headers['Content-Type'] = 'application/json';
|
|
||||||
const imageResponse = await fetch(`${api}/images`, {
|
|
||||||
body: JSON.stringify({
|
|
||||||
upload: media.id,
|
|
||||||
}),
|
|
||||||
headers,
|
|
||||||
method: 'post',
|
|
||||||
});
|
|
||||||
const data = await imageResponse.json();
|
|
||||||
image = data.doc;
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should query uploads relationship fields', async () => {
|
|
||||||
// language=graphQL
|
|
||||||
const query = `query {
|
|
||||||
Image(id: "${image.id}") {
|
|
||||||
id
|
|
||||||
upload {
|
|
||||||
alt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`;
|
|
||||||
|
|
||||||
const response = await client.request(query);
|
|
||||||
expect(response.Image.upload.alt).toStrictEqual(alt);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function fileExists(fileName: string): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
await stat(fileName);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
test/jest.setup.ts
Normal file
3
test/jest.setup.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = () => {
|
||||||
|
process.env.PAYLOAD_DISABLE_ADMIN = 'true';
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
import { buildConfig } from '../buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
|
|
||||||
export const slug = 'localized-posts';
|
export const slug = 'localized-posts';
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import payload from '../../../src';
|
import payload from '../../src';
|
||||||
import type { TypeWithTimestamps } from '../../../src/collections/config/types';
|
import type { TypeWithTimestamps } from '../../src/collections/config/types';
|
||||||
import { mapAsync } from '../../../src/utilities/mapAsync';
|
import { mapAsync } from '../../src/utilities/mapAsync';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import { firstRegister, saveDocAndAssert } from '../helpers';
|
import { firstRegister, saveDocAndAssert } from '../helpers';
|
||||||
import type { LocalizedPost } from './config';
|
import type { LocalizedPost } from './config';
|
||||||
import { slug } from './config';
|
import { slug } from './config';
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { buildConfig } from '../e2e/buildConfig';
|
import { buildConfig } from '../buildConfig';
|
||||||
import { devUser } from '../credentials';
|
import { devUser } from '../credentials';
|
||||||
import getFileByPath from '../../src/uploads/getFileByPath';
|
import getFileByPath from '../../src/uploads/getFileByPath';
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ export default buildConfig({
|
|||||||
resolve: {
|
resolve: {
|
||||||
...config.resolve,
|
...config.resolve,
|
||||||
alias: {
|
alias: {
|
||||||
...config.resolve.alias,
|
...config?.resolve?.alias,
|
||||||
fs: mockModulePath,
|
fs: mockModulePath,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { Media } from './payload-types';
|
|||||||
import payload from '../../src';
|
import payload from '../../src';
|
||||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadE2E } from '../helpers/configHelpers';
|
import { initPayloadE2E } from '../helpers/configHelpers';
|
||||||
import { login, saveDocAndAssert } from '../e2e/helpers';
|
import { login, saveDocAndAssert } from '../helpers';
|
||||||
import wait from '../../src/utilities/wait';
|
import wait from '../../src/utilities/wait';
|
||||||
|
|
||||||
const { beforeAll, describe } = test;
|
const { beforeAll, describe } = test;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect, test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
import { AdminUrlUtil } from '../../helpers/adminUrlUtil';
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||||
import { initPayloadTest } from '../../helpers/configHelpers';
|
import { initPayloadTest } from '../helpers/configHelpers';
|
||||||
import { firstRegister } from '../helpers';
|
import { firstRegister } from '../helpers';
|
||||||
import { slug } from './config';
|
import { slug } from './config';
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ describe('suite name', () => {
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
describe('feature', () => {
|
describe('feature', () => {
|
||||||
test('testname', () => {
|
it('testname', () => {
|
||||||
expect(1).toEqual(1);
|
expect(1).toEqual(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user