├── block ├── Save.js ├── index.js ├── block.json ├── Edit.js ├── __snapshots__ │ └── Edit.test.js.snap └── Edit.test.js ├── .github └── workflows │ └── test-js.yml ├── .gitignore ├── makeZip.js ├── testing-react-wordpress.php ├── package.json ├── webpack.config.js ├── docker-compose.yml └── README.md /block/Save.js: -------------------------------------------------------------------------------- 1 | import { __ } from '@wordpress/i18n'; 2 | import { useBlockProps } from '@wordpress/block-editor'; 3 | 4 | export default function save({ attributes }) { 5 | return
{attributes.content}
; 6 | } -------------------------------------------------------------------------------- /block/index.js: -------------------------------------------------------------------------------- 1 | 2 | import { registerBlockType } from "@wordpress/blocks"; 3 | import Edit from './Edit'; 4 | import Save from './Save'; 5 | 6 | const blockConfig = require('./block.json'); 7 | registerBlockType(blockConfig.name, { 8 | ...blockConfig, 9 | edit: Edit, 10 | save: Save 11 | }); -------------------------------------------------------------------------------- /.github/workflows/test-js.yml: -------------------------------------------------------------------------------- 1 | name: JavaScripts 2 | 3 | on: [push] 4 | 5 | jobs: 6 | buildAndTest: 7 | name: Test 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v1 11 | - uses: actions/setup-node@v1 12 | with: 13 | node-version: "12" 14 | - name: Install dependencies 15 | run: yarn 16 | - name: Test 17 | run: yarn test --ci 18 | -------------------------------------------------------------------------------- /block/block.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testing-react-wordpress/block", 3 | "title": "Testing block", 4 | "description": "BLOCK DESCRIPTION", 5 | "attributes": { 6 | "content": { 7 | "type": "string", 8 | "default": "Hi Roy" 9 | } 10 | }, 11 | "category": "widgets", 12 | "icon": "smiley", 13 | "supports": { 14 | "html": false 15 | } 16 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | lerna-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Dependency directories 14 | node_modules/ 15 | vendor/ 16 | 17 | # dotenv environment variables file 18 | .env 19 | .env.test 20 | 21 | vendor 22 | wordpress 23 | build 24 | .phpunit.result.cache -------------------------------------------------------------------------------- /makeZip.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var archiver = require('archiver'); 3 | 4 | var output = fs.createWriteStream('test-react-wordpress.zip'); 5 | var archive = archiver('zip'); 6 | 7 | console.log( 'Zipping!') 8 | output.on('close', function () { 9 | console.log('Zipped!'); 10 | console.log(archive.pointer() + ' total bytes'); 11 | }); 12 | 13 | archive.on('error', function(err){ 14 | throw err; 15 | }); 16 | 17 | archive.pipe(output); 18 | 19 | archive.append(fs.createReadStream( 20 | __dirname + '/test-react-wordpress.php' 21 | ), { name: 'test-react-wordpress.php' }); 22 | 23 | archive.directory('build', '/build'); 24 | 25 | archive.finalize(); -------------------------------------------------------------------------------- /testing-react-wordpress.php: -------------------------------------------------------------------------------- 1 | 'testing-react-wordpress-block', 23 | ]); 24 | 25 | 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | {"name":"test-react-wordpress","private":true,"version":"0.1.0","license":"GPL-2.0-or-later","main":"build/index.js","scripts":{"test":"yarn test:unit","test:unit":"wp-scripts test-unit-js","build":"wp-scripts build","test:ci":"wp-scripts test-unit-js --ci","format:js":"wp-scripts format-js","lint:css":"wp-scripts lint-style","lint:js":"wp-scripts lint-js","start":"wp-scripts start","zip":"yarn build && node makeZip.js"},"devDependencies":{"@babel/core":"^7","@testing-library/react":"@latest","@wordpress/scripts":"@latest"},"dependencies":{"@axe-core/react":"^4.0.0","@wordpress/block-editor":"@latest","@wordpress/blocks":"@latest","@wordpress/components":"@latest","@wordpress/element":"@latest","@wordpress/i18n":"@latest","@wordpress/scripts":"@latest"}} -------------------------------------------------------------------------------- /block/Edit.js: -------------------------------------------------------------------------------- 1 | import { TextControl } from '@wordpress/components'; 2 | import { __ } from '@wordpress/i18n'; 3 | import { useBlockProps } from '@wordpress/block-editor'; 4 | 5 | export const Editor = ({ value, onChange, isSelected }) => ( 6 | <> 7 | {isSelected ? 8 | :

{value}

