Issue template improvements (#2231)

This commit is contained in:
Jarrod Flesch
2023-03-21 22:34:01 -04:00
committed by GitHub
parent e09ebfffa0
commit 2ed7e325b8
13 changed files with 301 additions and 2 deletions

View File

@@ -8,6 +8,24 @@ labels: 'possible-bug'
<!--- Provide a general summary of the issue in the Title above -->
## Expected Behavior
<!--- Tell us what should happen -->
## Current Behavior
<!--- Tell us what happens instead of the expected behavior -->
## Reproduction Fork
<!---
Please fork this repository and recreate your issue in the `/test/_community/` folder. This will help expedite the resolution time for bugs by isolating them in a simpler form.
Please see the [issue guide](https://github.com/payloadcms/payload/blob/master/ISSUE_GUIDE.md) for more information.
IMPORTANT: The goal is to isolate the problem by reducing the number of fields/collections you add to the test/_community folder. This folder is not meant for you to copy your project into, but to recreate the issue you are experiencing with minimal config.
-->
## Steps to Reproduce
<!--- Steps to reproduce this bug. Include any code, if relevant -->

64
ISSUE_GUIDE.md Normal file
View File

@@ -0,0 +1,64 @@
# Reporting an issue
To report an issue, please follow the steps below:
1. Fork this repository
2. Add necessary collections/globals/fields to the `test/_community` directory to recreate the issue you are experiencing
3. Create an issue and add a link to your forked repo
**The goal is to isolate the problem by reducing the number of fields/collections you add to the test/_community folder. This folder is not meant for you to copy your project into, but to recreate the issue you are experiencing with minimal config.**
## Test directory file tree explanation
```text
.
├── config.ts
├── int.spec.ts
├── e2e.spec.ts
└── payload-types.ts
```
- `config.ts` - This is the _granular_ Payload config for testing. It should be as lightweight as possible. Reference existing configs for an example
- `int.spec.ts` [Optional] - This is the test file run by jest. Any test file must have a `*int.spec.ts` suffix.
- `e2e.spec.ts` [Optional] - This is the end-to-end test file that will load up the admin UI using the above config and run Playwright tests.
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `yarn dev:generate-types _community`.
The directory split up in this way specifically to reduce friction when creating tests and to add the ability to boot up Payload with that specific config. You should modify the files in `test/_community` to get started.
## How to start test collection admin UI
To start the admin panel so you can manually recreate your issue, you can run the following command:
```bash
# This command will start up Payload using your config
# NOTE: it will wipe the test database on restart
yarn dev _community
```
## Testing is optional but encouraged
An issue does not need to have failing tests — reproduction steps with your forked repo are enough at this point. Some people like to dive deeper and we want to give you the guidance/tools to do so. Read more below.
### How to run integration tests (Payload API tests)
There are a couple ways to do this:
- **Granularly** - you can run individual tests in vscode by installing the Jest Runner plugin and using that to run individual tests. Clicking the `debug` button will run the test in debug mode allowing you to set break points.
<img src="https://raw.githubusercontent.com/payloadcms/payload/master/src/admin/assets/images/github/int-debug.png" />
- **Manually** - you can run all int tests in the `/test/_community/int.spec.ts` file by running the following command:
```bash
yarn test:int _community
```
### How to run E2E tests (Admin Panel UI tests)
The easiest way to run E2E tests is to install
- [Playwright Test for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright)
- [Playwright Runner](https://marketplace.visualstudio.com/items?itemName=ortoni.ortoni)
Once they are installed you can open the `testing` tab in vscode sidebar and drill down to the test you want to run, i.e. `/test/_community/e2e.spec.ts`
<img src="https://raw.githubusercontent.com/payloadcms/payload/master/src/admin/assets/images/github/e2e-debug.png" />
#### Notes
- It is recommended to add the test credentials (located in `test/credentials.ts`) to your autofill for `localhost:3000/admin` as this will be required on every nodemon restart. The default credentials are `dev@payloadcms.com` as email and `test` as password.

View File

@@ -49,8 +49,6 @@ The directory split up in this way specifically to reduce friction when creating
The following command will start Payload with your config: `yarn dev my-test-dir`. This command will start up Payload using your config and refresh a test database on every restart.
When switching between test directories, you will want to remove your `node_modules/.cache ` manually or by running `yarn clean:cache`.
NOTE: It is recommended to add the test credentials (located in `test/credentials.ts`) to your autofill for `localhost:3000/admin` as this will be required on every nodemon restart. The default credentials are `dev@payloadcms.com` as E-Mail and `test` as password.
## Pull Requests

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,13 @@
import type { CollectionConfig } from '../../../../src/collections/config/types';
export const postsSlug = 'posts';
export const PostsCollection: CollectionConfig = {
slug: postsSlug,
fields: [
{
name: 'text',
type: 'text',
},
],
};

33
test/_community/config.ts Normal file
View File

@@ -0,0 +1,33 @@
import { buildConfig } from '../buildConfig';
import { PostsCollection, postsSlug } from './collections/Posts';
import { MenuGlobal } from './globals/Menu';
import { devUser } from '../credentials';
export default buildConfig({
// ...extend config here
collections: [
PostsCollection,
// ...add more collections here
],
globals: [
MenuGlobal,
// ...add more globals here
],
onInit: async (payload) => {
await payload.create({
collection: 'users',
data: {
email: devUser.email,
password: devUser.password,
},
});
await payload.create({
collection: postsSlug,
data: {
text: 'example post',
},
});
},
});

View File

@@ -0,0 +1,32 @@
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
import { initPayloadE2E } from '../helpers/configHelpers';
import { login } from '../helpers';
const { beforeAll, describe } = test;
let url: AdminUrlUtil;
describe('Admin Panel', () => {
let page: Page;
beforeAll(async ({ browser }) => {
const { serverURL } = await initPayloadE2E(__dirname);
url = new AdminUrlUtil(serverURL, 'posts');
const context = await browser.newContext();
page = await context.newPage();
await login({
page,
serverURL,
});
});
test('example test', async () => {
await page.goto(url.list);
const textCell = page.locator('.row-1 .cell-text');
await expect(textCell).toHaveText('example post');
});
});

View File

@@ -0,0 +1,13 @@
import { GlobalConfig } from '../../../../src/globals/config/types';
export const menuSlug = 'menu';
export const MenuGlobal: GlobalConfig = {
slug: menuSlug,
fields: [
{
name: 'globalText',
type: 'text',
},
],
};

View File

@@ -0,0 +1,73 @@
import mongoose from 'mongoose';
import payload from '../../src';
import { initPayloadTest } from '../helpers/configHelpers';
import { devUser } from '../credentials';
import { postsSlug } from './collections/Posts';
require('isomorphic-fetch');
let apiUrl;
let jwt;
const headers = {
'Content-Type': 'application/json',
};
const { email, password } = devUser;
describe('_Community Tests', () => {
// --__--__--__--__--__--__--__--__--__
// Boilerplate test setup/teardown
// --__--__--__--__--__--__--__--__--__
beforeAll(async () => {
const { serverURL } = await initPayloadTest({ __dirname, init: { local: false } });
apiUrl = `${serverURL}/api`;
const response = await fetch(`${apiUrl}/users/login`, {
body: JSON.stringify({
email,
password,
}),
headers,
method: 'post',
});
const data = await response.json();
jwt = data.token;
});
afterAll(async () => {
await mongoose.connection.dropDatabase();
await mongoose.connection.close();
await payload.mongoMemoryServer.stop();
});
// --__--__--__--__--__--__--__--__--__
// You can run tests against the local API or the REST API
// use the tests below as a guide
// --__--__--__--__--__--__--__--__--__
it('local API example', async () => {
const newPost = await payload.create({
collection: postsSlug,
data: {
text: 'LOCAL API EXAMPLE',
},
});
expect(newPost.text).toEqual('LOCAL API EXAMPLE');
});
it('rest API example', async () => {
const newPost = await fetch(`${apiUrl}/${postsSlug}`, {
method: 'POST',
headers: {
...headers,
Authorization: `JWT ${jwt}`,
},
body: JSON.stringify({
text: 'REST API EXAMPLE',
}),
}).then((res) => res.json());
expect(newPost.doc.text).toEqual('REST API EXAMPLE');
});
});

View File

@@ -0,0 +1,37 @@
/* 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 {
collections: {
posts: Post;
users: User;
};
globals: {
menu: Menu;
};
}
export interface Post {
id: string;
text?: string;
createdAt: string;
updatedAt: string;
}
export interface User {
id: string;
email?: string;
resetPasswordToken?: string;
resetPasswordExpiration?: string;
loginAttempts?: number;
lockUntil?: string;
createdAt: string;
updatedAt: string;
password?: string;
}
export interface Menu {
id: string;
globalText?: string;
}

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"paths": {
"payload/generated-types": [
"./payload-types.ts"
]
}
}
}

View File

@@ -9,6 +9,7 @@ export interface Config {
collections: {
'autosave-posts': AutosavePost;
'draft-posts': DraftPost;
'version-posts': VersionPost;
users: User;
};
globals: {
@@ -34,6 +35,13 @@ export interface DraftPost {
createdAt: string;
updatedAt: string;
}
export interface VersionPost {
id: string;
title: string;
description: string;
createdAt: string;
updatedAt: string;
}
export interface User {
id: string;
email?: string;
@@ -43,6 +51,7 @@ export interface User {
lockUntil?: string;
createdAt: string;
updatedAt: string;
password?: string;
}
export interface AutosaveGlobal {
id: string;