|
| 1 | +# Best Practices Guide |
| 2 | + |
| 3 | +This document outlines best practices for developing plugins in React and TypeScript for the [Cortex.io](http://cortex.io/) Plugin Community. Following these guidelines ensures consistent, maintainable, and high-quality plugins. |
| 4 | + |
| 5 | +## Project Structure |
| 6 | + |
| 7 | +Plugins should be Scaffolded in Cortex using the “Cortex Plugin” template and will match the following project structure: |
| 8 | + |
| 9 | +```jsx |
| 10 | +__mocks__/ |
| 11 | +src/ |
| 12 | + api/ |
| 13 | + Cortex.ts |
| 14 | + assets/ |
| 15 | + logo.svg |
| 16 | + components/ |
| 17 | + App.test.tsx |
| 18 | + App.tsx |
| 19 | + ErrorBoundary.tsx |
| 20 | + PluginContext.tsx |
| 21 | + baseStyles.css |
| 22 | + index.html |
| 23 | + index.tsx |
| 24 | + typings.d.ts |
| 25 | +.eslintignore |
| 26 | +.eslintrc.js |
| 27 | +.gitignore |
| 28 | +.prettierignore |
| 29 | +README.md |
| 30 | +babel.config.js |
| 31 | +cortex.yaml |
| 32 | +jest.config.js |
| 33 | +package.json |
| 34 | +setupTests.ts |
| 35 | +tsconfig.json |
| 36 | +webpack.config.js |
| 37 | +``` |
| 38 | + |
| 39 | +## Code Style |
| 40 | + |
| 41 | +1. **Linting and Formatting**: |
| 42 | + - Use **ESLint** with React and TypeScript plugins to enforce consistent code style. |
| 43 | + - Use **Prettier** for formatting. Configure Prettier to auto-format code on save. |
| 44 | + |
| 45 | +### Configuration for ESLint |
| 46 | + |
| 47 | +``` |
| 48 | +// .eslintrc.js |
| 49 | +module.exports = { |
| 50 | + env: { |
| 51 | + browser: true, |
| 52 | + es2021: true, |
| 53 | + }, |
| 54 | + extends: [ |
| 55 | + "plugin:react/jsx-runtime", |
| 56 | + "plugin:react-hooks/recommended", |
| 57 | + "standard-with-typescript", |
| 58 | + "prettier", |
| 59 | + ], |
| 60 | + overrides: [], |
| 61 | + parserOptions: { |
| 62 | + ecmaVersion: "latest", |
| 63 | + project: "tsconfig.json", |
| 64 | + sourceType: "module", |
| 65 | + tsconfigRootDir: __dirname, |
| 66 | + }, |
| 67 | + plugins: ["react"], |
| 68 | + rules: { |
| 69 | + // conflicts with no-extra-boolean-cast |
| 70 | + "@typescript-eslint/strict-boolean-expressions": "off", |
| 71 | + "no-console": ["error", { allow: ["warn", "error"] }], |
| 72 | + }, |
| 73 | + settings: { |
| 74 | + react: { |
| 75 | + version: "detect", |
| 76 | + }, |
| 77 | + }, |
| 78 | +}; |
| 79 | +``` |
| 80 | + |
| 81 | +## Unit Testing |
| 82 | + |
| 83 | +- **Coverage Requirement**: Aim for 80% test coverage. Prioritize testing key functions and complex logic. You can use Istanbul (baked into Yarn) to check your coverage, like: |
| 84 | + |
| 85 | +```markup |
| 86 | +yarn test --coverage |
| 87 | +``` |
| 88 | + |
| 89 | +- **Testing Library**: Use **Jest** and **React Testing Library** for unit tests. |
| 90 | +- **Testing Standards**: |
| 91 | + - Test each component’s rendered output. |
| 92 | + - Mock API calls and test component behavior based on different responses. |
| 93 | + - Test edge cases and error handling. |
| 94 | + |
| 95 | +## Example Unit Test |
| 96 | + |
| 97 | +```jsx |
| 98 | + it("Shows a page if page is found", async () => { |
| 99 | + fetchMock.mockResponses( |
| 100 | + [JSON.stringify(serviceYaml), { status: 200 }], |
| 101 | + [JSON.stringify(mockPageContent), { status: 200 }] |
| 102 | + ); |
| 103 | + |
| 104 | + render(<PageContent />); |
| 105 | + await waitFor(() => { |
| 106 | + expect(screen.queryByText("AppDirect Runbook")).toBeInTheDocument(); |
| 107 | + }); |
| 108 | + }); |
| 109 | +``` |
| 110 | + |
| 111 | +## Documentation and Comments |
| 112 | + |
| 113 | +1. **README**: Provide a clear README file for each plugin with installation, usage, and basic configuration instructions, ideally with a screenshot of the plugin. |
| 114 | +2. Clearly document which types of entities the plugin is compatible with |
| 115 | +3. **Code Comments**: |
| 116 | + - Use comments sparingly for complex logic or non-obvious code. |
| 117 | + - Avoid redundant comments that describe straightforward code. |
0 commit comments