12 | } 13 | 14 | ); 15 | export default function Edit({ attributes, setAttributes, isSelected }) { 16 | return ( 17 |
18 | setAttributes({ content })} /> 19 |
20 | ); 21 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const defaultConfig = require("@wordpress/scripts/config/webpack.config"); 2 | const path = require("path"); 3 | const isProduction = "production" === process.env.NODE_ENV; 4 | 5 | let entry = {}; 6 | /** 7 | * Array of entry points 8 | */ 9 | let entryPoints = ["block"] 10 | 11 | entryPoints.forEach( 12 | (entryPoint) => { 13 | entry[entryPoint] = path.resolve(process.cwd(), `${entryPoint}/index.js`); 14 | } 15 | ); 16 | module.exports = { 17 | mode: isProduction ? "production" : "development", 18 | ...defaultConfig, 19 | module: { 20 | ...defaultConfig.module, 21 | rules: [ 22 | ...defaultConfig.module.rules, 23 | { 24 | test: /\.css$/, 25 | use: ["style-loader", "css-loader"], 26 | }, 27 | ], 28 | }, 29 | entry, 30 | output: { 31 | filename: "[name].js", 32 | path: path.join(__dirname, "/build"), 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | #https://docs.docker.com/samples/wordpress/ 3 | version: "3.9" 4 | 5 | services: 6 | db: 7 | image: mysql:5.7 8 | volumes: 9 | - db_data:/var/lib/mysql 10 | restart: always 11 | environment: 12 | MYSQL_ROOT_PASSWORD: somewordpress 13 | MYSQL_DATABASE: wordpress 14 | MYSQL_USER: wordpress 15 | MYSQL_PASSWORD: wordpress 16 | 17 | wordpress: 18 | depends_on: 19 | - db 20 | image: wordpress:latest 21 | volumes: 22 | - wordpress_data:/var/www/html 23 | - ./:/var/www/html/wp-content/plugins/testing-react-wordpress 24 | 25 | ports: 26 | - "8000:80" 27 | restart: always 28 | environment: 29 | WORDPRESS_DB_HOST: db:3306 30 | WORDPRESS_DB_USER: wordpress 31 | WORDPRESS_DB_PASSWORD: wordpress 32 | WORDPRESS_DB_NAME: wordpress 33 | volumes: 34 | db_data: {} 35 | wordpress_data: {} -------------------------------------------------------------------------------- /block/__snapshots__/Edit.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Editor componet matches snapshot when not selected 1`] = ` 4 |
5 |
8 |
11 | 17 |
18 |
19 |
20 | `; 21 | 22 | exports[`Editor componet matches snapshot when selected 1`] = ` 23 |
24 |
27 |
30 | 36 |
37 |
38 |
39 | `; 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Testing JavaScript In And Around WordPress: Part 2 Example Code 2 | 3 | * [JavaScript Testing In And Around WordPress](https://shelob9.github.io/testing-javascript-in-and-around-wordpress) 4 | 5 | ## Development Quick Start 6 | 7 | - Git clone: 8 | - `git clone git@github.com:shelob9/testing-react-wordpress.git` 9 | - Install. 10 | - `yarn` 11 | - Build JS/CSS 12 | - `yarn build` 13 | - Start JS/CSS for development 14 | - `yarn start` 15 | - Test changed files 16 | - `yarn test --watch` 17 | - Test all files once 18 | - `yarn test` 19 | - `yarn test --ci` 20 | - Create an installable zip file of your plugin. 21 | - `yarn zip` 22 | 23 | ### To Add A New Entry Point 24 | 25 | If you want to add additional entry points, for example if you want to add blocks or to have separate JavaScript/ CSS for the front-end, follow these steps: 26 | 27 | - Choose a one word handle for the entry point 28 | - Create a directory named for the handle. 29 | - Add an index.js file to that directory 30 | - Add the handle to the array `entryPoints` in webpack.config.js 31 | - Run `yarn build` 32 | - Check that `build/$handle.js` and `build/$handle.asset.php` where created. 33 | 34 | ## Local Development 35 | 36 | - `docker-compose up -d` 37 | - [http://localhost:8000/](http://localhost:8000/) 38 | 39 | ## Contributing 40 | 41 | Please feel free to [open a pull request](https://github.com/shelob9/test-react-wordpress/pulls) if you would like to contribute. -------------------------------------------------------------------------------- /block/Edit.test.js: -------------------------------------------------------------------------------- 1 | 2 | //Import React 3 | import React from 'react'; 4 | //Import test renderer 5 | import { render, fireEvent, cleanup } from '@testing-library/react'; 6 | //Import component to test 7 | import { Editor } from './Edit'; 8 | 9 | 10 | describe("Editor componet", () => { 11 | afterEach(cleanup); 12 | it('matches snapshot when selected', () => { 13 | const onChange = jest.fn(); 14 | const { container } = render(); 19 | expect(container).toMatchSnapshot(); 20 | }); 21 | 22 | it('matches snapshot when not selected', () => { 23 | const onChange = jest.fn(); 24 | const { container } = render(); 29 | expect(container).toMatchSnapshot(); 30 | }); 31 | 32 | it("Calls the onchange function", () => { 33 | const onChange = jest.fn(); 34 | const { getByDisplayValue } = render(); 39 | fireEvent.change(getByDisplayValue("Salad"), { 40 | target: { value: "New Value" } 41 | }); 42 | expect(onChange).toHaveBeenCalledTimes(1); 43 | }); 44 | 45 | it("Passes updated value, not event to onChange callback", () => { 46 | const onChange = jest.fn(); 47 | const { getByDisplayValue } = render(); 52 | fireEvent.change(getByDisplayValue("Seltzer"), { 53 | target: { value: "Boring Water" } 54 | }); 55 | expect(onChange).toHaveBeenCalledWith("Boring Water"); 56 | }); 57 | }); --------------------------------------------------------------------------------