<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Marcusgreen</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Marcusgreen"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Marcusgreen"/>
	<updated>2026-07-30T00:33:24Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=64316</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=64316"/>
		<updated>2025-01-25T06:09:28Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: Pointing to the new documentation link for this topic&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The new place for documenting this is &lt;br /&gt;
&lt;br /&gt;
https://moodledev.io/general/development/tools/phpcs#editor-integrations&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy php.ini is being loaded.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
Out-of-the box VSCode does not provide [https://code.visualstudio.com/docs/editor/intellisense intellisense] for PHP.&lt;br /&gt;
&lt;br /&gt;
Recommended extensions are: either [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] or [https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode PHP (Devsense)] (do not enable both of them at once as they will duplicate results).&lt;br /&gt;
&lt;br /&gt;
Example configuration for the PHP (Devsense):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;quot;php.executablePath&amp;quot;: &amp;quot;/usr/bin/php&amp;quot;,&lt;br /&gt;
    &amp;quot;php.problems.exclude&amp;quot;: {&lt;br /&gt;
        &amp;quot;/&amp;quot; : [6601, 419]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;phpunit.phpunit&amp;quot;: &amp;quot;./vendor/bin/phpunit&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==MDLCode Wizards==&lt;br /&gt;
The MDLCode plugin is specifically for Moodle development and includes a suite of wizards to ease the creation of common chunks of Moodle code. It will also&lt;br /&gt;
show if strings in a language file are unused.&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=LMSCloud.mdlcode&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Install the Moodle coding standard with composer as follows&lt;br /&gt;
 composer global require moodlehq/moodle-cs&lt;br /&gt;
Tell phpcs to use the standard&lt;br /&gt;
 phpcs --config-set installed_paths ~/.config/composer/vendor/moodlehq/moodle-cs&lt;br /&gt;
Confirm that configuration has worked by issuing the command&lt;br /&gt;
 phpcs -i&lt;br /&gt;
You should see the text &amp;quot;The installed coding standards are ....&amp;quot; and one of them should be moodle&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
Following extensions will help with Behat .feature files (which use the cucumber language) &lt;br /&gt;
&lt;br /&gt;
Colour syntax highlighting &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
Beautification (indentation) &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
==Automated testing==&lt;br /&gt;
PHP (Devsense) mentioned [[#Intellisense|above]] can be set up to run unittests from within VSCode.&lt;br /&gt;
&lt;br /&gt;
Alternatively you can use [https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] .&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png|666x666px]]&lt;br /&gt;
== JSDoc==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=crystal-spider.jsdoc-generator will create JSDoc blocks by typing /** at the top of the function. Select the Autogenerated JSdoc option and it will create a template for the description, parameter and return types.&lt;br /&gt;
==Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Javascript==&lt;br /&gt;
VSCode provides Intellisense for Javascript and allows to navigate between ES6 modules. To make it resolve paths inside Moodle you need to create jsconfig.json file and place it in Moodle root. You can run&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
grunt jsconfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to generate jsconfig.json. See also [[Grunt]] documentation.&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;br /&gt;
The configuration of file launch.json in Visual Studio Code should be integrated with hostname as follows:&lt;br /&gt;
&amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;hostname&amp;quot;: &amp;quot;IP address of remote server&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003&lt;br /&gt;
        },&lt;br /&gt;
The file php.ini where Moodle is running should be updated: the default value of xdebug.client_host&#039;s parameter should be replaced with IP address of remote server. The default value is localhost.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63990</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63990"/>
		<updated>2023-08-31T09:45:43Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Changed heading from Wizards to MDLCode Wizards */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy php.ini is being loaded.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
Out-of-the box VSCode does not provide [https://code.visualstudio.com/docs/editor/intellisense intellisense] for PHP.&lt;br /&gt;
&lt;br /&gt;
Recommended extensions are: either [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] or [https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode PHP (Devsense)] (do not enable both of them at once as they will duplicate results).&lt;br /&gt;
&lt;br /&gt;
Example configuration for the PHP (Devsense):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;quot;php.executablePath&amp;quot;: &amp;quot;/usr/bin/php&amp;quot;,&lt;br /&gt;
    &amp;quot;php.problems.exclude&amp;quot;: {&lt;br /&gt;
        &amp;quot;/&amp;quot; : [6601, 419]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;phpunit.phpunit&amp;quot;: &amp;quot;./vendor/bin/phpunit&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==MDLCode Wizards==&lt;br /&gt;
The MDLCode plugin is specifically for Moodle development and includes a suite of wizards to ease the creation of common chunks of Moodle code. It will also&lt;br /&gt;
show if strings in a language file are unused.&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=LMSCloud.mdlcode&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Install the Moodle coding standard with composer as follows&lt;br /&gt;
 composer global require moodlehq/moodle-cs&lt;br /&gt;
Tell phpcs to use the standard&lt;br /&gt;
 phpcs --config-set installed_paths ~/.config/composer/vendor/moodlehq/moodle-cs&lt;br /&gt;
Confirm that configuration has worked by issuing the command&lt;br /&gt;
 phpcs -i&lt;br /&gt;
You should see the text &amp;quot;The installed coding standards are ....&amp;quot; and one of them should be moodle&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
Following extensions will help with Behat .feature files (which use the cucumber language) &lt;br /&gt;
&lt;br /&gt;
Colour syntax highlighting &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
Beautification (indentation) &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
==Automated testing==&lt;br /&gt;
PHP (Devsense) mentioned [[#Intellisense|above]] can be set up to run unittests from within VSCode.&lt;br /&gt;
&lt;br /&gt;
Alternatively you can use [https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] .&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png|666x666px]]&lt;br /&gt;
== JSDoc==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=crystal-spider.jsdoc-generator will create JSDoc blocks by typing /** at the top of the function. Select the Autogenerated JSdoc option and it will create a template for the description, parameter and return types.&lt;br /&gt;
==Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Javascript==&lt;br /&gt;
VSCode provides Intellisense for Javascript and allows to navigate between ES6 modules. To make it resolve paths inside Moodle you need to create jsconfig.json file and place it in Moodle root. You can run&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
grunt jsconfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to generate jsconfig.json. See also [[Grunt]] documentation.&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;br /&gt;
The configuration of file launch.json in Visual Studio Code should be integrated with hostname as follows:&lt;br /&gt;
&amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;hostname&amp;quot;: &amp;quot;IP address of remote server&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003&lt;br /&gt;
        },&lt;br /&gt;
The file php.ini where Moodle is running should be updated: the default value of xdebug.client_host&#039;s parameter should be replaced with IP address of remote server. The default value is localhost.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63989</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63989"/>
		<updated>2023-08-31T09:45:02Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* MDL Code plugin link */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy php.ini is being loaded.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
Out-of-the box VSCode does not provide [https://code.visualstudio.com/docs/editor/intellisense intellisense] for PHP.&lt;br /&gt;
&lt;br /&gt;
Recommended extensions are: either [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] or [https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode PHP (Devsense)] (do not enable both of them at once as they will duplicate results).&lt;br /&gt;
&lt;br /&gt;
Example configuration for the PHP (Devsense):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;quot;php.executablePath&amp;quot;: &amp;quot;/usr/bin/php&amp;quot;,&lt;br /&gt;
    &amp;quot;php.problems.exclude&amp;quot;: {&lt;br /&gt;
        &amp;quot;/&amp;quot; : [6601, 419]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;phpunit.phpunit&amp;quot;: &amp;quot;./vendor/bin/phpunit&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Wizards==&lt;br /&gt;
The MDLCode plugin is specifically for Moodle development and includes a suite of wizards to ease the creation of common chunks of Moodle code. It will also &lt;br /&gt;
show if strings in a language file are unused.&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=LMSCloud.mdlcode&lt;br /&gt;
&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Install the Moodle coding standard with composer as follows&lt;br /&gt;
 composer global require moodlehq/moodle-cs&lt;br /&gt;
Tell phpcs to use the standard&lt;br /&gt;
 phpcs --config-set installed_paths ~/.config/composer/vendor/moodlehq/moodle-cs&lt;br /&gt;
Confirm that configuration has worked by issuing the command&lt;br /&gt;
 phpcs -i&lt;br /&gt;
You should see the text &amp;quot;The installed coding standards are ....&amp;quot; and one of them should be moodle&lt;br /&gt;
&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
Following extensions will  help with Behat .feature files (which use the cucumber language) &lt;br /&gt;
&lt;br /&gt;
Colour syntax highlighting &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight &lt;br /&gt;
&lt;br /&gt;
Beautification (indentation) &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin &lt;br /&gt;
==Automated testing==&lt;br /&gt;
PHP (Devsense) mentioned [[#Intellisense|above]] can be set up to run unittests from within VSCode.&lt;br /&gt;
&lt;br /&gt;
Alternatively you can use [https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] .&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png|666x666px]]&lt;br /&gt;
== JSDoc==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=crystal-spider.jsdoc-generator will create JSDoc blocks by typing /** at the top of the function. Select the Autogenerated JSdoc option and it will create a template for the description, parameter and return types.&lt;br /&gt;
==Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Javascript==&lt;br /&gt;
VSCode provides Intellisense for Javascript and allows to navigate between ES6 modules. To make it resolve paths inside Moodle you need to create jsconfig.json file and place it in Moodle root. You can run&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
grunt jsconfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to generate jsconfig.json. See also [[Grunt]] documentation.&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;br /&gt;
The configuration of file launch.json in Visual Studio Code should be integrated with hostname as follows:&lt;br /&gt;
&amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;hostname&amp;quot;: &amp;quot;IP address of remote server&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003&lt;br /&gt;
        },&lt;br /&gt;
The file php.ini where Moodle is running should be updated: the default value of xdebug.client_host&#039;s parameter should be replaced with IP address of remote server. The default value is localhost.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63988</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63988"/>
		<updated>2023-08-31T09:42:36Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Behat/Gherkin/Cucumber Colour syntax and  Formatting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy php.ini is being loaded.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
Out-of-the box VSCode does not provide [https://code.visualstudio.com/docs/editor/intellisense intellisense] for PHP.&lt;br /&gt;
&lt;br /&gt;
Recommended extensions are: either [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] or [https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode PHP (Devsense)] (do not enable both of them at once as they will duplicate results).&lt;br /&gt;
&lt;br /&gt;
Example configuration for the PHP (Devsense):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;quot;php.executablePath&amp;quot;: &amp;quot;/usr/bin/php&amp;quot;,&lt;br /&gt;
    &amp;quot;php.problems.exclude&amp;quot;: {&lt;br /&gt;
        &amp;quot;/&amp;quot; : [6601, 419]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;phpunit.phpunit&amp;quot;: &amp;quot;./vendor/bin/phpunit&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Install the Moodle coding standard with composer as follows&lt;br /&gt;
 composer global require moodlehq/moodle-cs&lt;br /&gt;
Tell phpcs to use the standard&lt;br /&gt;
 phpcs --config-set installed_paths ~/.config/composer/vendor/moodlehq/moodle-cs&lt;br /&gt;
Confirm that configuration has worked by issuing the command&lt;br /&gt;
 phpcs -i&lt;br /&gt;
You should see the text &amp;quot;The installed coding standards are ....&amp;quot; and one of them should be moodle&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
Following extensions will  help with Behat .feature files (which use the cucumber language) &lt;br /&gt;
&lt;br /&gt;
Colour syntax highlighting &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight &lt;br /&gt;
&lt;br /&gt;
Beautification (indentation) &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin &lt;br /&gt;
==Automated testing==&lt;br /&gt;
PHP (Devsense) mentioned [[#Intellisense|above]] can be set up to run unittests from within VSCode.&lt;br /&gt;
&lt;br /&gt;
Alternatively you can use [https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] .&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png|666x666px]]&lt;br /&gt;
== JSDoc==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=crystal-spider.jsdoc-generator will create JSDoc blocks by typing /** at the top of the function. Select the Autogenerated JSdoc option and it will create a template for the description, parameter and return types.&lt;br /&gt;
==Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Javascript==&lt;br /&gt;
VSCode provides Intellisense for Javascript and allows to navigate between ES6 modules. To make it resolve paths inside Moodle you need to create jsconfig.json file and place it in Moodle root. You can run&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
grunt jsconfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to generate jsconfig.json. See also [[Grunt]] documentation.&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;br /&gt;
The configuration of file launch.json in Visual Studio Code should be integrated with hostname as follows:&lt;br /&gt;
&amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;hostname&amp;quot;: &amp;quot;IP address of remote server&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003&lt;br /&gt;
        },&lt;br /&gt;
The file php.ini where Moodle is running should be updated: the default value of xdebug.client_host&#039;s parameter should be replaced with IP address of remote server. The default value is localhost.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63932</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63932"/>
		<updated>2023-06-29T09:45:57Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* JSDoc Link to vscode plugin that will help create JSdoc blocks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy php.ini is being loaded.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
Out-of-the box VSCode does not provide [https://code.visualstudio.com/docs/editor/intellisense intellisense] for PHP.&lt;br /&gt;
&lt;br /&gt;
Recommended extensions are: either [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] or [https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode PHP (Devsense)] (do not enable both of them at once as they will duplicate results).&lt;br /&gt;
&lt;br /&gt;
Example configuration for the PHP (Devsense):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;quot;php.executablePath&amp;quot;: &amp;quot;/usr/bin/php&amp;quot;,&lt;br /&gt;
    &amp;quot;php.problems.exclude&amp;quot;: {&lt;br /&gt;
        &amp;quot;/&amp;quot; : [6601, 419]&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;phpunit.phpunit&amp;quot;: &amp;quot;./vendor/bin/phpunit&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Install the Moodle coding standard with composer as follows&lt;br /&gt;
 composer global require moodlehq/moodle-cs&lt;br /&gt;
Tell phpcs to use the standard&lt;br /&gt;
 phpcs --config-set installed_paths ~/.config/composer/vendor/moodlehq/moodle-cs&lt;br /&gt;
Confirm that configuration has worked by issuing the command&lt;br /&gt;
 phpcs -i&lt;br /&gt;
You should see the text &amp;quot;The installed coding standards are ....&amp;quot; and one of them should be moodle&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
Following extensions colour syntax formatting for behat .feature files. &lt;br /&gt;
* https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
* https://marketplace.visualstudio.com/items?itemName=stevejpurves.cucumber&lt;br /&gt;
Formatting tables:&lt;br /&gt;
* https://marketplace.visualstudio.com/items?itemName=shuworks.vscode-table-formatter&lt;br /&gt;
==Automated testing==&lt;br /&gt;
PHP (Devsense) mentioned [[#Intellisense|above]] can be set up to run unittests from within VSCode.&lt;br /&gt;
&lt;br /&gt;
Alternatively you can use [https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] .&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png|666x666px]]&lt;br /&gt;
== JSDoc==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=crystal-spider.jsdoc-generator will create JSDoc blocks by typing /** at the top of the function. Select the Autogenerated JSdoc option and it will create a template for the description, parameter and return types.&lt;br /&gt;
==Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Javascript==&lt;br /&gt;
VSCode provides Intellisense for Javascript and allows to navigate between ES6 modules. To make it resolve paths inside Moodle you need to create jsconfig.json file and place it in Moodle root. You can run&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sh&amp;quot;&amp;gt;&lt;br /&gt;
grunt jsconfig&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to generate jsconfig.json. See also [[Grunt]] documentation.&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;br /&gt;
The configuration of file launch.json in Visual Studio Code should be integrated with hostname as follows:&lt;br /&gt;
&amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;hostname&amp;quot;: &amp;quot;IP address of remote server&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003&lt;br /&gt;
        },&lt;br /&gt;
The file php.ini where Moodle is running should be updated: the default value of xdebug.client_host&#039;s parameter should be replaced with IP address of remote server. The default value is localhost.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Output_callbacks&amp;diff=63858</id>
		<title>Output callbacks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Output_callbacks&amp;diff=63858"/>
		<updated>2023-03-27T10:00:13Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* before_footer converted MDL ticket to hyperlink*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are cases where we want any plugin to contribute to a chunk of the output of any given page. We want this to be loosely coupled so you don&#039;t have say an admin tool&#039;s code leaking into your theme. In the past many plugins had an installation step like &amp;quot;Copy this into your theme header&amp;quot; which is what we want to completely avoid.&lt;br /&gt;
&lt;br /&gt;
There are a variety of [[Callbacks]] which enable any plugin to add or modify certain parts of the output and at certain stages in the rendering process. These callbacks are probably most useful for local plugins or admin tools which bring some functionality to the whole site instead of just certain pages. But they can also be used by any plugin to conditionally augment the output too.&lt;br /&gt;
= add_htmlattributes =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This is used to append extra attributes into the html element of the page which are required elsewhere. An example might be a facebook block plugin which uses the opengraph js libraries which need the xml namespace to be setup. It should return an array of attribute key and values like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_facebook_add_htmlattributes() {&lt;br /&gt;
     return array(&lt;br /&gt;
         &#039;xmlns:og&#039; =&amp;gt; &#039;http://ogp.me/ns#&#039;,&lt;br /&gt;
     );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Because multiple plugins can add extra attributes there is potential namespace clash issues. ie in the Facebook opengraph example stick with &amp;quot;xmlns:og&amp;quot; as specified by Facebook so that if multiple plugins declare the same key / value then they will match. Not that duplicates attribute keys are merged.&lt;br /&gt;
= before_footer =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This enables you to easily inject a chunk of JS or CSS into every page, for instance an analytics tool like Google Analytics or Facebook pixel. If a string is returned, it will be added to the page, as described in https://tracker.moodle.org/browse/MDL-68564&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_mytool_before_footer() {&lt;br /&gt;
    global $PAGE;&lt;br /&gt;
   $PAGE-&amp;gt;requires-&amp;gt;js_init_code(&amp;quot;alert(&#039;before_footer&#039;);&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
= before_http_headers =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This enables you to easily inject a HTTP header into every page. It only has side effects and it&#039;s return value is ignored:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_headertest_before_http_headers() {&lt;br /&gt;
    header(&amp;quot;X-CustomHeader: SomeValue&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Note that this is called after the page is generated and just prior to the headers being sent. So internal system state may have already been changed (eg adding events to the log) and the page generation may have been expensive and the student will be considered to have viewed the page.&lt;br /&gt;
&lt;br /&gt;
You should generally not use this callback for things like redirecting away under some conditions, instead consider either the [[Login_callbacks#after_config|after_config]] or the [[Login_callbacks#after_require_login|after_require_login]] callbacks which fire earlier in the request lifecycle.&lt;br /&gt;
= before_standard_html_head =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This is an API alternative to appending to $CFG-&amp;gt;additionalhtmlhead and could be used for adding meta tags or similar to the page. It MUST return a string containing a well formed html chunk, or at minimum an empty string.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_headtag_before_standard_html_head() {&lt;br /&gt;
    return &amp;quot;&amp;lt;meta name=&#039;foo&#039; value=&#039;before_top_of_body_html&#039; /&amp;gt;\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
= before_standard_top_of_body_html =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This enables a plugin to insert a chunk of html at the start of the html document. Typical use cases include some sort of alert notification, but in many cases the [[Notifications]] may be a better fit. It MUST return a string containing a well formed chunk of html, or at minimum an empty string.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_callbacktest_before_standard_top_of_body_html() {&lt;br /&gt;
    return &amp;quot;&amp;lt;div style=&#039;background: red&#039;&amp;gt;Before standard top of body html&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
= render_navbar_output =&lt;br /&gt;
{{Moodle 3.2}}&lt;br /&gt;
&lt;br /&gt;
TBA&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Output_callbacks&amp;diff=63857</id>
		<title>Output callbacks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Output_callbacks&amp;diff=63857"/>
		<updated>2023-03-27T09:59:20Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* before_http_headers now returns any string to the page */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are cases where we want any plugin to contribute to a chunk of the output of any given page. We want this to be loosely coupled so you don&#039;t have say an admin tool&#039;s code leaking into your theme. In the past many plugins had an installation step like &amp;quot;Copy this into your theme header&amp;quot; which is what we want to completely avoid.&lt;br /&gt;
&lt;br /&gt;
There are a variety of [[Callbacks]] which enable any plugin to add or modify certain parts of the output and at certain stages in the rendering process. These callbacks are probably most useful for local plugins or admin tools which bring some functionality to the whole site instead of just certain pages. But they can also be used by any plugin to conditionally augment the output too.&lt;br /&gt;
= add_htmlattributes =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This is used to append extra attributes into the html element of the page which are required elsewhere. An example might be a facebook block plugin which uses the opengraph js libraries which need the xml namespace to be setup. It should return an array of attribute key and values like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_facebook_add_htmlattributes() {&lt;br /&gt;
     return array(&lt;br /&gt;
         &#039;xmlns:og&#039; =&amp;gt; &#039;http://ogp.me/ns#&#039;,&lt;br /&gt;
     );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Because multiple plugins can add extra attributes there is potential namespace clash issues. ie in the Facebook opengraph example stick with &amp;quot;xmlns:og&amp;quot; as specified by Facebook so that if multiple plugins declare the same key / value then they will match. Not that duplicates attribute keys are merged.&lt;br /&gt;
= before_footer =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This enables you to easily inject a chunk of JS or CSS into every page, for instance an analytics tool like Google Analytics or Facebook pixel. If a string is returned, it will be added to the page, as described in &amp;lt;nowiki&amp;gt;https://tracker.moodle.org/browse/MDL-68564&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_mytool_before_footer() {&lt;br /&gt;
    global $PAGE;&lt;br /&gt;
   $PAGE-&amp;gt;requires-&amp;gt;js_init_code(&amp;quot;alert(&#039;before_footer&#039;);&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
= before_http_headers =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This enables you to easily inject a HTTP header into every page. It only has side effects and it&#039;s return value is ignored:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_headertest_before_http_headers() {&lt;br /&gt;
    header(&amp;quot;X-CustomHeader: SomeValue&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Note that this is called after the page is generated and just prior to the headers being sent. So internal system state may have already been changed (eg adding events to the log) and the page generation may have been expensive and the student will be considered to have viewed the page.&lt;br /&gt;
&lt;br /&gt;
You should generally not use this callback for things like redirecting away under some conditions, instead consider either the [[Login_callbacks#after_config|after_config]] or the [[Login_callbacks#after_require_login|after_require_login]] callbacks which fire earlier in the request lifecycle.&lt;br /&gt;
= before_standard_html_head =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This is an API alternative to appending to $CFG-&amp;gt;additionalhtmlhead and could be used for adding meta tags or similar to the page. It MUST return a string containing a well formed html chunk, or at minimum an empty string.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_headtag_before_standard_html_head() {&lt;br /&gt;
    return &amp;quot;&amp;lt;meta name=&#039;foo&#039; value=&#039;before_top_of_body_html&#039; /&amp;gt;\n&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
= before_standard_top_of_body_html =&lt;br /&gt;
{{Moodle 3.3}}&lt;br /&gt;
&lt;br /&gt;
This enables a plugin to insert a chunk of html at the start of the html document. Typical use cases include some sort of alert notification, but in many cases the [[Notifications]] may be a better fit. It MUST return a string containing a well formed chunk of html, or at minimum an empty string.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
function tool_callbacktest_before_standard_top_of_body_html() {&lt;br /&gt;
    return &amp;quot;&amp;lt;div style=&#039;background: red&#039;&amp;gt;Before standard top of body html&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
= render_navbar_output =&lt;br /&gt;
{{Moodle 3.2}}&lt;br /&gt;
&lt;br /&gt;
TBA&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63768</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63768"/>
		<updated>2023-01-01T21:22:21Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* PHPCS codesniffing and moodle standards config*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy php.ini is being loaded.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Install the Moodle coding standard with composer as follows&lt;br /&gt;
 composer global require moodlehq/moodle-cs&lt;br /&gt;
Tell phpcs to use the standard&lt;br /&gt;
 phpcs --config-set installed_paths ~/.config/composer/vendor/moodlehq/moodle-cs&lt;br /&gt;
Confirm that configuration has worked by issuing the command&lt;br /&gt;
 phpcs -i&lt;br /&gt;
You should see the text &amp;quot;The installed coding standards  are ....&amp;quot; and one of them should be moodle&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
&lt;br /&gt;
Search on the string siarheikuchuk in the vscode extensions dialog.&lt;br /&gt;
The following settings will confirm to Moodles expectations.&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.And&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Scenario&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Given&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Table&amp;quot;: 8,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Then&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.When&amp;quot;: 4&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space ==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63700</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63700"/>
		<updated>2022-11-25T20:28:57Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Behat/Gherkin/Cucumber Formatting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy  php.ini is being loaded.&lt;br /&gt;
&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See  [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
&lt;br /&gt;
Search on the string siarheikuchuk in the vscode extensions dialog. &lt;br /&gt;
The following settings will confirm to Moodles expectations.&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.And&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Scenario&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Given&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Table&amp;quot;: 8,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Then&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.When&amp;quot;: 4&lt;br /&gt;
&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63697</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63697"/>
		<updated>2022-11-20T21:58:13Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy  php.ini is being loaded.&lt;br /&gt;
&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See  [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
&lt;br /&gt;
Search on the string siarheikuchuk in the vscode extensions dialog. &lt;br /&gt;
The following settings will confirm to Moodles expectations.&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.And&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Scenario&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Given&amp;quot;: 4,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Table&amp;quot;: 8,&lt;br /&gt;
  &amp;quot;conf.view.identsBefore.Then&amp;quot;: 4&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63679</id>
		<title>Question types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63679"/>
		<updated>2022-11-01T22:12:53Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Changes in the question type plug in api between Moodle versions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Question_engine_2}}&lt;br /&gt;
=Question type plugin development=&lt;br /&gt;
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]], the question engine introduced with Moodle 2.1 .&lt;br /&gt;
&lt;br /&gt;
For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see [[Question_type_plugin_how_to]].&lt;br /&gt;
&lt;br /&gt;
Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]&lt;br /&gt;
==Existing question type plugins are helpful guides==&lt;br /&gt;
To learn to write question types, you are highly encouraged to read the code of some of the existing question types included in the Moodle code base, also there are many more examples of question types in the [https://github.com/moodleou/ Open University github repository] and even more examples of question types can be found in [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=29 the question type category of the Moodle plugins database].&lt;br /&gt;
===Existing question types and some of their features===&lt;br /&gt;
Below is a list of question types with their features, it is a good idea to examine the code of these question types especially ones that have features you may need for your new question type.&lt;br /&gt;
&lt;br /&gt;
If your question type will be GPLed then of course you can reuse the code in these question types either by cut and paste or by inheriting code from these question types.&lt;br /&gt;
* Questions included in Moodle&lt;br /&gt;
** true false, short answer&lt;br /&gt;
*** simplest question types&lt;br /&gt;
** Essay question type (essay)&lt;br /&gt;
*** manually not automatically graded.&lt;br /&gt;
** Calculated question&lt;br /&gt;
*** Uses a multipage question editing form&lt;br /&gt;
** Multiple choice (multichoice)&lt;br /&gt;
*** there is actually no reason why you should only have a single &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class for your question type. You may decide, depending on the question options, to use different definition classes where question options cause questions to behave in different ways. The multiple-choice question type does this, using different definition and renderer classes for single-response and multiple-response questions (but with common subclasses). This is possible because your question type can override the &amp;lt;tt&amp;gt;question_type::make_question_instance&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;question_definition::get_renderer&amp;lt;/tt&amp;gt; methods.&lt;br /&gt;
* Contrib questions&lt;br /&gt;
**[https://moodle.org/plugins/view.php?plugin=qtype_ddwtos Drag and drop into text (ddwtos)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddmarker Drag and drop markers question type (ddmarker)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddimageortext Drag and drop (image or text) onto image (ddimageortext)]&lt;br /&gt;
*** inherits code from Select missing words (gapselect).&lt;br /&gt;
*** also contains base classes which inherit from Select missing words (gapselect) and are used by Drag and drop markers&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_oumultiresponse OU multiple response (oumultiresponse)]&lt;br /&gt;
*** Question with multiple parts where grade is calculated by part for multiple attempts, student is given the grade for each part for the first time they got that part right or partially right.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatch Pmatch question type (pmatch)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatchjme Pattern match with JME editor (pmatchjme)]&lt;br /&gt;
*** Embeds a JAVA applet in the question which collects the student response and sends that to the server.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qbehaviour_opaque Question managed by a remote engine (opaque)]&lt;br /&gt;
*** communicates with an external system by a web service protocol based on SOAP to &amp;quot;delegate the rendering of questions, the scoring of responses and the generation of feedback to a remote question engine.&amp;quot; See https://docs.moodle.org/dev/Opaque&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_gapselect Select missing words (gapselect)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumeric Variable numeric question type (varnumeric)]&lt;br /&gt;
*** Code inherited from Variable numeric set.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumericset Variable numeric set question type (varnumericset)]&lt;br /&gt;
==Question type plugin template==&lt;br /&gt;
There is a [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/ question type plug in template available on github]. See the [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/blob/master/README.md README.md] file on the front page of the repository for more info about this template and how you are recommended to use it.&lt;br /&gt;
==The question engine itself is well commented==&lt;br /&gt;
Also note that all the question engine code has extensive PHP documenter comments that should explain the purpose of every class and method. This document is supposed to provide an overview of the key points to get you started. It does not attempt to duplicate all the details in the PHPdocs.&lt;br /&gt;
&lt;br /&gt;
This document assumes that you understand the data model, where a question attempt comprises a number of steps, and each step has some properties like a state and a mark, and an array of submitted data. [[Question_Engine_2:Overview|See the question engine overview doc for background]].&lt;br /&gt;
===Changes in the question type plugin api between Moodle versions===&lt;br /&gt;
[https://github.com/moodle/moodle/blob/master/question/type/upgrade.txt question/type/upgrade.txt] details the changes in the question type plug in api between Moodle versions.&lt;br /&gt;
==File layout==&lt;br /&gt;
Question types live in a folder in &amp;lt;tt&amp;gt;question/type&amp;lt;/tt&amp;gt;. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the &amp;lt;tt&amp;gt;question/type/mytype/&amp;lt;/tt&amp;gt; folder we would have:&lt;br /&gt;
; edit_YOURQTYPENAME_form.php : is the moodle_form used to define your question editing form. See [lib/formslib.php_Form_Definition] for details of how to use the formslib api.&lt;br /&gt;
; questiontype.php : Defines the &amp;lt;tt&amp;gt;qtype_mytype&amp;lt;/tt&amp;gt; class. This must extend &amp;lt;tt&amp;gt;question_type&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; question.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_question&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; renderer.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_renderer&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;qtype_renderer&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; tests/... : Contains the [[PHPUnit|unit tests]] and [[Acceptance_testing|Behat tests]] for this question type. You are strongly encouraged to write thorough unit tests to ensure the correctness of your question type.&lt;br /&gt;
; lang/en/qtype_myqtype.php : English language strings for this question type. You can, of course, include other languages too. The language file must define at least the strings giving the model a name etc., for example : &lt;br /&gt;
    $string[&#039;pluginname&#039;] = &#039;YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginname_help&#039;] = &#039;Create a .. description of your question type&#039;; // This is the text of the help icon show by the heading above the add/edit form when a question of this type is being edited.&lt;br /&gt;
    $string[&#039;pluginname_link&#039;] = &#039;question/type/YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginnameadding&#039;] = &#039;Adding a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnameediting&#039;] = &#039;Editing a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnamesummary&#039;] = &#039;A YOURQTYPENAME question type which allows...&#039;; // This is the text relating to this question type shown in the question-type chooser dialogue.&lt;br /&gt;
; lib.php : There is an importnat callback here that is called by the question engine to allow access to files used by questions. As with other plugins, you can put library code here, but in modern Moodle code it is better to use the classes/ folder.&lt;br /&gt;
; db/install.xml, db/upgrade.php : For creating any database tables required, [[Installing_and_upgrading_plugin_database_tables|as normal]]. See [[#Database_tables]] below.&lt;br /&gt;
; db/access.php : Defines any capabilities required by this question type. This is very rarely needed.&lt;br /&gt;
; version.php : [[version.php|version information]] for the question type. Also you can included in here which version no of core Moodle and/or other question types this module requires. Bumping up the question version will trigger the appropriate code in upgrade.php to be run when someone accesses {yourwwwroot}/admin/.&lt;br /&gt;
; styles.css : contains the styles used by your question type. You should preface all your selectors with .que.YOURQTYPENAME so that the styles are only applied to your question type which is wrapped in a div with class &#039;que&#039; and &#039;YOURQTYPENAME&#039;.&lt;br /&gt;
; pix/icon.svg: is the 16 * 16 px icon that appears next to your question type in the question type selection panel. (Can aslo be .png or .gif.)&lt;br /&gt;
; backup/moodle2/ : contains the files to implement backup and restore for your question type.&lt;br /&gt;
; classes/ : As with any Moodle plugin, you can put any extra classes you want to use to organise your code in here, and they will be [[Automatic_class_loading|auto-loaded]].&lt;br /&gt;
; settings.php (optional) : Admin menu settings that are for every question of this type. See [[Admin settings]] for info on how to add a settings page for your question type and the examples in some question types.&lt;br /&gt;
; amd/ : any [[Javascript_Modules|JavaScript modules]] your question type needs. (Old YUI-style JavaScript in yui/ or module.js would still work, but is not recommended.)&lt;br /&gt;
==Database tables==&lt;br /&gt;
Note that question types should only have database tables for the question definition. All runtime data is managed by the question engine.&lt;br /&gt;
&lt;br /&gt;
Question definitions should use the core table &amp;lt;tt&amp;gt;question&amp;lt;/tt&amp;gt;, and can use the core table &amp;lt;tt&amp;gt;question_answers&amp;lt;/tt&amp;gt;. You only need to define database tables if your question definition requires extra information that cannot be stored in either of these.&lt;br /&gt;
==Question type and question definition classes==&lt;br /&gt;
===The question definition class is in question.php===&lt;br /&gt;
This holds the definition of a particular question of this type. For example, an object of type qtype_shortanswer_question is a short-answer question instance. If you load three short-answer questions from the question bank, then you will get three instances of that class. This class is not just the question definition, it can also track the current state of a question as a student attempts it. For example, for a multiple-choice question, the class will store what order the choices have been randomly shuffled into for that student. To put it another way, the question_definition often works with a particular question_attempt.&lt;br /&gt;
===The question type class is in questiontype.php===&lt;br /&gt;
In contrast, the question type class represents the question type. For example, the qtype_shortanswer class represents the &#039;short answer&#039; type of question, and there will normally only be a single instance of this class. It has several responsiblities, including providing meta-data about this question type (e.g. public function name()). It knows how to load, save and delete questions of this type to and from the database (get_question_options and save_question_options, delete_question) and hence how to construct instances of the qtype_shortanswer_question class. It provides methods to help with editing questions of this type. It can also provide the implmentation for import and export in various formats.&lt;br /&gt;
==Renderer class==&lt;br /&gt;
Renderers are all about generating HTML output. The overall output of questions is controlled by the &amp;lt;tt&amp;gt;core_question_renderer::question(...)&amp;lt;/tt&amp;gt;, which in turn calls other methods of itself, the question type renderer and the behaviour renderer, to generate the various bits of output. See [[Question_Engine_2:Overview#What_are_the_parts_of_a_question.3F|this overview of the parts of a question]].&lt;br /&gt;
&lt;br /&gt;
Once again, in what follows, I only list the methods your are most likely to want to override.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===formulation_and_controls===&lt;br /&gt;
This displays the question text, and the controls the student will use to input their response. Some question types choose to display some feedback embedded in this area, for example ticks and crosses next to parts of the student&#039;s response.&lt;br /&gt;
&lt;br /&gt;
The output code must respect the &amp;lt;tt&amp;gt;question_display_options&amp;lt;/tt&amp;gt; and only reveal as much information as the calling code wants revealed. For example, the teacher creating a quiz may not want the correct answer revealed until after the quiz close date. Also, when outputting the controls, you need to respect the &amp;lt;tt&amp;gt;-&amp;gt;readonly&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
===specific_feedback===&lt;br /&gt;
Anything returned by this method is included in the &#039;outcome&#039; area of the question, it is some feedback that particularly relates to the response the student gave. This method is only called if the display options allow this to be shows, so you don&#039;t have to worry about testing that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===correct_response===&lt;br /&gt;
This would also be included in the &#039;outcome&#039; area. This should be an automatically generated (from the question definition) display of what the correct answer to the question is.&lt;br /&gt;
==Unit tests==&lt;br /&gt;
For a general introduction, see the [[PHPUnit|Moodle unit testing documentation]].&lt;br /&gt;
&lt;br /&gt;
The most important parts of your question type to test are the parts of the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class that process the students responses, including the compare and grade methods. The best way to start is probably to look at the tests for some of the standard question types.&lt;br /&gt;
&lt;br /&gt;
Another useful type of test for questions are &#039;walkthrough&#039; tests. These are implemented in using PHPunit, even though they are more integration tests than unit tests. There is [https://github.com/moodle/moodle/blob/master/question/engine/tests/helpers.php#L728 a detailed comment on the base class that explains more] and there are some nice examples in the core questions and also in the [https://github.com/moodleou/moodle-qtype_oumultiresponse/blob/master/tests/walkthrough_test.php OU Multi response github repository].&lt;br /&gt;
&lt;br /&gt;
Finally, it is good to have a few Behat tests, to check that everything works end-to-end. However, since Behat is much slower than unit tests, it is best to test all the details of the grading in PHPunit.&lt;br /&gt;
==Manually testing a question type==&lt;br /&gt;
The following provides a thorough test of a new question type. A lot of the following can now be done with [[Acceptance_testing|Behat]].&lt;br /&gt;
# Create some new questions of your type, exercising each significantly different combination of options.&lt;br /&gt;
# Go back to the editing form for each question to make sure that the options were saved accurately and that you can change them and that the changes are then saved.&lt;br /&gt;
# Try typing invalid input into the editing form, and ensure it is rejected.&lt;br /&gt;
# Preview each of your new questions using a variety of question behaviours. Check the mark and feedback for a range of correct and incorrect responses.&lt;br /&gt;
# Add your questions to some quizzes, using a range of behaviours, and different numbers of questions per page.&lt;br /&gt;
# Preview those quizzes several times, entering a range of correct and incorrect responses. Note that during this testing, some useful behind-the-scenes data (e.g. question summary, the exact behaviour being used) is shown in the Technical information region, so you probably want to expand that region, and check what is going on there.&lt;br /&gt;
# Now log in as a student and take the quizzes for real.&lt;br /&gt;
# If the question type uses complex CSS or JavaScript, repeat this testing in different web browsers.&lt;br /&gt;
# View all of the quiz reports, and ensure that they correctly display the information about your questions.&lt;br /&gt;
# Backup the course, restore it as a new course, and ensure that all your questions have been copied across accurately.&lt;br /&gt;
# Export your questions from the original course to each of the import/export formats your support. Import these questions to a new question category, and ensure they have been copied accurately (within the limits to which your question type can be represented in each format).&lt;br /&gt;
# Edit the questions so that there is a link to another part of the course (e.g. a Page resource) in every place that HTML can be entered. Repeat the backup and restore test and verify that the URLs in the restored question have been updated to point to the new copy of the Page resource in the new course.&lt;br /&gt;
# Edit the question to add an image to every HTML field that supports it. Repeat the Editing, Preview, Backup/restore and Export/import tests, and verify that the images always work, and that you don&#039;t end up with broken image links.&lt;br /&gt;
# Move the category containing the questions with images to a new context in the question bank, and make sure that the image links don&#039;t break.&lt;br /&gt;
# Check that all the unit tests for your question type pass.&lt;br /&gt;
# Run code-checker (https://moodle.org/plugins/view.php?plugin=local_codechecker) over your plugin to check the coding style.&lt;br /&gt;
# Check your question type against Accessibility guidelines, for example the [http://www.w3.org/WAI/intro/wcag.php Web Content Accessibility Guidelines].&lt;br /&gt;
==See also==&lt;br /&gt;
Next section: [[Using_the_question_engine_from_module|Using the question engine from a module]].&lt;br /&gt;
* The PHP documenter comments that explain the purposes of every method in the question engine code.&lt;br /&gt;
* Back to [[Question_Engine_2|Question Engine 2]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63678</id>
		<title>Question types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63678"/>
		<updated>2022-11-01T22:12:31Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Question type plug in template */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Question_engine_2}}&lt;br /&gt;
=Question type plugin development=&lt;br /&gt;
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]], the question engine introduced with Moodle 2.1 .&lt;br /&gt;
&lt;br /&gt;
For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see [[Question_type_plugin_how_to]].&lt;br /&gt;
&lt;br /&gt;
Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]&lt;br /&gt;
==Existing question type plugins are helpful guides==&lt;br /&gt;
To learn to write question types, you are highly encouraged to read the code of some of the existing question types included in the Moodle code base, also there are many more examples of question types in the [https://github.com/moodleou/ Open University github repository] and even more examples of question types can be found in [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=29 the question type category of the Moodle plugins database].&lt;br /&gt;
===Existing question types and some of their features===&lt;br /&gt;
Below is a list of question types with their features, it is a good idea to examine the code of these question types especially ones that have features you may need for your new question type.&lt;br /&gt;
&lt;br /&gt;
If your question type will be GPLed then of course you can reuse the code in these question types either by cut and paste or by inheriting code from these question types.&lt;br /&gt;
* Questions included in Moodle&lt;br /&gt;
** true false, short answer&lt;br /&gt;
*** simplest question types&lt;br /&gt;
** Essay question type (essay)&lt;br /&gt;
*** manually not automatically graded.&lt;br /&gt;
** Calculated question&lt;br /&gt;
*** Uses a multipage question editing form&lt;br /&gt;
** Multiple choice (multichoice)&lt;br /&gt;
*** there is actually no reason why you should only have a single &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class for your question type. You may decide, depending on the question options, to use different definition classes where question options cause questions to behave in different ways. The multiple-choice question type does this, using different definition and renderer classes for single-response and multiple-response questions (but with common subclasses). This is possible because your question type can override the &amp;lt;tt&amp;gt;question_type::make_question_instance&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;question_definition::get_renderer&amp;lt;/tt&amp;gt; methods.&lt;br /&gt;
* Contrib questions&lt;br /&gt;
**[https://moodle.org/plugins/view.php?plugin=qtype_ddwtos Drag and drop into text (ddwtos)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddmarker Drag and drop markers question type (ddmarker)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddimageortext Drag and drop (image or text) onto image (ddimageortext)]&lt;br /&gt;
*** inherits code from Select missing words (gapselect).&lt;br /&gt;
*** also contains base classes which inherit from Select missing words (gapselect) and are used by Drag and drop markers&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_oumultiresponse OU multiple response (oumultiresponse)]&lt;br /&gt;
*** Question with multiple parts where grade is calculated by part for multiple attempts, student is given the grade for each part for the first time they got that part right or partially right.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatch Pmatch question type (pmatch)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatchjme Pattern match with JME editor (pmatchjme)]&lt;br /&gt;
*** Embeds a JAVA applet in the question which collects the student response and sends that to the server.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qbehaviour_opaque Question managed by a remote engine (opaque)]&lt;br /&gt;
*** communicates with an external system by a web service protocol based on SOAP to &amp;quot;delegate the rendering of questions, the scoring of responses and the generation of feedback to a remote question engine.&amp;quot; See https://docs.moodle.org/dev/Opaque&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_gapselect Select missing words (gapselect)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumeric Variable numeric question type (varnumeric)]&lt;br /&gt;
*** Code inherited from Variable numeric set.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumericset Variable numeric set question type (varnumericset)]&lt;br /&gt;
==Question type plugin template==&lt;br /&gt;
There is a [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/ question type plug in template available on github]. See the [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/blob/master/README.md README.md] file on the front page of the repository for more info about this template and how you are recommended to use it.&lt;br /&gt;
==The question engine itself is well commented==&lt;br /&gt;
Also note that all the question engine code has extensive PHP documenter comments that should explain the purpose of every class and method. This document is supposed to provide an overview of the key points to get you started. It does not attempt to duplicate all the details in the PHPdocs.&lt;br /&gt;
&lt;br /&gt;
This document assumes that you understand the data model, where a question attempt comprises a number of steps, and each step has some properties like a state and a mark, and an array of submitted data. [[Question_Engine_2:Overview|See the question engine overview doc for background]].&lt;br /&gt;
===Changes in the question type plug in api between Moodle versions===&lt;br /&gt;
[https://github.com/moodle/moodle/blob/master/question/type/upgrade.txt question/type/upgrade.txt] details the changes in the question type plug in api between Moodle versions.&lt;br /&gt;
==File layout==&lt;br /&gt;
Question types live in a folder in &amp;lt;tt&amp;gt;question/type&amp;lt;/tt&amp;gt;. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the &amp;lt;tt&amp;gt;question/type/mytype/&amp;lt;/tt&amp;gt; folder we would have:&lt;br /&gt;
; edit_YOURQTYPENAME_form.php : is the moodle_form used to define your question editing form. See [lib/formslib.php_Form_Definition] for details of how to use the formslib api.&lt;br /&gt;
; questiontype.php : Defines the &amp;lt;tt&amp;gt;qtype_mytype&amp;lt;/tt&amp;gt; class. This must extend &amp;lt;tt&amp;gt;question_type&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; question.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_question&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; renderer.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_renderer&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;qtype_renderer&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; tests/... : Contains the [[PHPUnit|unit tests]] and [[Acceptance_testing|Behat tests]] for this question type. You are strongly encouraged to write thorough unit tests to ensure the correctness of your question type.&lt;br /&gt;
; lang/en/qtype_myqtype.php : English language strings for this question type. You can, of course, include other languages too. The language file must define at least the strings giving the model a name etc., for example : &lt;br /&gt;
    $string[&#039;pluginname&#039;] = &#039;YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginname_help&#039;] = &#039;Create a .. description of your question type&#039;; // This is the text of the help icon show by the heading above the add/edit form when a question of this type is being edited.&lt;br /&gt;
    $string[&#039;pluginname_link&#039;] = &#039;question/type/YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginnameadding&#039;] = &#039;Adding a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnameediting&#039;] = &#039;Editing a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnamesummary&#039;] = &#039;A YOURQTYPENAME question type which allows...&#039;; // This is the text relating to this question type shown in the question-type chooser dialogue.&lt;br /&gt;
; lib.php : There is an importnat callback here that is called by the question engine to allow access to files used by questions. As with other plugins, you can put library code here, but in modern Moodle code it is better to use the classes/ folder.&lt;br /&gt;
; db/install.xml, db/upgrade.php : For creating any database tables required, [[Installing_and_upgrading_plugin_database_tables|as normal]]. See [[#Database_tables]] below.&lt;br /&gt;
; db/access.php : Defines any capabilities required by this question type. This is very rarely needed.&lt;br /&gt;
; version.php : [[version.php|version information]] for the question type. Also you can included in here which version no of core Moodle and/or other question types this module requires. Bumping up the question version will trigger the appropriate code in upgrade.php to be run when someone accesses {yourwwwroot}/admin/.&lt;br /&gt;
; styles.css : contains the styles used by your question type. You should preface all your selectors with .que.YOURQTYPENAME so that the styles are only applied to your question type which is wrapped in a div with class &#039;que&#039; and &#039;YOURQTYPENAME&#039;.&lt;br /&gt;
; pix/icon.svg: is the 16 * 16 px icon that appears next to your question type in the question type selection panel. (Can aslo be .png or .gif.)&lt;br /&gt;
; backup/moodle2/ : contains the files to implement backup and restore for your question type.&lt;br /&gt;
; classes/ : As with any Moodle plugin, you can put any extra classes you want to use to organise your code in here, and they will be [[Automatic_class_loading|auto-loaded]].&lt;br /&gt;
; settings.php (optional) : Admin menu settings that are for every question of this type. See [[Admin settings]] for info on how to add a settings page for your question type and the examples in some question types.&lt;br /&gt;
; amd/ : any [[Javascript_Modules|JavaScript modules]] your question type needs. (Old YUI-style JavaScript in yui/ or module.js would still work, but is not recommended.)&lt;br /&gt;
==Database tables==&lt;br /&gt;
Note that question types should only have database tables for the question definition. All runtime data is managed by the question engine.&lt;br /&gt;
&lt;br /&gt;
Question definitions should use the core table &amp;lt;tt&amp;gt;question&amp;lt;/tt&amp;gt;, and can use the core table &amp;lt;tt&amp;gt;question_answers&amp;lt;/tt&amp;gt;. You only need to define database tables if your question definition requires extra information that cannot be stored in either of these.&lt;br /&gt;
==Question type and question definition classes==&lt;br /&gt;
===The question definition class is in question.php===&lt;br /&gt;
This holds the definition of a particular question of this type. For example, an object of type qtype_shortanswer_question is a short-answer question instance. If you load three short-answer questions from the question bank, then you will get three instances of that class. This class is not just the question definition, it can also track the current state of a question as a student attempts it. For example, for a multiple-choice question, the class will store what order the choices have been randomly shuffled into for that student. To put it another way, the question_definition often works with a particular question_attempt.&lt;br /&gt;
===The question type class is in questiontype.php===&lt;br /&gt;
In contrast, the question type class represents the question type. For example, the qtype_shortanswer class represents the &#039;short answer&#039; type of question, and there will normally only be a single instance of this class. It has several responsiblities, including providing meta-data about this question type (e.g. public function name()). It knows how to load, save and delete questions of this type to and from the database (get_question_options and save_question_options, delete_question) and hence how to construct instances of the qtype_shortanswer_question class. It provides methods to help with editing questions of this type. It can also provide the implmentation for import and export in various formats.&lt;br /&gt;
==Renderer class==&lt;br /&gt;
Renderers are all about generating HTML output. The overall output of questions is controlled by the &amp;lt;tt&amp;gt;core_question_renderer::question(...)&amp;lt;/tt&amp;gt;, which in turn calls other methods of itself, the question type renderer and the behaviour renderer, to generate the various bits of output. See [[Question_Engine_2:Overview#What_are_the_parts_of_a_question.3F|this overview of the parts of a question]].&lt;br /&gt;
&lt;br /&gt;
Once again, in what follows, I only list the methods your are most likely to want to override.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===formulation_and_controls===&lt;br /&gt;
This displays the question text, and the controls the student will use to input their response. Some question types choose to display some feedback embedded in this area, for example ticks and crosses next to parts of the student&#039;s response.&lt;br /&gt;
&lt;br /&gt;
The output code must respect the &amp;lt;tt&amp;gt;question_display_options&amp;lt;/tt&amp;gt; and only reveal as much information as the calling code wants revealed. For example, the teacher creating a quiz may not want the correct answer revealed until after the quiz close date. Also, when outputting the controls, you need to respect the &amp;lt;tt&amp;gt;-&amp;gt;readonly&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
===specific_feedback===&lt;br /&gt;
Anything returned by this method is included in the &#039;outcome&#039; area of the question, it is some feedback that particularly relates to the response the student gave. This method is only called if the display options allow this to be shows, so you don&#039;t have to worry about testing that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===correct_response===&lt;br /&gt;
This would also be included in the &#039;outcome&#039; area. This should be an automatically generated (from the question definition) display of what the correct answer to the question is.&lt;br /&gt;
==Unit tests==&lt;br /&gt;
For a general introduction, see the [[PHPUnit|Moodle unit testing documentation]].&lt;br /&gt;
&lt;br /&gt;
The most important parts of your question type to test are the parts of the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class that process the students responses, including the compare and grade methods. The best way to start is probably to look at the tests for some of the standard question types.&lt;br /&gt;
&lt;br /&gt;
Another useful type of test for questions are &#039;walkthrough&#039; tests. These are implemented in using PHPunit, even though they are more integration tests than unit tests. There is [https://github.com/moodle/moodle/blob/master/question/engine/tests/helpers.php#L728 a detailed comment on the base class that explains more] and there are some nice examples in the core questions and also in the [https://github.com/moodleou/moodle-qtype_oumultiresponse/blob/master/tests/walkthrough_test.php OU Multi response github repository].&lt;br /&gt;
&lt;br /&gt;
Finally, it is good to have a few Behat tests, to check that everything works end-to-end. However, since Behat is much slower than unit tests, it is best to test all the details of the grading in PHPunit.&lt;br /&gt;
==Manually testing a question type==&lt;br /&gt;
The following provides a thorough test of a new question type. A lot of the following can now be done with [[Acceptance_testing|Behat]].&lt;br /&gt;
# Create some new questions of your type, exercising each significantly different combination of options.&lt;br /&gt;
# Go back to the editing form for each question to make sure that the options were saved accurately and that you can change them and that the changes are then saved.&lt;br /&gt;
# Try typing invalid input into the editing form, and ensure it is rejected.&lt;br /&gt;
# Preview each of your new questions using a variety of question behaviours. Check the mark and feedback for a range of correct and incorrect responses.&lt;br /&gt;
# Add your questions to some quizzes, using a range of behaviours, and different numbers of questions per page.&lt;br /&gt;
# Preview those quizzes several times, entering a range of correct and incorrect responses. Note that during this testing, some useful behind-the-scenes data (e.g. question summary, the exact behaviour being used) is shown in the Technical information region, so you probably want to expand that region, and check what is going on there.&lt;br /&gt;
# Now log in as a student and take the quizzes for real.&lt;br /&gt;
# If the question type uses complex CSS or JavaScript, repeat this testing in different web browsers.&lt;br /&gt;
# View all of the quiz reports, and ensure that they correctly display the information about your questions.&lt;br /&gt;
# Backup the course, restore it as a new course, and ensure that all your questions have been copied across accurately.&lt;br /&gt;
# Export your questions from the original course to each of the import/export formats your support. Import these questions to a new question category, and ensure they have been copied accurately (within the limits to which your question type can be represented in each format).&lt;br /&gt;
# Edit the questions so that there is a link to another part of the course (e.g. a Page resource) in every place that HTML can be entered. Repeat the backup and restore test and verify that the URLs in the restored question have been updated to point to the new copy of the Page resource in the new course.&lt;br /&gt;
# Edit the question to add an image to every HTML field that supports it. Repeat the Editing, Preview, Backup/restore and Export/import tests, and verify that the images always work, and that you don&#039;t end up with broken image links.&lt;br /&gt;
# Move the category containing the questions with images to a new context in the question bank, and make sure that the image links don&#039;t break.&lt;br /&gt;
# Check that all the unit tests for your question type pass.&lt;br /&gt;
# Run code-checker (https://moodle.org/plugins/view.php?plugin=local_codechecker) over your plugin to check the coding style.&lt;br /&gt;
# Check your question type against Accessibility guidelines, for example the [http://www.w3.org/WAI/intro/wcag.php Web Content Accessibility Guidelines].&lt;br /&gt;
==See also==&lt;br /&gt;
Next section: [[Using_the_question_engine_from_module|Using the question engine from a module]].&lt;br /&gt;
* The PHP documenter comments that explain the purposes of every method in the question engine code.&lt;br /&gt;
* Back to [[Question_Engine_2|Question Engine 2]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63677</id>
		<title>Question types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63677"/>
		<updated>2022-11-01T22:11:51Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Existing question type plug ins are helpful guides */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Question_engine_2}}&lt;br /&gt;
=Question type plugin development=&lt;br /&gt;
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]], the question engine introduced with Moodle 2.1 .&lt;br /&gt;
&lt;br /&gt;
For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see [[Question_type_plugin_how_to]].&lt;br /&gt;
&lt;br /&gt;
Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]&lt;br /&gt;
==Existing question type plugins are helpful guides==&lt;br /&gt;
To learn to write question types, you are highly encouraged to read the code of some of the existing question types included in the Moodle code base, also there are many more examples of question types in the [https://github.com/moodleou/ Open University github repository] and even more examples of question types can be found in [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=29 the question type category of the Moodle plugins database].&lt;br /&gt;
===Existing question types and some of their features===&lt;br /&gt;
Below is a list of question types with their features, it is a good idea to examine the code of these question types especially ones that have features you may need for your new question type.&lt;br /&gt;
&lt;br /&gt;
If your question type will be GPLed then of course you can reuse the code in these question types either by cut and paste or by inheriting code from these question types.&lt;br /&gt;
* Questions included in Moodle&lt;br /&gt;
** true false, short answer&lt;br /&gt;
*** simplest question types&lt;br /&gt;
** Essay question type (essay)&lt;br /&gt;
*** manually not automatically graded.&lt;br /&gt;
** Calculated question&lt;br /&gt;
*** Uses a multipage question editing form&lt;br /&gt;
** Multiple choice (multichoice)&lt;br /&gt;
*** there is actually no reason why you should only have a single &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class for your question type. You may decide, depending on the question options, to use different definition classes where question options cause questions to behave in different ways. The multiple-choice question type does this, using different definition and renderer classes for single-response and multiple-response questions (but with common subclasses). This is possible because your question type can override the &amp;lt;tt&amp;gt;question_type::make_question_instance&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;question_definition::get_renderer&amp;lt;/tt&amp;gt; methods.&lt;br /&gt;
* Contrib questions&lt;br /&gt;
**[https://moodle.org/plugins/view.php?plugin=qtype_ddwtos Drag and drop into text (ddwtos)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddmarker Drag and drop markers question type (ddmarker)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddimageortext Drag and drop (image or text) onto image (ddimageortext)]&lt;br /&gt;
*** inherits code from Select missing words (gapselect).&lt;br /&gt;
*** also contains base classes which inherit from Select missing words (gapselect) and are used by Drag and drop markers&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_oumultiresponse OU multiple response (oumultiresponse)]&lt;br /&gt;
*** Question with multiple parts where grade is calculated by part for multiple attempts, student is given the grade for each part for the first time they got that part right or partially right.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatch Pmatch question type (pmatch)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatchjme Pattern match with JME editor (pmatchjme)]&lt;br /&gt;
*** Embeds a JAVA applet in the question which collects the student response and sends that to the server.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qbehaviour_opaque Question managed by a remote engine (opaque)]&lt;br /&gt;
*** communicates with an external system by a web service protocol based on SOAP to &amp;quot;delegate the rendering of questions, the scoring of responses and the generation of feedback to a remote question engine.&amp;quot; See https://docs.moodle.org/dev/Opaque&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_gapselect Select missing words (gapselect)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumeric Variable numeric question type (varnumeric)]&lt;br /&gt;
*** Code inherited from Variable numeric set.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumericset Variable numeric set question type (varnumericset)]&lt;br /&gt;
==Question type plug in template==&lt;br /&gt;
There is a [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/ question type plug in template available on github]. See the [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/blob/master/README.md README.md] file on the front page of the repository for more info about this template and how you are recommended to use it.&lt;br /&gt;
==The question engine itself is well commented==&lt;br /&gt;
Also note that all the question engine code has extensive PHP documenter comments that should explain the purpose of every class and method. This document is supposed to provide an overview of the key points to get you started. It does not attempt to duplicate all the details in the PHPdocs.&lt;br /&gt;
&lt;br /&gt;
This document assumes that you understand the data model, where a question attempt comprises a number of steps, and each step has some properties like a state and a mark, and an array of submitted data. [[Question_Engine_2:Overview|See the question engine overview doc for background]].&lt;br /&gt;
===Changes in the question type plug in api between Moodle versions===&lt;br /&gt;
[https://github.com/moodle/moodle/blob/master/question/type/upgrade.txt question/type/upgrade.txt] details the changes in the question type plug in api between Moodle versions.&lt;br /&gt;
==File layout==&lt;br /&gt;
Question types live in a folder in &amp;lt;tt&amp;gt;question/type&amp;lt;/tt&amp;gt;. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the &amp;lt;tt&amp;gt;question/type/mytype/&amp;lt;/tt&amp;gt; folder we would have:&lt;br /&gt;
; edit_YOURQTYPENAME_form.php : is the moodle_form used to define your question editing form. See [lib/formslib.php_Form_Definition] for details of how to use the formslib api.&lt;br /&gt;
; questiontype.php : Defines the &amp;lt;tt&amp;gt;qtype_mytype&amp;lt;/tt&amp;gt; class. This must extend &amp;lt;tt&amp;gt;question_type&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; question.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_question&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; renderer.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_renderer&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;qtype_renderer&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; tests/... : Contains the [[PHPUnit|unit tests]] and [[Acceptance_testing|Behat tests]] for this question type. You are strongly encouraged to write thorough unit tests to ensure the correctness of your question type.&lt;br /&gt;
; lang/en/qtype_myqtype.php : English language strings for this question type. You can, of course, include other languages too. The language file must define at least the strings giving the model a name etc., for example : &lt;br /&gt;
    $string[&#039;pluginname&#039;] = &#039;YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginname_help&#039;] = &#039;Create a .. description of your question type&#039;; // This is the text of the help icon show by the heading above the add/edit form when a question of this type is being edited.&lt;br /&gt;
    $string[&#039;pluginname_link&#039;] = &#039;question/type/YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginnameadding&#039;] = &#039;Adding a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnameediting&#039;] = &#039;Editing a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnamesummary&#039;] = &#039;A YOURQTYPENAME question type which allows...&#039;; // This is the text relating to this question type shown in the question-type chooser dialogue.&lt;br /&gt;
; lib.php : There is an importnat callback here that is called by the question engine to allow access to files used by questions. As with other plugins, you can put library code here, but in modern Moodle code it is better to use the classes/ folder.&lt;br /&gt;
; db/install.xml, db/upgrade.php : For creating any database tables required, [[Installing_and_upgrading_plugin_database_tables|as normal]]. See [[#Database_tables]] below.&lt;br /&gt;
; db/access.php : Defines any capabilities required by this question type. This is very rarely needed.&lt;br /&gt;
; version.php : [[version.php|version information]] for the question type. Also you can included in here which version no of core Moodle and/or other question types this module requires. Bumping up the question version will trigger the appropriate code in upgrade.php to be run when someone accesses {yourwwwroot}/admin/.&lt;br /&gt;
; styles.css : contains the styles used by your question type. You should preface all your selectors with .que.YOURQTYPENAME so that the styles are only applied to your question type which is wrapped in a div with class &#039;que&#039; and &#039;YOURQTYPENAME&#039;.&lt;br /&gt;
; pix/icon.svg: is the 16 * 16 px icon that appears next to your question type in the question type selection panel. (Can aslo be .png or .gif.)&lt;br /&gt;
; backup/moodle2/ : contains the files to implement backup and restore for your question type.&lt;br /&gt;
; classes/ : As with any Moodle plugin, you can put any extra classes you want to use to organise your code in here, and they will be [[Automatic_class_loading|auto-loaded]].&lt;br /&gt;
; settings.php (optional) : Admin menu settings that are for every question of this type. See [[Admin settings]] for info on how to add a settings page for your question type and the examples in some question types.&lt;br /&gt;
; amd/ : any [[Javascript_Modules|JavaScript modules]] your question type needs. (Old YUI-style JavaScript in yui/ or module.js would still work, but is not recommended.)&lt;br /&gt;
==Database tables==&lt;br /&gt;
Note that question types should only have database tables for the question definition. All runtime data is managed by the question engine.&lt;br /&gt;
&lt;br /&gt;
Question definitions should use the core table &amp;lt;tt&amp;gt;question&amp;lt;/tt&amp;gt;, and can use the core table &amp;lt;tt&amp;gt;question_answers&amp;lt;/tt&amp;gt;. You only need to define database tables if your question definition requires extra information that cannot be stored in either of these.&lt;br /&gt;
==Question type and question definition classes==&lt;br /&gt;
===The question definition class is in question.php===&lt;br /&gt;
This holds the definition of a particular question of this type. For example, an object of type qtype_shortanswer_question is a short-answer question instance. If you load three short-answer questions from the question bank, then you will get three instances of that class. This class is not just the question definition, it can also track the current state of a question as a student attempts it. For example, for a multiple-choice question, the class will store what order the choices have been randomly shuffled into for that student. To put it another way, the question_definition often works with a particular question_attempt.&lt;br /&gt;
===The question type class is in questiontype.php===&lt;br /&gt;
In contrast, the question type class represents the question type. For example, the qtype_shortanswer class represents the &#039;short answer&#039; type of question, and there will normally only be a single instance of this class. It has several responsiblities, including providing meta-data about this question type (e.g. public function name()). It knows how to load, save and delete questions of this type to and from the database (get_question_options and save_question_options, delete_question) and hence how to construct instances of the qtype_shortanswer_question class. It provides methods to help with editing questions of this type. It can also provide the implmentation for import and export in various formats.&lt;br /&gt;
==Renderer class==&lt;br /&gt;
Renderers are all about generating HTML output. The overall output of questions is controlled by the &amp;lt;tt&amp;gt;core_question_renderer::question(...)&amp;lt;/tt&amp;gt;, which in turn calls other methods of itself, the question type renderer and the behaviour renderer, to generate the various bits of output. See [[Question_Engine_2:Overview#What_are_the_parts_of_a_question.3F|this overview of the parts of a question]].&lt;br /&gt;
&lt;br /&gt;
Once again, in what follows, I only list the methods your are most likely to want to override.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===formulation_and_controls===&lt;br /&gt;
This displays the question text, and the controls the student will use to input their response. Some question types choose to display some feedback embedded in this area, for example ticks and crosses next to parts of the student&#039;s response.&lt;br /&gt;
&lt;br /&gt;
The output code must respect the &amp;lt;tt&amp;gt;question_display_options&amp;lt;/tt&amp;gt; and only reveal as much information as the calling code wants revealed. For example, the teacher creating a quiz may not want the correct answer revealed until after the quiz close date. Also, when outputting the controls, you need to respect the &amp;lt;tt&amp;gt;-&amp;gt;readonly&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
===specific_feedback===&lt;br /&gt;
Anything returned by this method is included in the &#039;outcome&#039; area of the question, it is some feedback that particularly relates to the response the student gave. This method is only called if the display options allow this to be shows, so you don&#039;t have to worry about testing that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===correct_response===&lt;br /&gt;
This would also be included in the &#039;outcome&#039; area. This should be an automatically generated (from the question definition) display of what the correct answer to the question is.&lt;br /&gt;
==Unit tests==&lt;br /&gt;
For a general introduction, see the [[PHPUnit|Moodle unit testing documentation]].&lt;br /&gt;
&lt;br /&gt;
The most important parts of your question type to test are the parts of the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class that process the students responses, including the compare and grade methods. The best way to start is probably to look at the tests for some of the standard question types.&lt;br /&gt;
&lt;br /&gt;
Another useful type of test for questions are &#039;walkthrough&#039; tests. These are implemented in using PHPunit, even though they are more integration tests than unit tests. There is [https://github.com/moodle/moodle/blob/master/question/engine/tests/helpers.php#L728 a detailed comment on the base class that explains more] and there are some nice examples in the core questions and also in the [https://github.com/moodleou/moodle-qtype_oumultiresponse/blob/master/tests/walkthrough_test.php OU Multi response github repository].&lt;br /&gt;
&lt;br /&gt;
Finally, it is good to have a few Behat tests, to check that everything works end-to-end. However, since Behat is much slower than unit tests, it is best to test all the details of the grading in PHPunit.&lt;br /&gt;
==Manually testing a question type==&lt;br /&gt;
The following provides a thorough test of a new question type. A lot of the following can now be done with [[Acceptance_testing|Behat]].&lt;br /&gt;
# Create some new questions of your type, exercising each significantly different combination of options.&lt;br /&gt;
# Go back to the editing form for each question to make sure that the options were saved accurately and that you can change them and that the changes are then saved.&lt;br /&gt;
# Try typing invalid input into the editing form, and ensure it is rejected.&lt;br /&gt;
# Preview each of your new questions using a variety of question behaviours. Check the mark and feedback for a range of correct and incorrect responses.&lt;br /&gt;
# Add your questions to some quizzes, using a range of behaviours, and different numbers of questions per page.&lt;br /&gt;
# Preview those quizzes several times, entering a range of correct and incorrect responses. Note that during this testing, some useful behind-the-scenes data (e.g. question summary, the exact behaviour being used) is shown in the Technical information region, so you probably want to expand that region, and check what is going on there.&lt;br /&gt;
# Now log in as a student and take the quizzes for real.&lt;br /&gt;
# If the question type uses complex CSS or JavaScript, repeat this testing in different web browsers.&lt;br /&gt;
# View all of the quiz reports, and ensure that they correctly display the information about your questions.&lt;br /&gt;
# Backup the course, restore it as a new course, and ensure that all your questions have been copied across accurately.&lt;br /&gt;
# Export your questions from the original course to each of the import/export formats your support. Import these questions to a new question category, and ensure they have been copied accurately (within the limits to which your question type can be represented in each format).&lt;br /&gt;
# Edit the questions so that there is a link to another part of the course (e.g. a Page resource) in every place that HTML can be entered. Repeat the backup and restore test and verify that the URLs in the restored question have been updated to point to the new copy of the Page resource in the new course.&lt;br /&gt;
# Edit the question to add an image to every HTML field that supports it. Repeat the Editing, Preview, Backup/restore and Export/import tests, and verify that the images always work, and that you don&#039;t end up with broken image links.&lt;br /&gt;
# Move the category containing the questions with images to a new context in the question bank, and make sure that the image links don&#039;t break.&lt;br /&gt;
# Check that all the unit tests for your question type pass.&lt;br /&gt;
# Run code-checker (https://moodle.org/plugins/view.php?plugin=local_codechecker) over your plugin to check the coding style.&lt;br /&gt;
# Check your question type against Accessibility guidelines, for example the [http://www.w3.org/WAI/intro/wcag.php Web Content Accessibility Guidelines].&lt;br /&gt;
==See also==&lt;br /&gt;
Next section: [[Using_the_question_engine_from_module|Using the question engine from a module]].&lt;br /&gt;
* The PHP documenter comments that explain the purposes of every method in the question engine code.&lt;br /&gt;
* Back to [[Question_Engine_2|Question Engine 2]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63676</id>
		<title>Question types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=63676"/>
		<updated>2022-11-01T22:11:18Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Question_engine_2}}&lt;br /&gt;
=Question type plugin development=&lt;br /&gt;
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]], the question engine introduced with Moodle 2.1 .&lt;br /&gt;
&lt;br /&gt;
For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see [[Question_type_plugin_how_to]].&lt;br /&gt;
&lt;br /&gt;
Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]&lt;br /&gt;
==Existing question type plug ins are helpful guides==&lt;br /&gt;
To learn to write question types, you are highly encouraged to read the code of some of the existing question types included in the Moodle code base, also there are many more examples of question types in the [https://github.com/moodleou/ Open University github repository] and even more examples of question types can be found in [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=29 the question type category of the Moodle plugins database].&lt;br /&gt;
===Existing question types and some of their features===&lt;br /&gt;
Below is a list of question types with their features, it is a good idea to examine the code of these question types especially ones that have features you may need for your new question type.&lt;br /&gt;
&lt;br /&gt;
If your question type will be GPLed then of course you can reuse the code in these question types either by cut and paste or by inheriting code from these question types.&lt;br /&gt;
* Questions included in Moodle&lt;br /&gt;
** true false, short answer&lt;br /&gt;
*** simplest question types&lt;br /&gt;
** Essay question type (essay)&lt;br /&gt;
*** manually not automatically graded.&lt;br /&gt;
** Calculated question&lt;br /&gt;
*** Uses a multipage question editing form&lt;br /&gt;
** Multiple choice (multichoice)&lt;br /&gt;
*** there is actually no reason why you should only have a single &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class for your question type. You may decide, depending on the question options, to use different definition classes where question options cause questions to behave in different ways. The multiple-choice question type does this, using different definition and renderer classes for single-response and multiple-response questions (but with common subclasses). This is possible because your question type can override the &amp;lt;tt&amp;gt;question_type::make_question_instance&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;question_definition::get_renderer&amp;lt;/tt&amp;gt; methods.&lt;br /&gt;
* Contrib questions&lt;br /&gt;
**[https://moodle.org/plugins/view.php?plugin=qtype_ddwtos Drag and drop into text (ddwtos)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddmarker Drag and drop markers question type (ddmarker)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddimageortext Drag and drop (image or text) onto image (ddimageortext)]&lt;br /&gt;
*** inherits code from Select missing words (gapselect).&lt;br /&gt;
*** also contains base classes which inherit from Select missing words (gapselect) and are used by Drag and drop markers&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_oumultiresponse OU multiple response (oumultiresponse)]&lt;br /&gt;
*** Question with multiple parts where grade is calculated by part for multiple attempts, student is given the grade for each part for the first time they got that part right or partially right.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatch Pmatch question type (pmatch)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatchjme Pattern match with JME editor (pmatchjme)]&lt;br /&gt;
*** Embeds a JAVA applet in the question which collects the student response and sends that to the server.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qbehaviour_opaque Question managed by a remote engine (opaque)]&lt;br /&gt;
*** communicates with an external system by a web service protocol based on SOAP to &amp;quot;delegate the rendering of questions, the scoring of responses and the generation of feedback to a remote question engine.&amp;quot; See https://docs.moodle.org/dev/Opaque&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_gapselect Select missing words (gapselect)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumeric Variable numeric question type (varnumeric)]&lt;br /&gt;
*** Code inherited from Variable numeric set.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumericset Variable numeric set question type (varnumericset)]&lt;br /&gt;
==Question type plug in template==&lt;br /&gt;
There is a [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/ question type plug in template available on github]. See the [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/blob/master/README.md README.md] file on the front page of the repository for more info about this template and how you are recommended to use it.&lt;br /&gt;
==The question engine itself is well commented==&lt;br /&gt;
Also note that all the question engine code has extensive PHP documenter comments that should explain the purpose of every class and method. This document is supposed to provide an overview of the key points to get you started. It does not attempt to duplicate all the details in the PHPdocs.&lt;br /&gt;
&lt;br /&gt;
This document assumes that you understand the data model, where a question attempt comprises a number of steps, and each step has some properties like a state and a mark, and an array of submitted data. [[Question_Engine_2:Overview|See the question engine overview doc for background]].&lt;br /&gt;
===Changes in the question type plug in api between Moodle versions===&lt;br /&gt;
[https://github.com/moodle/moodle/blob/master/question/type/upgrade.txt question/type/upgrade.txt] details the changes in the question type plug in api between Moodle versions.&lt;br /&gt;
==File layout==&lt;br /&gt;
Question types live in a folder in &amp;lt;tt&amp;gt;question/type&amp;lt;/tt&amp;gt;. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the &amp;lt;tt&amp;gt;question/type/mytype/&amp;lt;/tt&amp;gt; folder we would have:&lt;br /&gt;
; edit_YOURQTYPENAME_form.php : is the moodle_form used to define your question editing form. See [lib/formslib.php_Form_Definition] for details of how to use the formslib api.&lt;br /&gt;
; questiontype.php : Defines the &amp;lt;tt&amp;gt;qtype_mytype&amp;lt;/tt&amp;gt; class. This must extend &amp;lt;tt&amp;gt;question_type&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; question.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_question&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; renderer.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_renderer&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;qtype_renderer&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; tests/... : Contains the [[PHPUnit|unit tests]] and [[Acceptance_testing|Behat tests]] for this question type. You are strongly encouraged to write thorough unit tests to ensure the correctness of your question type.&lt;br /&gt;
; lang/en/qtype_myqtype.php : English language strings for this question type. You can, of course, include other languages too. The language file must define at least the strings giving the model a name etc., for example : &lt;br /&gt;
    $string[&#039;pluginname&#039;] = &#039;YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginname_help&#039;] = &#039;Create a .. description of your question type&#039;; // This is the text of the help icon show by the heading above the add/edit form when a question of this type is being edited.&lt;br /&gt;
    $string[&#039;pluginname_link&#039;] = &#039;question/type/YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginnameadding&#039;] = &#039;Adding a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnameediting&#039;] = &#039;Editing a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnamesummary&#039;] = &#039;A YOURQTYPENAME question type which allows...&#039;; // This is the text relating to this question type shown in the question-type chooser dialogue.&lt;br /&gt;
; lib.php : There is an importnat callback here that is called by the question engine to allow access to files used by questions. As with other plugins, you can put library code here, but in modern Moodle code it is better to use the classes/ folder.&lt;br /&gt;
; db/install.xml, db/upgrade.php : For creating any database tables required, [[Installing_and_upgrading_plugin_database_tables|as normal]]. See [[#Database_tables]] below.&lt;br /&gt;
; db/access.php : Defines any capabilities required by this question type. This is very rarely needed.&lt;br /&gt;
; version.php : [[version.php|version information]] for the question type. Also you can included in here which version no of core Moodle and/or other question types this module requires. Bumping up the question version will trigger the appropriate code in upgrade.php to be run when someone accesses {yourwwwroot}/admin/.&lt;br /&gt;
; styles.css : contains the styles used by your question type. You should preface all your selectors with .que.YOURQTYPENAME so that the styles are only applied to your question type which is wrapped in a div with class &#039;que&#039; and &#039;YOURQTYPENAME&#039;.&lt;br /&gt;
; pix/icon.svg: is the 16 * 16 px icon that appears next to your question type in the question type selection panel. (Can aslo be .png or .gif.)&lt;br /&gt;
; backup/moodle2/ : contains the files to implement backup and restore for your question type.&lt;br /&gt;
; classes/ : As with any Moodle plugin, you can put any extra classes you want to use to organise your code in here, and they will be [[Automatic_class_loading|auto-loaded]].&lt;br /&gt;
; settings.php (optional) : Admin menu settings that are for every question of this type. See [[Admin settings]] for info on how to add a settings page for your question type and the examples in some question types.&lt;br /&gt;
; amd/ : any [[Javascript_Modules|JavaScript modules]] your question type needs. (Old YUI-style JavaScript in yui/ or module.js would still work, but is not recommended.)&lt;br /&gt;
==Database tables==&lt;br /&gt;
Note that question types should only have database tables for the question definition. All runtime data is managed by the question engine.&lt;br /&gt;
&lt;br /&gt;
Question definitions should use the core table &amp;lt;tt&amp;gt;question&amp;lt;/tt&amp;gt;, and can use the core table &amp;lt;tt&amp;gt;question_answers&amp;lt;/tt&amp;gt;. You only need to define database tables if your question definition requires extra information that cannot be stored in either of these.&lt;br /&gt;
==Question type and question definition classes==&lt;br /&gt;
===The question definition class is in question.php===&lt;br /&gt;
This holds the definition of a particular question of this type. For example, an object of type qtype_shortanswer_question is a short-answer question instance. If you load three short-answer questions from the question bank, then you will get three instances of that class. This class is not just the question definition, it can also track the current state of a question as a student attempts it. For example, for a multiple-choice question, the class will store what order the choices have been randomly shuffled into for that student. To put it another way, the question_definition often works with a particular question_attempt.&lt;br /&gt;
===The question type class is in questiontype.php===&lt;br /&gt;
In contrast, the question type class represents the question type. For example, the qtype_shortanswer class represents the &#039;short answer&#039; type of question, and there will normally only be a single instance of this class. It has several responsiblities, including providing meta-data about this question type (e.g. public function name()). It knows how to load, save and delete questions of this type to and from the database (get_question_options and save_question_options, delete_question) and hence how to construct instances of the qtype_shortanswer_question class. It provides methods to help with editing questions of this type. It can also provide the implmentation for import and export in various formats.&lt;br /&gt;
==Renderer class==&lt;br /&gt;
Renderers are all about generating HTML output. The overall output of questions is controlled by the &amp;lt;tt&amp;gt;core_question_renderer::question(...)&amp;lt;/tt&amp;gt;, which in turn calls other methods of itself, the question type renderer and the behaviour renderer, to generate the various bits of output. See [[Question_Engine_2:Overview#What_are_the_parts_of_a_question.3F|this overview of the parts of a question]].&lt;br /&gt;
&lt;br /&gt;
Once again, in what follows, I only list the methods your are most likely to want to override.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===formulation_and_controls===&lt;br /&gt;
This displays the question text, and the controls the student will use to input their response. Some question types choose to display some feedback embedded in this area, for example ticks and crosses next to parts of the student&#039;s response.&lt;br /&gt;
&lt;br /&gt;
The output code must respect the &amp;lt;tt&amp;gt;question_display_options&amp;lt;/tt&amp;gt; and only reveal as much information as the calling code wants revealed. For example, the teacher creating a quiz may not want the correct answer revealed until after the quiz close date. Also, when outputting the controls, you need to respect the &amp;lt;tt&amp;gt;-&amp;gt;readonly&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
===specific_feedback===&lt;br /&gt;
Anything returned by this method is included in the &#039;outcome&#039; area of the question, it is some feedback that particularly relates to the response the student gave. This method is only called if the display options allow this to be shows, so you don&#039;t have to worry about testing that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===correct_response===&lt;br /&gt;
This would also be included in the &#039;outcome&#039; area. This should be an automatically generated (from the question definition) display of what the correct answer to the question is.&lt;br /&gt;
==Unit tests==&lt;br /&gt;
For a general introduction, see the [[PHPUnit|Moodle unit testing documentation]].&lt;br /&gt;
&lt;br /&gt;
The most important parts of your question type to test are the parts of the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class that process the students responses, including the compare and grade methods. The best way to start is probably to look at the tests for some of the standard question types.&lt;br /&gt;
&lt;br /&gt;
Another useful type of test for questions are &#039;walkthrough&#039; tests. These are implemented in using PHPunit, even though they are more integration tests than unit tests. There is [https://github.com/moodle/moodle/blob/master/question/engine/tests/helpers.php#L728 a detailed comment on the base class that explains more] and there are some nice examples in the core questions and also in the [https://github.com/moodleou/moodle-qtype_oumultiresponse/blob/master/tests/walkthrough_test.php OU Multi response github repository].&lt;br /&gt;
&lt;br /&gt;
Finally, it is good to have a few Behat tests, to check that everything works end-to-end. However, since Behat is much slower than unit tests, it is best to test all the details of the grading in PHPunit.&lt;br /&gt;
==Manually testing a question type==&lt;br /&gt;
The following provides a thorough test of a new question type. A lot of the following can now be done with [[Acceptance_testing|Behat]].&lt;br /&gt;
# Create some new questions of your type, exercising each significantly different combination of options.&lt;br /&gt;
# Go back to the editing form for each question to make sure that the options were saved accurately and that you can change them and that the changes are then saved.&lt;br /&gt;
# Try typing invalid input into the editing form, and ensure it is rejected.&lt;br /&gt;
# Preview each of your new questions using a variety of question behaviours. Check the mark and feedback for a range of correct and incorrect responses.&lt;br /&gt;
# Add your questions to some quizzes, using a range of behaviours, and different numbers of questions per page.&lt;br /&gt;
# Preview those quizzes several times, entering a range of correct and incorrect responses. Note that during this testing, some useful behind-the-scenes data (e.g. question summary, the exact behaviour being used) is shown in the Technical information region, so you probably want to expand that region, and check what is going on there.&lt;br /&gt;
# Now log in as a student and take the quizzes for real.&lt;br /&gt;
# If the question type uses complex CSS or JavaScript, repeat this testing in different web browsers.&lt;br /&gt;
# View all of the quiz reports, and ensure that they correctly display the information about your questions.&lt;br /&gt;
# Backup the course, restore it as a new course, and ensure that all your questions have been copied across accurately.&lt;br /&gt;
# Export your questions from the original course to each of the import/export formats your support. Import these questions to a new question category, and ensure they have been copied accurately (within the limits to which your question type can be represented in each format).&lt;br /&gt;
# Edit the questions so that there is a link to another part of the course (e.g. a Page resource) in every place that HTML can be entered. Repeat the backup and restore test and verify that the URLs in the restored question have been updated to point to the new copy of the Page resource in the new course.&lt;br /&gt;
# Edit the question to add an image to every HTML field that supports it. Repeat the Editing, Preview, Backup/restore and Export/import tests, and verify that the images always work, and that you don&#039;t end up with broken image links.&lt;br /&gt;
# Move the category containing the questions with images to a new context in the question bank, and make sure that the image links don&#039;t break.&lt;br /&gt;
# Check that all the unit tests for your question type pass.&lt;br /&gt;
# Run code-checker (https://moodle.org/plugins/view.php?plugin=local_codechecker) over your plugin to check the coding style.&lt;br /&gt;
# Check your question type against Accessibility guidelines, for example the [http://www.w3.org/WAI/intro/wcag.php Web Content Accessibility Guidelines].&lt;br /&gt;
==See also==&lt;br /&gt;
Next section: [[Using_the_question_engine_from_module|Using the question engine from a module]].&lt;br /&gt;
* The PHP documenter comments that explain the purposes of every method in the question engine code.&lt;br /&gt;
* Back to [[Question_Engine_2|Question Engine 2]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63664</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63664"/>
		<updated>2022-10-17T19:44:54Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Is xdebug loaded */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Is xdebug loaded?  ==&lt;br /&gt;
&lt;br /&gt;
There are a lot of web resources on how to configure xdebug with PHP, but a simple first step is to confirm that it appears in the yourmoodle.com/admin/phpinfo.php page and check settings are as you expect. For example look which copy  php.ini is being loaded.&lt;br /&gt;
&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See  [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Database_Schema&amp;diff=63646</id>
		<title>Database Schema</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Database_Schema&amp;diff=63646"/>
		<updated>2022-10-06T12:05:13Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The files available here are in [http://fabforce.net/dbdesigner4/ DBDesigner4] format. DBDesigner4 is a schema drawing program released under GPL.&lt;br /&gt;
&lt;br /&gt;
The database schemas have been put together by [http://moodle.org/user/view.php?id=11101&amp;amp;course=11 Alberto Giampani], [http://moodle.org/user/view.php?id=192442&amp;amp;course=11 Dario Toledo] and [http://moodle.org/user/view.php?id=305352&amp;amp;course=5 Isaac Cueto]. We are also discussing a means of creating them automatically from the new XMLDB definitions with an XML transform.&lt;br /&gt;
&lt;br /&gt;
Discussion of the database schemas happens either in the forum of the relevant module, or in the [https://moodle.org/mod/forum/view.php?id=55 General developer forum].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Moodle 4.0 = &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/4.0 Web view of the Moodle 4.00 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.11= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.11 Web view of the Moodle 3.11 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.10= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.10 Web view of the Moodle 3.10 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.9= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.9 Web view of the Moodle 3.9 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.7= &lt;br /&gt;
&lt;br /&gt;
[https://www.examulator.com/er/3.7/index.html Web view of the Moodle 3.7 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.6= &lt;br /&gt;
&lt;br /&gt;
[https://www.examulator.com/er/3.6/index.html Web view of the Moodle 3.6 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.5= &lt;br /&gt;
&lt;br /&gt;
[https://www.examulator.com/er/3.5/index.html Web view of the Moodle 3.5 schema] which is also grouped into common used components. .&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.4= &lt;br /&gt;
&lt;br /&gt;
[https://www.examulator.com/er/3.4/index.html Web view of the Moodle 3.4 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.3= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.3/index.html Web view of the Moodle 3.3 schema] which is also grouped into common used components.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.2= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.2/index.html Web view of the Moodle 3.2 schema] and a downloadable [http://www.examulator.com/er/moodle_32_erd.mwb Moodle 3.2 schema] by [http://www.moodleworld.com/moodle-entity-relationship-diagram-moodle-3-2-available-moodle3-2/ Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool.&lt;br /&gt;
&lt;br /&gt;
=Moodle 3.1= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.1/index.html Web view of the Moodle 3.1 schema] and a downloadable [http://examulator.com/er/3.1/moodle_31_erd.mwb Moodle 3.1 schema] by [https://moodle.org/mod/forum/discuss.php?d=278052 Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool. &lt;br /&gt;
&lt;br /&gt;
=Moodle 3.0= &lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/3.0/index.html Web view of the Moodle 3.0 schema] and a downloadable [http://www.examulator.com/er/moodle30_erd.mwb Moodle 3.0 schema] by [https://moodle.org/mod/forum/discuss.php?d=278052 Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool. &lt;br /&gt;
&lt;br /&gt;
=Moodle 2.9=&lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/2.9/index.html Web view of the Moodle 2.9 schema] and a downloadable [http://www.examulator.com/er/moodle29_erd.mwb Moodle 2.9 schema] by [https://moodle.org/mod/forum/discuss.php?d=278052 Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool. &lt;br /&gt;
&lt;br /&gt;
=Moodle 2.8=&lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/2.8/index.html Web view of the Moodle 2.8 schema] and a downloadable [http://www.examulator.com/er/moodle28_erd.mwb Moodle 2.8 schema] by [https://moodle.org/mod/forum/discuss.php?d=278052 Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool. &lt;br /&gt;
&lt;br /&gt;
=Moodle 2.7=&lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/2.7/index.html Web view of the Moodle 2.7 schema] and a downloadable [http://www.examulator.com/er/moodle27_erd.mwb Moodle 2.7 schema] by [https://moodle.org/mod/forum/discuss.php?d=278052 Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool. &lt;br /&gt;
&lt;br /&gt;
=Moodle 2.2=&lt;br /&gt;
&lt;br /&gt;
[http://www.examulator.com/er/2.2/index.html Web view of the Moodle 2.2 schema] and a downloadable [http://www.examulator.com/er/moodle22_erd.mwb Moodle 2.2 schema] by [https://moodle.org/mod/forum/discuss.php?d=278052 Marcus green] can be opened by [http://www.mysql.com/products/workbench MYSQL Workbench] tool. &lt;br /&gt;
&lt;br /&gt;
=Moodle 1.8=&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/file.php/5/moddata/forum/28/376698/moodle_1.8_data_structure.rar&lt;br /&gt;
&lt;br /&gt;
=Moodle 1.7=&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/file.php/11/moddata/forum/110/268325/db-edudist-Moodle-1.7_.rar&lt;br /&gt;
&lt;br /&gt;
=Moodle 1.5.3=&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/file.php/11/moddata/forum/110/267644/Db-Edudist-Moodle1.5.3-xml.rar&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:XMLDB]]&lt;br /&gt;
[[Category:DB]]&lt;br /&gt;
[[Category:Interfaces]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63642</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63642"/>
		<updated>2022-09-29T15:48:04Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* PHP Code Sniffer*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via pathMappings as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS (codesniffer). Under Ubuntu/Linux this may be done as &lt;br /&gt;
&lt;br /&gt;
sudo apt-get install -y php-codesniffer&lt;br /&gt;
&lt;br /&gt;
See  [https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS https://docs.moodle.org/dev/CodeSniffer#Installing_PHP] For more details on installing&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63529</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63529"/>
		<updated>2022-07-14T10:00:56Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: tweak to xdebug commentary&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is not the same as where the Moodle code is located, the settings.json file for xdebug can be set to point to that location via  pathMappings  as in this example.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS following steps described in https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS (you may choose your favourite way to install and configure it).&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63528</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=63528"/>
		<updated>2022-07-14T09:35:45Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: Set location of code for xdebug&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
If the root of the project is above the moodle code xdebug can be pointed to the code in the settings.json file like this&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Listen for Xdebug&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;php&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 9003,&lt;br /&gt;
            &amp;quot;pathMappings&amp;quot;: {&lt;br /&gt;
                &amp;quot;/var/www/html&amp;quot;: &amp;quot;${workspaceFolder}/moodle&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
==Intellisense==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
==Linting==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
*[https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
===PHP CS===&lt;br /&gt;
1. Install PHP CS following steps described in https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS (you may choose your favourite way to install and configure it).&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Code Formatting==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Behat/Gherkin/Cucumber Formatting==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
==Automated testing==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
== Docblocks==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
==Moodle specific Snippets and autocomplete==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
==Auto trim trailing white space==&lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
==Develop over an ssh connection==&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Writing_acceptance_tests&amp;diff=61678</id>
		<title>Writing acceptance tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Writing_acceptance_tests&amp;diff=61678"/>
		<updated>2022-01-31T19:32:57Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* When you define more steps in your plugin, make it clear they come from your plugin */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This documentation gives some hints on writing behat tests for Moodle core, and for plugins. The focus of the documentation is on behat tests for plugins. Behat Features and Scenarios are written in a natural language, and should&lt;br /&gt;
describe how a user would interact with Moodle.&lt;br /&gt;
&lt;br /&gt;
Each test consists of several stages which are categorised by the terms &#039;&#039;&#039;Given&#039;&#039;&#039;, &#039;&#039;&#039;When&#039;&#039;&#039;, and &#039;&#039;&#039;Then&#039;&#039;&#039;:&lt;br /&gt;
*&#039;&#039;&#039;Given&#039;&#039;&#039;: These steps allow you to perform a test set-up. Typically Given steps are used to set configuration, create users, courses and plugin instances, and generally prepare the site for testing&lt;br /&gt;
*&#039;&#039;&#039;When&#039;&#039;&#039;: When steps are used to get the test environment to the point at which you wish to test the conditions. This may include logging in, and then performing a range of actions like submitting an assignment and grading it for example&lt;br /&gt;
*&#039;&#039;&#039;Then&#039;&#039;&#039;: Then steps are used to check that your plugin behaved as expected. They typically check very simple things like if certain elements or text are visible or not. For example after submitting an assignment in the When stage, you may have a step which checks that a notice was shown to state that the submission was successful.&lt;br /&gt;
These three stages match the standard [http://xunitpatterns.com/Four%20Phase%20Test.html Four-phase test pattern]. The fourth phase is &#039;tear-down&#039; which is performed by Moodle between each test and does not need to be explicitly defined in your test.&lt;br /&gt;
&lt;br /&gt;
Note: Each test should have only one use of &#039;&#039;&#039;Given&#039;&#039;&#039;, &#039;&#039;&#039;When&#039;&#039;&#039;, and &#039;&#039;&#039;Then&#039;&#039;&#039;.&lt;br /&gt;
See MDLSITE-3778 for information and the policy decision on why you should not have multiple Given, When, and Then steps.&lt;br /&gt;
&lt;br /&gt;
Where you have several Given, When, and Then steps you should use the words &#039;&#039;&#039;And&#039;&#039;&#039;, and &#039;&#039;&#039;But&#039;&#039;&#039;, for example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given the following user exists:&lt;br /&gt;
  | username   | ccolon             |&lt;br /&gt;
  | First name | Colin              |&lt;br /&gt;
  | Last name  | Colon              |&lt;br /&gt;
  | email      | ccolon@example.com |&lt;br /&gt;
And the following course exists:&lt;br /&gt;
  | Name      | Jump Judging (Level 1) |&lt;br /&gt;
  | Shortname | sjea1                  |&lt;br /&gt;
When I log in as &amp;quot;ccolon&amp;quot;&lt;br /&gt;
And I navigate to &amp;quot;Site home &amp;gt; Jump Judging (Level 1)&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;You are not enrolled in this course&amp;quot;&lt;br /&gt;
But I should see &amp;quot;Enrol now&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
To initialize and run your tests, please follow the instructions of [[Running_acceptance_test]].&lt;br /&gt;
==Create your own tests==&lt;br /&gt;
Behat tests are located within the directory tests/behat of your plugin.&lt;br /&gt;
The different tests are defined in files with the ending *.feature.&lt;br /&gt;
First, you have to define the header of your test:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
@mod @mod_yourplugin @javascript&lt;br /&gt;
Feature: Here comes a description of your user story.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The tags on top of the feature description can be used to select specific test cases when running the tests.&lt;br /&gt;
The &#039;@javascript&#039; tag should only be used, if javascript is needed to execute your test. This is dependent on the step you will use in your definition.&lt;br /&gt;
Javascript tests are usually much slower than tests executed without javascript.&lt;br /&gt;
&lt;br /&gt;
Afterwards you can specify a scenario:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
@javascript&lt;br /&gt;
  Scenario: Description of your scenario, which you want to test.&lt;br /&gt;
    When I log in as &amp;quot;student1&amp;quot;&lt;br /&gt;
    And I am on &amp;quot;Course 1&amp;quot; course homepage&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Again you can define specific tags. Afterwards you write the steps, which should be executed during your test.&lt;br /&gt;
====Multiple Scenarios====&lt;br /&gt;
You can have an arbitrary amount of scenarios within a test. Please make sure they all belong to the same feature.&lt;br /&gt;
If you have certain steps, which should be executed for every scenario of a feature, you can define them using a background:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Background:&lt;br /&gt;
    Given the following &amp;quot;courses&amp;quot; exist:&lt;br /&gt;
      | fullname | shortname | category | groupmode |&lt;br /&gt;
      | Course 1 | C1        | 0        | 1         |&lt;br /&gt;
    And the following &amp;quot;users&amp;quot; exist:&lt;br /&gt;
      | username | firstname | lastname | email |&lt;br /&gt;
      | teacher1 | Theo | Teacher | teacher1@example.com |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This is usually used, to define the different &#039;&#039;&#039;GIVEN&#039;&#039;&#039; steps.&lt;br /&gt;
====Use existing steps====&lt;br /&gt;
There are different ways how to effectively browse the available existing steps:&lt;br /&gt;
======Moodle Administration======&lt;br /&gt;
Moodle offers within its administration menu under Site Administration &amp;gt; Development &amp;gt; Acceptance Testing a complete and searchable list of all available step definitions.&lt;br /&gt;
However, make sure you installed the behat test site first!&lt;br /&gt;
======PhpStorm======&lt;br /&gt;
In PhpStorm or IntelliJ you can install the behat extension. Then you get auto completions within feature files, which helps a lot during behat test development.&lt;br /&gt;
====Providing values to steps====&lt;br /&gt;
Most of the steps requires values, there are methods to provide values to steps, the method depends on the step specification.&lt;br /&gt;
*&#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A PyString&#039;&#039;&#039;; is a multiline string, most commonly used to fill out forms when a newline is required. Like steps with tables, steps which require PyStrings will end with &amp;quot;:&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;A field value&#039;&#039;&#039;; There are many different field types, if an argument requires a field value the expected value will depend on the field type:&lt;br /&gt;
**Text-based fields: It expects the text. This includes textareas, input type text, input type password...&lt;br /&gt;
**Checkbox: It expects 1 to check and for checked and &amp;quot;&amp;quot; to uncheck or for unchecked&lt;br /&gt;
**Select: It expects the option text or the option value. In case you interact with a multi-select you should specify the options separating them with commas. For example: &#039;&#039;&#039;option1, option2, option3&#039;&#039;&#039;&lt;br /&gt;
**Radio: The text of the radio option&lt;br /&gt;
*&#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
**link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
**button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
**link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
**radio - for searching a radio button by its id, name, or label&lt;br /&gt;
**file - for searching a file input by its id, name, or label&lt;br /&gt;
**optgroup - for searching optgroup by its label&lt;br /&gt;
**option - for searching an option by its content&lt;br /&gt;
**dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
**filemanager - for searching a filemanager by it&#039;s id or label&lt;br /&gt;
**block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** section - for searching for a section on a course page by it&#039;s title or its written out date (e.g. &amp;quot;1 January - 7 January&amp;quot;). Use &amp;quot;frontpage&amp;quot; &amp;quot;section&amp;quot; for the frontpage section if it has no title (default)&lt;br /&gt;
**activity - for searching for an activity module in a course list by it&#039;s title&lt;br /&gt;
**region - for searching a Moodle page region with that id, in fact it works with all ids for &amp;lt;tt&amp;gt;div&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;section&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;aside&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;header&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;footer&amp;lt;/tt&amp;gt; elements.&lt;br /&gt;
**table_row - for searching a table row which contains the specified text&lt;br /&gt;
**table - for searching a table by its id or caption&lt;br /&gt;
** icon - for searching an icon by its title&lt;br /&gt;
**fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
**xpath_element - for searching an element by its XPath&lt;br /&gt;
*&#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
**block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** section - for searching for a section on a course page by it&#039;s title or its written out date (e.g. &amp;quot;1 January - 7 January&amp;quot;). Use &amp;quot;frontpage&amp;quot; &amp;quot;section&amp;quot; for the frontpage section if it has no title (default)&lt;br /&gt;
**activity - for searching for an activity module in a course list by it&#039;s title&lt;br /&gt;
**region - for searching a Moodle page region with that id, in fact it works with all ids for &amp;lt;tt&amp;gt;div&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;section&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;aside&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;header&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;footer&amp;lt;/tt&amp;gt; elements.&lt;br /&gt;
**table_row - for searching a table row which contains the specified text&lt;br /&gt;
**table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** list_item - for searching a list item which contains the specified text&lt;br /&gt;
**css_element - for searching an element by its CSS selector&lt;br /&gt;
**xpath_element - for searching an element by its XPath&lt;br /&gt;
======Checking table values ======&lt;br /&gt;
You can check if specific value exists or not in a table row/column by using:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Then &amp;quot;STRING_IN_ROW&amp;quot; row &amp;quot;COLUMN_HEADER&amp;quot; column of &amp;quot;TABLE_ID&amp;quot; table should contain &amp;quot;VALUE_TO_CHECK&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Then the following should exist in the &amp;quot;TABLE_ID&amp;quot; table:&lt;br /&gt;
    | COLUMN_HEADER1 | COLUMN_HEADER2 |&lt;br /&gt;
    | VALUE_IN_ROW_1 | VALUE_IN_ROW_1 |&lt;br /&gt;
    | VALUE_IN_ROW_2 | VALUE_IN_ROW_2 |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
====Advanced use cases====&lt;br /&gt;
Most of the time the usage of existing step definitions is straight forward. However, there are some exceptions were it might get complicated. Some of them are listed here:&lt;br /&gt;
======Uploading files======&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
*The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
*The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example)&lt;br /&gt;
*&#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
*The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
@editor @editor_atto @atto @atto_media @_file_upload&lt;br /&gt;
Feature: Add media to Atto&lt;br /&gt;
  To write rich text - I need to add media.&lt;br /&gt;
&lt;br /&gt;
  Background:&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I follow &amp;quot;Manage private files...&amp;quot;&lt;br /&gt;
    And I upload &amp;quot;lib/editor/atto/tests/fixtures/moodle-logo.webm&amp;quot; file to &amp;quot;Files&amp;quot; filemanager&lt;br /&gt;
    And I upload &amp;quot;lib/editor/atto/tests/fixtures/moodle-logo.mp4&amp;quot; file to &amp;quot;Files&amp;quot; filemanager&lt;br /&gt;
    And I upload &amp;quot;lib/editor/atto/tests/fixtures/moodle-logo.png&amp;quot; file to &amp;quot;Files&amp;quot; filemanager&lt;br /&gt;
    And I upload &amp;quot;lib/editor/atto/tests/fixtures/pretty-good-en.vtt&amp;quot; file to &amp;quot;Files&amp;quot; filemanager&lt;br /&gt;
    And I upload &amp;quot;lib/editor/atto/tests/fixtures/pretty-good-sv.vtt&amp;quot; file to &amp;quot;Files&amp;quot; filemanager&lt;br /&gt;
    And I click on &amp;quot;Save changes&amp;quot; &amp;quot;button&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
======Field groups======&lt;br /&gt;
This section describes how you can use the step definitions&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I set the following fields to these values:&lt;br /&gt;
...&lt;br /&gt;
When I set the field &amp;quot;([^&amp;quot;]|\&amp;quot;*)&amp;quot; to &amp;quot;([^&amp;quot;]|\&amp;quot;*)&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
for field groups. Examples for such field groups are the duration field or the date_time_selector. These are not displayed as one single input field within the front-end but consist of multiple input fields within one row.&lt;br /&gt;
You can access each single input field of a group using &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
identifierOfYourField[keyOfTheSpecificInput]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Examples would be:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I set the following fields to these values:&lt;br /&gt;
  | myDate[day]             |   21   |&lt;br /&gt;
  | myDate[month]           |   12   |&lt;br /&gt;
  | myDate[hour]            |   14   |&lt;br /&gt;
  | myDuration[number]      |   10   |&lt;br /&gt;
  | myDuration[unit]        | days   |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
======Human-readable and relative dates======&lt;br /&gt;
When testing plugins with deadlines, for instance for submissions, it is often necessary to set certain time values to dates relative to today.&lt;br /&gt;
You can specify a relative time enclosed within two ## blocks. For example:&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;## yesterday ##&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;## 2 days ago ##&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can use everything according to http://php.net/manual/en/datetime.formats.php.&lt;br /&gt;
&lt;br /&gt;
Especially useful are the relative formats from: http://php.net/manual/en/datetime.formats.relative.php&lt;br /&gt;
&lt;br /&gt;
Additionally, you can specify a format you want the date to be returned into:&lt;br /&gt;
*&amp;lt;nowiki&amp;gt;## yesterday ## myformat ##&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
These formats can be used as outlined in http://php.net/manual/en/function.date.php.&lt;br /&gt;
This can be combined with the field groups:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
When I set the following fields to these values:&lt;br /&gt;
  | myDate[day]   | ##yesterday##%d## |&lt;br /&gt;
  | myDate[month] | ##yesterday##%B## |&lt;br /&gt;
  | myDate[year]  | ##yesterday##%Y## |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
====Writing your own steps====&lt;br /&gt;
Sometimes, you will need to set up data that is specific to your plugin, or perform steps that are specific to your plugin&#039;s UI. In this case it may be necessary to [[Writing_new_acceptance_test_step_definitions|write new step definitions]], but the short version is that you define new steps as PHP methods with a special annotation inside a class called &amp;lt;tt&amp;gt;behat_plugintype_plugingname&amp;lt;/tt&amp;gt; inside tests/behat/behat_plugintype_plugingname.php in your plugin.&lt;br /&gt;
&lt;br /&gt;
As well as creating completely new steps, you can also extend some of the standard steps:&lt;br /&gt;
=====Custom selectors (&amp;lt;tt&amp;gt;... in the &amp;quot;...&amp;quot; &amp;quot;...&amp;quot;&amp;lt;/tt&amp;gt;)=====&lt;br /&gt;
There are a load of different steps which can refer to specific items on-screen, for example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
And I click on &amp;quot;Submit all and finish&amp;quot; &amp;quot;button&amp;quot; in the &amp;quot;Confirmation&amp;quot; &amp;quot;dialogue&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &#039;button&#039; and &#039;dialogue&#039; are examples of selectors, and &#039;Submit all and finish&#039; and &#039;Confirmation&#039; are the locators which say which button or dialogue it is. When the test runs, this gets converted to an XPath expression, which is what the Behat system acutally uses to locate the right element on the page.&lt;br /&gt;
&lt;br /&gt;
From Moodle 3.8 onwards, you can define new types of selector (for example &amp;lt;tt&amp;gt;core_message &amp;gt; Message&amp;lt;/tt&amp;gt;) by implementing functions like &amp;lt;tt&amp;gt;behat_component_named_selector&amp;lt;/tt&amp;gt; in your plugin&#039;s &amp;lt;tt&amp;gt;behat_plugintype_plugingname&amp;lt;/tt&amp;gt; class. The detailed instructions for how to do this are in [https://github.com/moodle/moodle/blob/33da028c27607354981cd8e62ecabb7b973c6637/lib/behat/behat_base.php#L1111 the PHPdoc comments on the base class].&lt;br /&gt;
&lt;br /&gt;
The reasons you might want to do this are:&lt;br /&gt;
*It makes your tests easier to read, which makes it easier to be sure that the test is testing the right thing, and being able to read the tests helps people understand your features.&lt;br /&gt;
*If the HTML structure you output changes, then you only need to update the selector definition in one place.&lt;br /&gt;
=====Custom navigation targets (&amp;lt;tt&amp;gt;And I am on the &amp;quot;...&amp;quot; &amp;quot;...&amp;quot; page&amp;lt;/tt&amp;gt;)=====&lt;br /&gt;
From Moodle 3.8 onwards,there are two related steps:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given I am on the &amp;quot;Quiz 1&amp;quot; &amp;quot;mod_quiz &amp;gt; View&amp;quot; page logged in as &amp;quot;manager&amp;quot;&lt;br /&gt;
Given I am on the &amp;quot;C1&amp;quot; &amp;quot;Course&amp;quot; page&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
To make this work, in your plugin&#039;s &amp;lt;tt&amp;gt;behat_plugintype_plugingname&amp;lt;/tt&amp;gt; class, you need to implement the functions &amp;lt;tt&amp;gt;resolve_page_url&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;resolve_page_instance_url&amp;lt;/tt&amp;gt; methods. Once again, the detailed instructions about how this works are given in [https://github.com/moodle/moodle/blob/a0fc902eb184cd4097c8ab453ddc57964cd2dbd4/lib/behat/behat_base.php#L1093 the PHPdoc comments on the base class].&lt;br /&gt;
&lt;br /&gt;
There are two reasons why it is good to use these steps:&lt;br /&gt;
*You are trying to test that your feature works, not Moodle navigation. In the pase we have had many occasions when Moodle navigation changed, and lots of tests failed and had to be fixed. It is better for your tests to start on your feature. (Except, perhpas, it might be appropriate to have one test for the expected method for users to navigate to your feature.)&lt;br /&gt;
*It is much faster because you load fewer irrelevant pages, and in particular the normal loggi step leaves you on the Dashboard page, which is &#039;&#039;&#039;very&#039;&#039;&#039; slow to load.&lt;br /&gt;
===== Custom entity generators (&amp;lt;tt&amp;gt;And the following &amp;quot;...&amp;quot; exist:&amp;lt;/tt&amp;gt;)=====&lt;br /&gt;
From Moodle 3.8 onwards, it is possible to extend the &#039;&#039;Given the following &amp;quot;entites&amp;quot; exist&#039;&#039; step to support your plugin&#039;s data generators. This avoids having to write new whole&lt;br /&gt;
new behat step definitions for your plugin, and allows you to re-use data generators between PHPUnit and Behat tests.&lt;br /&gt;
&lt;br /&gt;
Full documentation of this process and all available options can be found in the [https://github.com/moodle/moodle/blob/1d4fdb0d1c60448104bc9eac79b5123863c67cbd/lib/behat/classes/behat_generator_base.php#L33 PHPDoc for behat_generator_base]. A core example of this can be found in [https://github.com/moodle/moodle/tree/master/mod/quiz/tests/generator /mod/quiz/tests/generator] and [https://github.com/moodle/moodle/blob/1d4fdb0d1c60448104bc9eac79b5123863c67cbd/mod/quiz/tests/behat/quiz_reset.feature#L51 quiz_reset.feature]. What follows is a simple example.&lt;br /&gt;
&lt;br /&gt;
To begin, you need a [[Writing_PHPUnit_tests#Generators|generator]] in /&#039;&#039;your&#039;&#039;/&#039;&#039;plugin&#039;&#039;/tests/generator/lib.php. If you are generating a type of entity called &amp;quot;thing&amp;quot;, your generator will need a method called create_thing, which accepts an object:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class local_myplugin_generator extends component_generator_base {&lt;br /&gt;
    public function create_thing($thing) {&lt;br /&gt;
        global $DB;&lt;br /&gt;
        $DB-&amp;gt;insert_record(&#039;local_myplugin_things&#039;, $thing);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Next, you will need to define your behat generator in /&#039;&#039;your&#039;&#039;/&#039;&#039;plugin&#039;&#039;/tests/generator/behat_&#039;&#039;your_plugin&#039;&#039;_generator.php, with the method get_createable_entitites():&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
class behat_local_myplugin_generator extends behat_generator_base {&lt;br /&gt;
&lt;br /&gt;
    protected function get_creatable_entities(): array {&lt;br /&gt;
        return [&lt;br /&gt;
            &#039;things&#039; =&amp;gt; [&lt;br /&gt;
                &#039;datagenerator&#039; =&amp;gt; &#039;thing&#039;,&lt;br /&gt;
                &#039;required&#039; =&amp;gt; [&#039;name&#039;]&lt;br /&gt;
            ],&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &#039;datagenerator&#039; value refers to the method in the generator class that we are calling, in this case &#039;&#039;create_thing()&#039;&#039;. The outer array key is the entity name we will use in the behat step, in this case &#039;&#039;Given the following &amp;quot;local_myplugin &amp;gt; things&amp;quot; exist&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now, in your behat test, you can have a step like this, which will generate 2 &#039;&#039;things&#039;&#039;, the first with the name &amp;quot;thing1&amp;quot; and the second with the name &amp;quot;thing2&amp;quot;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;gherkin&amp;quot;&amp;gt;&lt;br /&gt;
Given the following &amp;quot;local_myplugin &amp;gt; things&amp;quot; exist:&lt;br /&gt;
  | name   |&lt;br /&gt;
  | thing1 |&lt;br /&gt;
  | thing2 |&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==Good practice==&lt;br /&gt;
===Test one thing per scenario===&lt;br /&gt;
The ideal that you should strive for, is that each scenario tests just one specific bit of functionality. Therefore, if one test fails, the scenario name should tell you exactly what the bug is. Also, any bug should cause just one scenario to fail, not lots of unrelated ones. If you can achieve this, then the idea is that it minimises the time from seeing a test fail to having fixed the bug that was detected. Of course, this ideal is not always achievable, but in my experience it is worth striving for.&lt;br /&gt;
&lt;br /&gt;
Note that this also implies that the Given, When and Then keywords should be used only once per scenario.&lt;br /&gt;
===Set-up (Given) should not use the UI===&lt;br /&gt;
The setup is not what you are really testing here. Therefore, it should be as quick and reliable as possible. The way to achieve this is with steps like &amp;lt;tt&amp;gt;And the following &amp;quot;Thing&amp;quot; exist:&amp;lt;/tt&amp;gt; which directly insert the data into the database. If necessary, write extra steps for your plugin to setup the things you need.&lt;br /&gt;
===Don&#039;t use XPath or CSS selectors - fix your Accessibility bugs===&lt;br /&gt;
If, the only way you can identify something in the page that you want to manipulate is with a step like &amp;lt;tt&amp;gt;I set the field with xpath &amp;quot;//textarea[contains(@name, &#039;answer&#039;)]&amp;quot; to &amp;quot;frog&amp;quot;&amp;lt;/tt&amp;gt;, then this is probably the sign that you have an Accessibility bug, because Behat accesses the page very like a screen-reader user would.&lt;br /&gt;
&lt;br /&gt;
You should be able to refer to things with steps like &amp;lt;tt&amp;gt;I set the field &amp;quot;Answer&amp;quot; to &amp;quot;frog&amp;quot;&#039;&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;I click on &amp;quot;True&amp;quot; &amp;quot;radio&amp;quot; in the &amp;quot;First question&amp;quot; &amp;quot;question&amp;quot;&amp;lt;/tt&amp;gt;. If not, you should probably think about fixing the accessibility bug, rather than resorting to unreadable selectors in your Behat test.&lt;br /&gt;
===When you define more steps in your plugin, make it clear they come from your plugin===&lt;br /&gt;
When defining new Step definitions in your plugin, try to make sure the step name identifies it as belonging to your plugin. So, don&#039;t make a step called &amp;lt;tt&amp;gt;I disable UI plugins&amp;lt;/tt&amp;gt;. Call it something like &amp;lt;tt&amp;gt;I disable UI plugins in the CodeRunner question type&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===PHPDoc comments to map scenario steps===&lt;br /&gt;
PHPDoc style comments before functions can be used to map to your .scenario files. Read more about this here&lt;br /&gt;
&lt;br /&gt;
https://behat.org/en/latest/user_guide/context/definitions.html &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you define more steps in your plugin, make it clear they come from your plugin&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=61506</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=61506"/>
		<updated>2021-11-15T23:07:00Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Behat/Gherkin/Cucumber Formatting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Intellisense ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
&lt;br /&gt;
=== PHP CS ===&lt;br /&gt;
&lt;br /&gt;
1. Install PHP CS following steps described in https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS (you may choose your favourite way to install and configure it).&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Formatting ==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Behat/Gherkin/Cucumber Formatting ==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
This plugin seems to indent the feature files nicely&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=siarheikuchuk.gherkin-beautifier-vs-code-plugin&lt;br /&gt;
&lt;br /&gt;
== Automated testing ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
&lt;br /&gt;
== Docblocks ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/syntaxhighlight&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
&lt;br /&gt;
== Develop over an ssh connection == &lt;br /&gt;
&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer tools|vscode]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Main_Page&amp;diff=61335</id>
		<title>Talk:Main Page</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Main_Page&amp;diff=61335"/>
		<updated>2021-09-16T10:32:43Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note: This is not the place to ask questions. If you have a development related question, ask it in the [https://moodle.org/mod/forum/view.php?id=55 General Developer forum].&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Broken link in accessibility section ==&lt;br /&gt;
&lt;br /&gt;
Please note that on the following page: https://docs.moodle.org/dev/Accessibility the link to the British standard is broken: http://www.southampton.ac.uk/web4all/standards/BS_16steps/&lt;br /&gt;
&lt;br /&gt;
===Previously broken link in accessibility section fixed===&lt;br /&gt;
Please note that the page at https://docs.moodle.org/dev/Accessibility now correctly links to https://www.access8878.co.uk/getting-started-with-bs-8878/16-steps.aspx [[User:German Valero|German Valero]] ([[User talk:German Valero|talk]])&lt;br /&gt;
&lt;br /&gt;
===Missing (?) link to PHPStorm in &amp;quot;Developer Tools&amp;quot; category ===&lt;br /&gt;
I don&#039;t know what&#039;s the condition to appear on the main dev page, but as I&#039;m using IntelliJ/PHPStorm I noticed it&#039;s article was missing there [[Setting_up_PhpStorm]]&lt;br /&gt;
&lt;br /&gt;
And more importantly the link to VSCode is missing https://docs.moodle.org/dev/Setting_up_VSCode&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Javascript_Modules&amp;diff=58981</id>
		<title>Javascript Modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Javascript_Modules&amp;diff=58981"/>
		<updated>2021-06-19T21:51:37Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.9}}&lt;br /&gt;
&lt;br /&gt;
= Javascript Modules =&lt;br /&gt;
&lt;br /&gt;
== What is a Javascript module and why do I care? ==&lt;br /&gt;
&lt;br /&gt;
A Javascript module is nothing more than a collection of Javascript code that can be used (reliably) from other pieces of Javascript. &lt;br /&gt;
&lt;br /&gt;
== Why should I package my code as a module? ==&lt;br /&gt;
&lt;br /&gt;
By packaging your code as a module you break your code up into smaller reusable pieces. This is good because:&lt;br /&gt;
&lt;br /&gt;
a) Each smaller piece is simpler to understand / debug&lt;br /&gt;
&lt;br /&gt;
b) Each smaller piece is simpler to test&lt;br /&gt;
&lt;br /&gt;
c) You can re-use common code instead of duplicating it&lt;br /&gt;
&lt;br /&gt;
= How do I write a Javascript module in Moodle? =&lt;br /&gt;
&lt;br /&gt;
Since version 2.9, Moodle supports Javascript modules written using the Asynchronous Module Definition ([https://github.com/amdjs/amdjs-api/wiki/AMD AMD]) API. This is a standard API for creating Javascript modules and you will find many useful third party libraries that are already using this format. &lt;br /&gt;
&lt;br /&gt;
To edit or create an AMD module in Moodle you need to do a couple of things. &lt;br /&gt;
&lt;br /&gt;
Since version 3.8, Moodle supports [https://github.com/lukehoban/es6features#readme ECMAScript 2015 features] (aka ES6) in a cross browser compatible way thanks to [https://babeljs.io/ Babel JS]. In order to achieve the compatibility with older browsers Babel will compile the newer ES6 features back into ES5 Javascript. Unfortunately this means that in order for your Javascript changes to show in the browser they must be compiled by running [[Grunt]], even with the cachejs config setting set to false (i.e. &amp;quot;Development mode&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Note that, for Moodle 3.10 and up (see MDLSITE-6130), any new Javascript module &#039;&#039;&#039;must&#039;&#039;&#039; be written on ES6.&lt;br /&gt;
&lt;br /&gt;
== Install NVM and Node ==&lt;br /&gt;
&lt;br /&gt;
The recommended way of installing NodeJS is via the [https://github.com/nvm-sh/nvm Node Version Manager], or NVM. NVM allows you to have several different versions of NodeJS installed at and in-use at any once on your computer. Supported versions of Moodle all use version {{NodeJSExactVersion}} of NodeJS.&lt;br /&gt;
&lt;br /&gt;
https://github.com/nvm-sh/nvm#installing-and-updating&lt;br /&gt;
&lt;br /&gt;
Confirm it is working:&lt;br /&gt;
&lt;br /&gt;
 $ nvm --version&lt;br /&gt;
 0.35.3&lt;br /&gt;
&lt;br /&gt;
After you have installed &#039;&#039;&#039;nvm&#039;&#039;&#039;, you should install the correct version of NodeJS by running the following commands from your Moodle directory:&lt;br /&gt;
&lt;br /&gt;
 nvm install&lt;br /&gt;
 nvm use&lt;br /&gt;
&lt;br /&gt;
If your primary use of NodeJS is for Moodle then we recommend that you set NodeJS version {{NodeJSExactVersion}} as your default version. You can do this by running:&lt;br /&gt;
&lt;br /&gt;
 nvm alias default {{NodeJSExactVersion}}&lt;br /&gt;
&lt;br /&gt;
== Install grunt ==&lt;br /&gt;
&lt;br /&gt;
The AMD modules in Moodle must be processed by some build tools before they will be visible to your web browser. We use &amp;quot;[[grunt]]&amp;quot; as a build tool to wrap our different processes. Grunt is a build tool written in Javascript that runs in the &amp;quot;[http://nodejs.org/ nodejs]&amp;quot; environment.&lt;br /&gt;
&lt;br /&gt;
Once this is done, you can run the the following commands from your Moodle directory:&lt;br /&gt;
&lt;br /&gt;
 npm install&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This may mention vulnerabilities, that&#039;s fine and doesn&#039;t apply.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 npm install -g grunt-cli&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v2.9 to v3.7)  ==&lt;br /&gt;
&lt;br /&gt;
To avoid having to constantly run grunt, make sure you set the following in your config.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Prevent JS caching&lt;br /&gt;
$CFG-&amp;gt;cachejs = false;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Moodle will now run your module from the amd/src module. Don&#039;t forget to switch this off and run &#039;grunt&#039; before deploying the new version!&lt;br /&gt;
&lt;br /&gt;
In this mode - if you get a strange message in your javascript console like &amp;quot;No define call for core/first&amp;quot; it means you have a syntax error in the javascript you are developing. &lt;br /&gt;
Or, &amp;quot;No define call for theme_XXX/loader&amp;quot; as you are probably missing the &#039;src&#039; folder with relevant JS files. which might happen when you turn debugging ON on a theme that was bought, without &#039;src&#039; folder :-(&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v3.8 and above)  ==&lt;br /&gt;
&lt;br /&gt;
All Javascript code is now compiled using Babel which means Moodle will only ever serve minified Javascript to the browser, even in development mode. However in development mode Moodle will also send the browser the corresponding source map files for each of the Javascript modules. The source map files will tell the browser how to map the minified source code back to the unminified original source code so that the original source files will be displayed in the sources section of the browser&#039;s development tools.&lt;br /&gt;
&lt;br /&gt;
While in development mode each of the Javascript modules will appear in the browser&#039;s source tree as separate modules (no more giant first.js file!) and they will also be loaded with individual network requests (this is a compromise we had to make thanks to some browser bugs with source map files).&lt;br /&gt;
&lt;br /&gt;
To enable development mode set the &#039;&#039;&#039;cachejs&#039;&#039;&#039; config value to &#039;&#039;&#039;false&#039;&#039;&#039; in the admin settings or directly in your config.php file:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Prevent JS caching&lt;br /&gt;
$CFG-&amp;gt;cachejs = false;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since all Javascript must now be compiled you must run [[Grunt]] in order for you changes to appear in the browser. However rather than running Grunt manually each time on either the whole project or each file you modified, it is recommended that you just run the &#039;&#039;&#039;grunt watch&#039;&#039;&#039; task at the root of your Moodle directory. The grunt watch task will listen for changes to the Javascript files in the Moodle directory and will automatically lint and compile only the file that is changed after each change is detected. This removes the need to manually run grunt after each change.&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v3.10 and above)  ==&lt;br /&gt;
&lt;br /&gt;
All the above for Moodle 3.8 and up applies, plus (see MDLSITE-6130), any new Javascript module must be written on ES6.&lt;br /&gt;
&lt;br /&gt;
== Running grunt ==&lt;br /&gt;
&lt;br /&gt;
You can run grunt in your plugin&#039;s &#039;amd&#039; directory and it will only operate on your modules. If you&#039;re having problems or just want to check your work it is worth running for the &#039;lint&#039; feature. This can find basic problems. This sub-directory support wont work on Windows unfortunately but there is an alternative: Run grunt from the top directory with the --root=path/to/dir to limit execution to a sub-directory.&lt;br /&gt;
&lt;br /&gt;
See [[Grunt#Running_grunt]] for more details of specific grunt commands which can be used.&lt;br /&gt;
&lt;br /&gt;
If you get the error message&lt;br /&gt;
&lt;br /&gt;
 /usr/bin/env: node: No such file or directory&lt;br /&gt;
&lt;br /&gt;
Then see the thread https://github.com/nodejs/node-v0.x-archive/issues/3911&lt;br /&gt;
&lt;br /&gt;
On Ubuntu 14.04 this fixed it for me:&lt;br /&gt;
&lt;br /&gt;
 sudo ln -fs /usr/bin/nodejs /usr/local/bin/node&lt;br /&gt;
&lt;br /&gt;
Note: Once you have run grunt and built your code, you will then need to purge Moodle caches otherwise the changes made to your minified files may not be picked up by Moodle.&lt;br /&gt;
&lt;br /&gt;
== ES6 Modules (Moodle v3.8 and above) ==&lt;br /&gt;
&lt;br /&gt;
In addition to AMD module syntax Moodle now supports the [https://github.com/lukehoban/es6features#modules ES6 syntax] for writing Javascript modules. All modules (defined using either syntax) are compatible with one another. Behind the scenes the ES6 module syntax is converted into an AMD syntax as part of the Babel compiling process.&lt;br /&gt;
&lt;br /&gt;
Note that, for Moodle 3.10 and up (see MDLSITE-6130), any new Javascript module must be written on ES6.&lt;br /&gt;
&lt;br /&gt;
The call from a PHP file takes the same format&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;myplugin/myfile&#039;,&#039;init&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And a minimal ES6 file will work with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
export const init = () =&amp;gt; {&lt;br /&gt;
    window.console.log(&#039;we have been started&#039;);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export default ===&lt;br /&gt;
There is one slight difference between the ES6 definition for exporting modules and the RequireJS (AMD) definition.&lt;br /&gt;
&lt;br /&gt;
ES6 allows you to export a “default” value which is actually no different to exporting a named value where the name is “default”. Unfortunately, RequireJS allows for unnamed default exports (e.g. you can do &amp;quot;return SomeClass;&amp;quot;) which can be imported by just requiring them in other AMD modules.&lt;br /&gt;
&lt;br /&gt;
That’s a bit confusing, get to the point! Well, it basically means that in Moodle you won’t be able to write an ES6 module that exports both a default and named exports, e.g. &amp;quot;export default function() {...}&amp;quot; and &amp;quot;export const FOO = &#039;bar&#039;&amp;quot; in the same module. The export default will simply override all other exports in that module.&lt;br /&gt;
&lt;br /&gt;
=== Inline Javascript ===&lt;br /&gt;
Another important note is that ES6 support is only for stand alone Javascript files because it relies on the compilation from Babel and Grunt. That means any inline Javascript (either in PHP or in Mustache templates) won&#039;t support the ES6 features. Instead it would be best to keep the inline Javascript as minimal as possible and only use it to load a stand alone Javascript module.&lt;br /&gt;
&lt;br /&gt;
== Minimum (getting started) module for plugins ==&lt;br /&gt;
&lt;br /&gt;
This shows the absolute minimum module you need to get started adding modules to your plugins. It&#039;s actually quite simple...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// Put this file in path/to/plugin/amd/src&lt;br /&gt;
// You can call it anything you like&lt;br /&gt;
&lt;br /&gt;
export const init = () =&amp;gt; {&lt;br /&gt;
    document.addEventListener(&#039;change&#039;, e =&amp;gt; {&lt;br /&gt;
        const someNode = e.target.closest(&#039;.someclass&#039;);&lt;br /&gt;
        if (someNode) {&lt;br /&gt;
            alert(&#039;It changed!&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For older versions of Moodle prior to 3.8, you will need to use the legacy ES5 format instead:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
define([], function() {&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        init: function() {&lt;br /&gt;
            document.addEventListener(&#039;change&#039;, function(e) {&lt;br /&gt;
                var someNode = e.target.closest(&#039;.someclass&#039;);&lt;br /&gt;
                if (someNode) {&lt;br /&gt;
                    alert(&#039;It changed!&#039;);&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code passes the jquery module into our function (parameter $). There are a number of other useful modules available in Moodle, some of which you&#039;ll probably need in a practical application. See [[Useful_core_Javascript_modules]]. Simply list them in both the define() first parameter and the function callback. E.g.,&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
import jQuery from &#039;jquery&#039;; // We recommend that you strongly consider whether you really need jQuery. It is typically not needed in modern code.&lt;br /&gt;
import * as Str from &#039;core/str&#039;;&lt;br /&gt;
import Ajax from &#039;core/ajax&#039;;&lt;br /&gt;
&lt;br /&gt;
export const init = config =&amp;gt; {&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The idea here is that we will run the &#039;init&#039; function from our (PHP) code to set things up. This is called from PHP like this...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;frankenstyle_path/your_js_filename&#039;, &#039;init&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to supply the complete &#039;[[Frankenstyle]]&#039; path. The .js is not needed. &lt;br /&gt;
&lt;br /&gt;
js_call_amd takes a third parameter which is an &#039;&#039;array&#039;&#039; of parameters. These will translate to individual parameters in the &#039;init&#039; function call. For example...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;block_iomad_company_admin/department_select&#039;, &#039;init&#039;, array($first, $last));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
export const init = (first, last) {&lt;br /&gt;
    window.console.log(`The first name was &#039;${first}&#039; and the last name was &#039;${last}&#039;`);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A more comprehensive explanation follows...&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Hello World&amp;quot; I am a Javascript Module ==&lt;br /&gt;
Lets now create a simple Javascript module so we can see how to lay things out. &lt;br /&gt;
&lt;br /&gt;
Each Javascript module is contained in a single source file in the &amp;lt;componentdir&amp;gt;/amd/src folder. The final name of the module is taken from the file name and the component name. E.g. block_overview/amd/src/helloworld.js would be a module named &amp;quot;block_overview/helloworld&amp;quot;. the name of the module is important when you want to call it from somewhere else in the code. &lt;br /&gt;
&lt;br /&gt;
After running grunt - the minified Javascript files are stored in the &amp;lt;componentdir&amp;gt;/amd/build folder. The javascript files are renamed to show that they are minified (helloworld.js becomes helloworld.min.js). &lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to add the built files (the ones in amd/build) to your git commits, or in production no-one will see your changes. &lt;br /&gt;
&lt;br /&gt;
Lets create a simple module now:&lt;br /&gt;
&lt;br /&gt;
blocks/overview/amd/src/helloworld.js&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// Standard license block omitted.&lt;br /&gt;
/*&lt;br /&gt;
 * @package    block_overview&lt;br /&gt;
 * @copyright  2015 Someone cool&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
import * as Str from &#039;core/str&#039;;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Reveal all of the hidden notes.&lt;br /&gt;
 */&lt;br /&gt;
const showAllNotes = () =&amp;gt; {&lt;br /&gt;
    document.querySelectorAll(&#039;.note.hidden&#039;).map(note =&amp;gt; note.removeClass(&#039;hidden&#039;));&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Hide all of the notes.&lt;br /&gt;
 */&lt;br /&gt;
const hideAllNotes = () =&amp;gt; document.querySelectorAll(&#039;.note&#039;).map(note =&amp;gt; note.addClass(&#039;hidden&#039;));&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Return a personalised, formal, greeting.&lt;br /&gt;
 *&lt;br /&gt;
 * @param   {String} name The name of the person to greet&lt;br /&gt;
 * @returns {Promise}&lt;br /&gt;
 */&lt;br /&gt;
export const formal = name =&amp;gt; Str.get_string(&#039;formallygreet&#039;, &#039;block_overview&#039;, name);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Return a personalised, informal, greeting.&lt;br /&gt;
 *&lt;br /&gt;
 * @param   {String} name The name of the person to greet&lt;br /&gt;
 * @returns {Promise}&lt;br /&gt;
 */&lt;br /&gt;
export const informal = name =&amp;gt; {&lt;br /&gt;
    return Str.get_string(&#039;informallygreet&#039;, &#039;block_overview&#039;, name);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to note tha tonly functions which are exported will be callable from outside the module. These are part of the public API.&lt;br /&gt;
&lt;br /&gt;
== Loading modules dynamically ==&lt;br /&gt;
What do you do if you don&#039;t know in advance which modules will be required? In a limited number of situations you may not know the modules that you need until you call them. You can make use of dynamic imports to import them when you know what they are. Note: This is not the recommended approach in most cases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
export const showTheThing = thingToShow =&amp;gt; {&lt;br /&gt;
    // Load the module for this thing.&lt;br /&gt;
    import(`local_examples/local/types/type_${thingToShow.modname}`)&lt;br /&gt;
    .then(thingModule =&amp;gt; {&lt;br /&gt;
        window.console.log(`The ${thingToShow.modname} is now available under thingModule within this scope`);&lt;br /&gt;
&lt;br /&gt;
        return thingModule;&lt;br /&gt;
    });&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Including an external javascript/jquery library ==&lt;br /&gt;
If you want to include a javascript / jquery library downloaded from the internet you can do so as follows:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning: if the library you download, supports AMD but is already &amp;quot;named&amp;quot; you will not be able to include it directly&#039;&#039;&#039;&lt;br /&gt;
e.g. &lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// DO NOT DO THIS - IT DOES NOT WORK IN MOODLE&lt;br /&gt;
define(&amp;quot;typeahead.js&amp;quot;, *[ &amp;quot;jquery&amp;quot; ], function(a0) {&lt;br /&gt;
    return factory(a0);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work, as moodle injects it&#039;s own define name when loading the library.&lt;br /&gt;
&lt;br /&gt;
If the library is in AMD format and has a define:&lt;br /&gt;
e.g. i want to include the jquery final countdown timer on my page ( hilios.github.io/jQuery.countdown/ )&lt;br /&gt;
* download the module in both normal and minified versions&lt;br /&gt;
* place the modules in your moodle install e.g. your custom theme dir, or plugin dir&lt;br /&gt;
* /theme/mytheme/amd/src/jquery.countdown.js&lt;br /&gt;
&lt;br /&gt;
you can now include the module and initialise it (there are multiple ways to do this)&lt;br /&gt;
php:&lt;br /&gt;
&lt;br /&gt;
1. Create your own AMD module and initialise it:&lt;br /&gt;
&lt;br /&gt;
In your PHP file:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;requires-&amp;gt;js_call_amd(&#039;theme_mytheme/countdowntimer&#039;, &#039;init&#039;, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Javascript module:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// /theme/mytheme/amd/src/countdowntimer.js&lt;br /&gt;
import Countdown from &#039;theme_mytheme/jquery.countdown&#039;);&lt;br /&gt;
import $ from &#039;jquery&#039;;&lt;br /&gt;
&lt;br /&gt;
export const init = params =&amp;gt; {&lt;br /&gt;
    $(&#039;#clock&#039;).countdown(params.targetItem, event =&amp;gt; {&lt;br /&gt;
             $(event.target).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
    });&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Call your Javascript module from your template:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// /theme/mytheme/templates/countdowntimer.mustache&lt;br /&gt;
&amp;lt;span id=&amp;quot;theme_mytheme-clock-{{uniqid}}&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
{{#js}}&lt;br /&gt;
require([&#039;theme_mytheme/countdowntimer&#039;], function(myModule) {&lt;br /&gt;
    myModule.init({&lt;br /&gt;
        targetItem: &#039;theme_mytheme-clock-{{uniqid}}&#039;&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
{{/js}}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you feel that you need to work around MDL-62468, then you should probably be putting the data into the DOM in your template via data Attributes, or loading it via a Web Service.&lt;br /&gt;
&lt;br /&gt;
Another example of adding a 3rd-party library to a Moodle plugin (by Ruslan Kabalin)&lt;br /&gt;
&lt;br /&gt;
If you want use https://github.com/R-TEK/colr_pickr in your plugin but this module isn&#039;t RequireJS-compatible.&lt;br /&gt;
&lt;br /&gt;
You need to configure requirejs in your plugin to use third-party library:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$config = [&#039;paths&#039; =&amp;gt; [&#039;colorpicker&#039; =&amp;gt; &#039;CDN or local path...&#039;]];&lt;br /&gt;
$requirejs = &#039;require.config(&#039; . json_encode($config) . &#039;)&#039;;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_amd_inline($requirejs);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then in your JS module in the plugin:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
define([colorpicker], function(ColorPicker) {&lt;br /&gt;
    const button = document.getElementById(&#039;my_picker&#039;);&lt;br /&gt;
    let picker = new ColorPicker(button, &#039;#ff0000&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And another example of using https://github.com/itsjavi/bootstrap-colorpicker (that has a [[jQuery]] dependency) with native ES6 JS:&lt;br /&gt;
&lt;br /&gt;
 NOTE: It is advised to move away from [[jQuery]] related plugins, as Moodle core is moving away from jQuery.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
import ColourPicker from &#039;local_myplugin/bootstrap-colorpicker&#039;;&lt;br /&gt;
&lt;br /&gt;
const myElement = document.querySelector(&#039;.myelement&#039;);&lt;br /&gt;
const picker = new ColourPicker(myElement);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Embedding AMD code in a page ==&lt;br /&gt;
So you have created lots of cool Javascript modules. Great. How do we actually call them? Any javascript code that calls an AMD module must execute AFTER the requirejs module loader has finished loading. We have provided a function &amp;quot;js_call_amd&amp;quot; that will call a single function from an AMD module with parameters.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_call_amd($modulename, $functionname, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
that will &amp;quot;do the right thing&amp;quot; with your block of AMD code and execute it at the end of the page, after our AMD module loader has loaded. &lt;br /&gt;
Notes:&lt;br /&gt;
* the $modulename is the &#039;componentname/modulename&#039; discussed above&lt;br /&gt;
* the $functionname is the name of a public function exposed by the amd module. &lt;br /&gt;
* the $params is an array of params passed as arguments to the function. These should be simple types that can be handled by json_encode (no recursive arrays, or complex classes please). &lt;br /&gt;
* if the size of the params array is too large (&amp;gt; 1Kb), this will produce a developer warning. Do not attempt to pass large amounts of data through this function, it will pollute the page size. A preferred approach is to pass css selectors for DOM elements that contain data-attributes for any required data, or fetch data via ajax in the background.&lt;br /&gt;
&lt;br /&gt;
AMD / JS code can also be embedded on a page via mustache templates&lt;br /&gt;
see here: https://docs.moodle.org/dev/Templates#What_if_a_template_contains_javascript.3F&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== npm-shrinkwrap.json sha1 / sha512 changes ===&lt;br /&gt;
&lt;br /&gt;
If grunt changes all the hashes in npm-shrinkwrap.json then try this:&lt;br /&gt;
&lt;br /&gt;
 rm -rf node_modules &amp;amp;&amp;amp; npm i&lt;br /&gt;
&lt;br /&gt;
== But I have a mega JS file I don&#039;t want loaded on every page? ==&lt;br /&gt;
Loading all JS files at once and stuffing them in the browser cache is the right choice for MOST js files, there are probably some exceptions. For these files, you can rename the javascript file to end with the suffix &amp;quot;-lazy.js&amp;quot; which indicates that the module will not be loaded by default, it will be requested the first time it is used. There is no difference in usage for lazy loaded modules, the require() call looks exactly the same, it&#039;s just that the module name will also have the &amp;quot;-lazy&amp;quot; suffix.&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
* [https://assets.moodlemoot.org/sites/15/20171004085436/JavaScript-AMD-with-RequireJS-presented-by-Daniel-Roperto-Catalyst.pdf JavaScript AMD with RequireJS] presented by Daniel Roperto, Catalyst. (MoodleMOOT AU 2017)&lt;br /&gt;
* [[Useful_core_Javascript_modules]]&lt;br /&gt;
*[[Guide_to_adding_third_party_jQuery_for_AMD]] by Patrick Thibaudeau&lt;br /&gt;
*[https://moodle.org/mod/forum/discuss.php?d=378112#p1524459 How to get variables from PHP into javascript AMD modules in M3.5] Justin Hunt, on Moodle forums.&lt;br /&gt;
*MDL-67327 JavaScript issues when not following the official documentation, since Moodle 3.8&lt;br /&gt;
*[https://moodle.org/mod/forum/discuss.php?d=405829 Error from grunt watch - Moodle 3.9]  Forum Discussion&lt;br /&gt;
&lt;br /&gt;
[[Category:AJAX]]&lt;br /&gt;
[[Category:Javascript]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58896</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58896"/>
		<updated>2021-05-24T06:54:53Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Auto trim trailing white space */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Intellisense ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: &lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v3.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
&lt;br /&gt;
=== PHP CS ===&lt;br /&gt;
&lt;br /&gt;
1. Install PHP CS following steps described in https://docs.moodle.org/dev/CodeSniffer#Installing_PHP_CS (you may choose your favourite way to install and configure it).&lt;br /&gt;
&lt;br /&gt;
2. After installing PHP Sniffer, add the following setting to define standard PHP CS (if you haven&#039;t set it as default in your system):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&amp;quot;phpSniffer.standard&amp;quot;: &amp;quot;moodle&amp;quot;,&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Formatting ==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, with PHP CS configured too, set it to be the default formatter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Behat/Gherkin/Cucumber Formatting ==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
I have not found a plugin that will format .feature files consistent with the expected indentations&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
== Automated testing ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
&lt;br /&gt;
== Docblocks ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;code&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/code&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;br /&gt;
&lt;br /&gt;
== Develop over an ssh connection == &lt;br /&gt;
&lt;br /&gt;
With this plugin you can develop on a remote machine as if it were locally providing you have ssh login acces&lt;br /&gt;
&lt;br /&gt;
https://github.com/Microsoft/vscode-remote-release&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58261</id>
		<title>Running acceptance test</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58261"/>
		<updated>2021-01-28T14:52:43Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Running behat with specified theme (Since Moodle 3.2) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Short version ==&lt;br /&gt;
&lt;br /&gt;
...or how I got it to work on Ubuntu and some of the problems encountered. &lt;br /&gt;
&lt;br /&gt;
You need a bunch of browsers and terminal windows open to do this.&lt;br /&gt;
&lt;br /&gt;
==== 1. Background ====  &lt;br /&gt;
&lt;br /&gt;
# I am using the desktop version of Ubuntu 17.04 so there are no issues about running this software in headless mode. Running in headless mode was not tested.&lt;br /&gt;
# Moodle is version 3.3 and is a fully installed and working version using the &#039;standard&#039; Ubuntu LAMP stack.&lt;br /&gt;
&lt;br /&gt;
==== 2. Set up Selenium ====&lt;br /&gt;
First, you should have a look at [[Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium#Working_combinations_of_OS.2BBrowser.2Bselenium|working combinations of OS+Browser+selenium]].&lt;br /&gt;
&lt;br /&gt;
# Download the Selenium Standalone Server from [http://www.seleniumhq.org/download/ http://www.seleniumhq.org/download/]. It&#039;s a single JAR file, put it anywhere handy.&lt;br /&gt;
# Download the Chrome driver from [https://sites.google.com/a/chromium.org/chromedriver/ https://sites.google.com/a/chromium.org/chromedriver/]. Ensure you have the right version of the Chrome driver - see [[#Trouble_shooting| Trouble shooting]]. (Firefox is currently problematic. See [[Actual_Selenium_with_old_Firefox_47.0.1]] if you need to try to make it work.)&lt;br /&gt;
# Unzip the driver (it&#039;s a single file) and copy to /usr/local/bin (should work anywhere on the path)&lt;br /&gt;
# If not installed already, &#039;&amp;lt;tt&amp;gt;sudo apt install default-jre&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Start Selenium - &#039;&amp;lt;tt&amp;gt;java -jar /path/to/your/selenium/server/selenium-server-standalone-N.NN.N.jar -port 4444&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# check it works, access &#039;localhost:4444/wd/hub/&#039; in your browser and check you can create a new Chrome session.&lt;br /&gt;
&lt;br /&gt;
If running headless or the above doesn&#039;t work (&amp;quot;Selenium server is not running&amp;quot; when running the behat tests). Try the following&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;Xvfb -ac :99 -screen 0 1280x1024x16 &amp;amp;&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Then immediately, &#039;&amp;lt;tt&amp;gt;export DISPLAY=:99&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# The run the Selenium command as above&lt;br /&gt;
&lt;br /&gt;
==== 3. Set up Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Create a new &#039;dataroot&#039; area for files especially for behat adjusting permissions accordingly. &lt;br /&gt;
# If not there already, add Section 11 from config-dist.php to your config.php file and review the settings. &lt;br /&gt;
# $CFG-&amp;gt;behat_wwwroot needs to point to your Moodle site yet be different from the &#039;normal&#039; wwwroot (e.g. if you used localhost for wwwroot use 127.0.0.1 for the behat_wwwroot). Whatever you choose, make sure it works. &lt;br /&gt;
# $CFG-&amp;gt;behat_dataroot should point to the directory you created above&lt;br /&gt;
# $CFG-&amp;gt;behat_prefix should be fine. &lt;br /&gt;
# Set up $CFG-&amp;gt;behat_profiles to select Chrome as the browser...&lt;br /&gt;
&lt;br /&gt;
     $CFG-&amp;gt;behat_profiles = [&lt;br /&gt;
         &#039;default&#039; =&amp;gt; [&lt;br /&gt;
             &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
             &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
                 &#039;Behat\MinkExtension&#039; =&amp;gt; [&lt;br /&gt;
                     &#039;selenium2&#039; =&amp;gt; [&lt;br /&gt;
                         &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                     ]&lt;br /&gt;
                 ]&lt;br /&gt;
             ]&lt;br /&gt;
         ]&lt;br /&gt;
     ];&lt;br /&gt;
&lt;br /&gt;
==== 4. Configure Behat for Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;php admin/tool/behat/cli/init.php&amp;lt;/tt&amp;gt;&#039; (from the root of your Moodle install). This installs all the required software and creates the test version of Moodle. &lt;br /&gt;
&lt;br /&gt;
==== 5. Run Behat tests ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;vendor/bin/behat&amp;lt;/tt&amp;gt;&#039;. If you don&#039;t want to run all the tests add &#039;&amp;lt;tt&amp;gt;--tags=&amp;quot;@something&amp;quot;&amp;lt;/tt&amp;gt;&#039; where the @something refers to the tags at the top of most feature files. Use comma-separated list like &#039;&amp;lt;tt&amp;gt;@some_thing,@some_thing_else&amp;lt;/tt&amp;gt;&#039; to run tests from multiple areas. See upstream documentation on Gherkin filters for advanced syntax and more complex examples.&lt;br /&gt;
# After some initial setup dots should start to go by. It&#039;s a while before Selenium is first accessed. On the Linux desktop a new Chrome window appears and the testing process &#039;remote control&#039; starts (hopefully!)&lt;br /&gt;
# At the end of each line it shows you the number of steps that have completed so far.&lt;br /&gt;
#* If you are doing a full run, then as of November 2020 there are about 63,000 steps, which took around 25 hours to complete on one test machine (when not using the parallel running feature). Moodle HQ manage complete runs in ~5 hours on a well-optmised set-up, with 3 parallel workers.&lt;br /&gt;
&lt;br /&gt;
== Prerequisite ==&lt;br /&gt;
Before initializing acceptance test environment for running behat, you should ensure:&lt;br /&gt;
# [[Acceptance_testing#Requirements Meet min. system requirements for running tests]]&lt;br /&gt;
# [[Acceptance_testing#Installation Have set min. config variable in config.php for behat]]&lt;br /&gt;
# [[Acceptance_testing#Installation Downloaded composer dependencies]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Acceptance tests (also known as behat), use [http://www.seleniumhq.org/download/ Selenium server] and can be run as:&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; In single run, only one behat run is executed. So all features are executed in this single run.&lt;br /&gt;
# &#039;&#039;&#039;Parallel runs:&#039;&#039;&#039; (Since Moodle 3.0) Parallel runs allow dev&#039;s to execute multiple behat runs together. This was introduced to get acceptance tests results faster. To achieve this:&lt;br /&gt;
#* Features are divided between multiple behat runs&lt;br /&gt;
#* Symlinks behatrun{x} (x being the run process number), are created pointing to moodle directory, so site for run 1 is accessible via https://localhost/moodle/behatrun1&lt;br /&gt;
#* Process number is included as suffix to $CFG-&amp;gt;behat_prefix.&lt;br /&gt;
#* Process number is suffixed to $CFG-&amp;gt;behat_dataroot.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Initialise acceptance test environment ==&lt;br /&gt;
Before running acceptance tests, environment needs to be initialised for acceptance testing.&lt;br /&gt;
&lt;br /&gt;
=== Single run ===&lt;br /&gt;
For initialising acceptance tests for single run, above command is sufficient.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For initialising acceptance tests for parallel runs, you can use one of the following options&lt;br /&gt;
# &#039;&#039;&#039;-j=&amp;lt;number&amp;gt; or --parallel=&amp;lt;number&amp;gt;&#039;&#039;&#039; (required) Number of parallel behat run to initialise&lt;br /&gt;
# &#039;&#039;&#039;-m=&amp;lt;number&amp;gt; or --maxruns=&amp;lt;number&amp;gt;&#039;&#039;&#039;  (optional) Max parallel site which should be initialised at one time. If your system is slow, then you can initialise sites in chucks.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run from. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;--torun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run till. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;-o or --optimize-runs&#039;&#039;&#039; (optional) This option will split features with specified tags in all parallel runs, so they are executed first when parallel run gets executed.&lt;br /&gt;
# &#039;&#039;&#039;-a=&amp;lt;name&amp;gt; or --add-core-features-to-theme=&amp;lt;name&amp;gt;&#039;&#039;&#039; (optional) Since Moodle 3.2. Use this option to add all core features to specified themes (comma separated list of themes)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// Below command will initialise moodle to run 2 parallel tests.&lt;br /&gt;
php admin/tool/behat/cli/init.php --parallel=2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 2: Running acceptance test environment ==&lt;br /&gt;
=== Single run ===&lt;br /&gt;
Run either of the following commands. For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You almost always want to limit the number of tests that are run. To run all the tests in one plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml --tags mod_myplugin&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run all the tests in one .feature file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run a single scenario:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature:40&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &#039;40&#039; is the line-number of the feature file where the Scenario starts.&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For running parallel runs, use following command&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/run.php&lt;br /&gt;
&lt;br /&gt;
Following optional options are available for custom run:&lt;br /&gt;
# &#039;&#039;&#039;--feature&#039;&#039;&#039; Only execute specified feature file (Absolute path of feature file).&lt;br /&gt;
# &#039;&#039;&#039;--suite&#039;&#039;&#039; Features for specified theme will be executed.&lt;br /&gt;
# &#039;&#039;&#039;--replace&#039;&#039;&#039; Replace args string with run process number, useful for output and reruns.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun&#039;&#039;&#039; Execute run starting from (Used for parallel runs on different vms)&lt;br /&gt;
# &#039;&#039;&#039;--torun&#039;&#039;&#039; Execute run till (Used for parallel runs on different vms)&lt;br /&gt;
# Behat options can be passed for filtering features/scenarios:&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests, use the Behat tags option to skip them, &#039;&#039;&#039;--tags=&amp;quot;~@javascript&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific scenario, use the Behat name option to run it, &#039;&#039;&#039;--name=&amp;quot;Filter user accounts by role and cohort&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific feature file, use the Behat feature option to run it, &#039;&#039;&#039;--feature=&amp;quot;/PATH/TO/MOODLE/admin/tests/behat/filter_users.feature&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example: Initialise and run Behat tests for a custom plugin under a custom theme:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/init.php --parallel=3 --add-core-features-to-theme=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
 php admin/tool/behat/cli/run.php --tags=&amp;quot;@tool_myplugin&amp;quot; --suite=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Common options for running tests ===&lt;br /&gt;
==== Tests filters ====&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; iframe&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
==== Output formats ====&lt;br /&gt;
Since Moodle 3.1 option for output is:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=pretty --out=/path/to/pretty.txt --format=moodle_progress --out=std&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Before Moodle 3.1 option for output was:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=&#039;moodle_progress,pretty&#039; --out=&#039;,/path/to/pretty.txt&#039;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Following output formats are supported:&lt;br /&gt;
# &#039;&#039;&#039;progress&#039;&#039;&#039;: Prints one character per step.&lt;br /&gt;
# &#039;&#039;&#039;pretty&#039;&#039;&#039;: Prints the feature as is.&lt;br /&gt;
# &#039;&#039;&#039;junit&#039;&#039;&#039;: Outputs the failures in JUnit compatible files.&lt;br /&gt;
# &#039;&#039;&#039;moodle_progress&#039;&#039;&#039;: Prints Moodle branch information and dots for each step.&lt;br /&gt;
# &#039;&#039;&#039;moodle_list&#039;&#039;&#039;: List all scenarios.&lt;br /&gt;
# &#039;&#039;&#039;moodle_stepcount&#039;&#039;&#039;: List all features with total steps in each feature file. Used for parallel run.&lt;br /&gt;
# &#039;&#039;&#039;moodle_screenshot&#039;&#039;&#039;: (since Moodle 3.1) Take screenshot and core dump of each step. With following options you can dump either or both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;image&amp;quot;}&#039;**: will dump image only&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;}&#039;**: will dump html only.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html,image&amp;quot;}&#039;**: will dump both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;, &amp;quot;dir_permissions&amp;quot;: &amp;quot;0777&amp;quot;}&#039;**&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format. Format &#039;pretty&#039; (&#039;&#039;&#039;-f pretty&#039;&#039;&#039;) is sufficient for most cases, as it outputs each step outcomes in the command line making easier to see the progress.&lt;br /&gt;
&lt;br /&gt;
== Advance usage ==&lt;br /&gt;
=== Rerun failed scenarios ===&lt;br /&gt;
With slow systems or parallel run you might see some random failures, to rerun only failed scenarios (to eliminate random failures), use --rerun option&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; --run=&amp;quot;absolute_path_to_empty_file&amp;quot; (Behat will record failed scenarios in this file, and when run again only failed scenarios will be run)&lt;br /&gt;
# &#039;&#039;&#039;Parallel run:&#039;&#039;&#039; --rerun=&amp;quot;absolute_path_to_empty_file_{runprocess}.txt --replace=&amp;quot;{runprocess}&amp;quot; ({runprocess} will be replaced with the process number for recording fails in the specific run process).&lt;br /&gt;
&#039;&#039;&#039;Since Moodle 3.1 --rerun option don&#039;t accept any value, as it is handled internally by behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Running behat with specified theme (Since Moodle 3.2) ===&lt;br /&gt;
You can run behat with any theme installed. To execute behat with specified theme use &#039;&#039;&#039;--suite=[classic | customtheme ]&#039;&#039;&#039; option, while running behat. By default the features in theme behat folder will be executed for the suite. But if you want to run all core features with the specific theme then initialise acceptance test with --add-core-features-to-theme={THEME_NAME}, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php --add-core-features-to-theme=clean&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first time init runs can be time consuming as it creates a paralell set of tables to core, i.e. bh_user,bh_assign etc. After init the tests can be run with the alternative theme as follows.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --suite=classic --tags=&amp;quot;@enrol_foobar&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If there is no --suite= parameter it will fall back to the default boost theme.  No = or quotes needed around the theme name.&lt;br /&gt;
&lt;br /&gt;
Make sure that &amp;lt;tt&amp;gt;$CFG-&amp;gt;theme&amp;lt;/tt&amp;gt; is &#039;&#039;&#039;not set&#039;&#039;&#039; in your config.php.&lt;br /&gt;
&lt;br /&gt;
==== Override behat core context for theme suite ====&lt;br /&gt;
To override behat step definitions so as to run behat with specified theme, you should create a contexts within &#039;&#039;&#039;/theme/{MYTHEME}/tests/behat/&#039;&#039;&#039; with prefix behat_theme_{MYTHEME}_ and suffixed with the context being overridden. For example, if you want to override behat_mod_forum context, then you should create a class /theme/{MYTHEME}/tests/behat/mod_forum/behat_theme_{MYTHEME}_behat_mod_forum.php&lt;br /&gt;
&lt;br /&gt;
==== Blacklist behat context or features to run in theme suite ====&lt;br /&gt;
To blacklist contexts/ features to be executed by theme suite you should create a /theme/{MYTHEME}/tests/behat/blacklist.json file with following format. Following will not use step_definitions from  behat_grade and behat_navigation while running theme suite. Also, scenarios in auth/tests/behat/login.feature and grade/tests/behat/grade_hidden_items.feature won&#039;t be executed with theme suite.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;contexts&amp;quot;: [&lt;br /&gt;
    &amp;quot;behat_grade&amp;quot;,&lt;br /&gt;
    &amp;quot;behat_navigation&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;features&amp;quot;: [&lt;br /&gt;
    &amp;quot;auth/tests/behat/login.feature&amp;quot;,&lt;br /&gt;
    &amp;quot;grade/tests/behat/grade_hidden_items.feature&amp;quot;,&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Override core behat selectors ====&lt;br /&gt;
To override behat selectors in specific theme, you should create a class behat_theme_{MYTHEME}_behat_selectors in /theme/{MYTHEME}/tests/behat/behat_theme_{MYTHEME}_behat_selectors.php extending behat_selectors.&lt;br /&gt;
&lt;br /&gt;
=== Use php built in web server ===&lt;br /&gt;
You can use php built-in-web server for executing behat runs. To do so:&lt;br /&gt;
# Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# Update $CFG-&amp;gt;behat_wwwroot = localhost:8000; in config.php&lt;br /&gt;
&lt;br /&gt;
=== Define custom options for parallel runs ===&lt;br /&gt;
You can set following custom config options for parallel runs via $CFG-&amp;gt;behat_parallel_run. It&#039;s an array of options where 1st array is for 1st run and so on.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
       array (&lt;br /&gt;
           &#039;dbtype&#039; =&amp;gt; &#039;mysqli&#039;,&lt;br /&gt;
           &#039;dblibrary&#039; =&amp;gt; &#039;native&#039;,&lt;br /&gt;
           &#039;dbhost&#039; =&amp;gt; &#039;localhost&#039;,&lt;br /&gt;
           &#039;dbname&#039; =&amp;gt; &#039;moodletest&#039;,&lt;br /&gt;
           &#039;dbuser&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;dbpass&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;behat_prefix&#039; =&amp;gt; &#039;mdl_&#039;,&lt;br /&gt;
           &#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;,&lt;br /&gt;
           &#039;behat_wwwroot&#039; =&amp;gt; &#039;http://127.0.0.1/moodle&#039;,&lt;br /&gt;
           &#039;behat_dataroot&#039; =&amp;gt; &#039;/home/example/bht_moodledata&#039;&lt;br /&gt;
       )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set different selenium servers for parallel runs, you can use following. NOTE: Running parallel (headless) runs on different selenium servers avoid random focus failures.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    $CFG-&amp;gt;behat_parallel_run = array (&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4445/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4446/wd/hub&#039;),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Write new tests and behat methods ===&lt;br /&gt;
&lt;br /&gt;
If you want to write tests for your own integration, you can do so by creating new tests with format .feature. Follow instructions in [[Writing_acceptance_tests|this page]] to write new tests. &lt;br /&gt;
&lt;br /&gt;
It is also possible to add new steps the moodle behat integration. In order to do so, you will have to create a new .php class with the prefix &#039;&#039;&#039;behat_&#039;&#039;&#039;. Copy the format from &#039;&#039;&#039;lib\behat\behat_base.php&#039;&#039;&#039;, but set your class to extend the behat_base class instead of the MinkExtension. You can define new behat steps by declaring functions with the appropriate heading. &lt;br /&gt;
&lt;br /&gt;
You will not be  able to use these steps and features right away. Check [[Running_acceptance_test#New_step_definitions_or_features_are_not_executed|this section]] for instructions on how to update the behat integration. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For further information on how to create new steps definitions, check [[Acceptance testing/Custom acceptance steps]].&lt;br /&gt;
&lt;br /&gt;
=== Running acceptance tests with different browser ===&lt;br /&gt;
&lt;br /&gt;
If you follow the steps above, Behat will run with Chrome.&lt;br /&gt;
&lt;br /&gt;
You can get it to run with other browsers. The basic idea is to expand the $CFG-&amp;gt;behat_profiles array in config.php to list more browsers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_profiles = array(&lt;br /&gt;
   &#039;chrome&#039; =&amp;gt; array(&lt;br /&gt;
       &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
       &#039;tags&#039; =&amp;gt; &#039;@javascript&#039;,&lt;br /&gt;
   )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Acceptance_testing/Browsers|More info about alternative browsers]]&lt;br /&gt;
&lt;br /&gt;
=== Start multiple selenium servers ===&lt;br /&gt;
From command line Start selenium servers at different ports (say 4444, 4445, 4446 for 3 parallel runs)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4444 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4445 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4446&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative way of running three Selenium servers in parallel:&lt;br /&gt;
&lt;br /&gt;
 $ printf %d\\n {4444..4446} | xargs -n 1 -P 3 java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port&lt;br /&gt;
&lt;br /&gt;
=== Run tests directly in Chrome, with no Selenium ===&lt;br /&gt;
&lt;br /&gt;
Historically, the tests would talk to a Selenium server, which would then tell the target browser what to do. More and more, the browsers themselves contain such a server and you can talk to them directly, which is faster and easier. Work was done to get this working with Chrome in MDL-58948, but it still needs some further setup to get it working, which is detailed in the bug ticket, and which I&#039;ll copy below:&lt;br /&gt;
&lt;br /&gt;
Replace your current behat config with the abve, the api_url is where you&#039;ll talk directly to your Chrome browser.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = [&lt;br /&gt;
    &#039;default&#039; =&amp;gt; [&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
            &#039;DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension&#039; =&amp;gt; [],&lt;br /&gt;
            &#039;Behat\MinkExtension&#039;                                          =&amp;gt; [&lt;br /&gt;
                &#039;browser_name&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                &#039;base_url&#039;     =&amp;gt; $CFG-&amp;gt;behat_wwwroot,&lt;br /&gt;
                &#039;goutte&#039;       =&amp;gt; null,&lt;br /&gt;
                &#039;selenium2&#039;    =&amp;gt; null,&lt;br /&gt;
                &#039;sessions&#039;     =&amp;gt; [&lt;br /&gt;
                    &#039;javascript&#039; =&amp;gt; [&lt;br /&gt;
                        &#039;chrome&#039; =&amp;gt; [&lt;br /&gt;
                            &#039;api_url&#039; =&amp;gt; &#039;http://localhost:9222&#039;&lt;br /&gt;
                        ]&lt;br /&gt;
                    ]&lt;br /&gt;
                ]&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    ],&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use composer to install two more required libraries:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer require --dev dmore/behat-chrome-extension&lt;br /&gt;
composer require --dev dmore/chrome-mink-driver&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you try to run the tests it will tell you that Chrome isn&#039;t running, in a second tab run the following to start Chrome (or chromium-browser on Ubuntu)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;chrome --disable-gpu --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is running headless so you won&#039;t see any windows pop up as the tests run, though it runs in the other mode too.&lt;br /&gt;
&lt;br /&gt;
Behat should now run as before, but faster.&lt;br /&gt;
&lt;br /&gt;
==== Run Chrome locally with Behat and Moodle on a remote server ====&lt;br /&gt;
If you have Moodle running on a remote (headless) server, but don&#039;t want to install a window manager, you can do the following:&lt;br /&gt;
&lt;br /&gt;
1. Go through all the steps from above&lt;br /&gt;
&lt;br /&gt;
2. Establish an SSH SOCKS5 proxy connection to your server:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C USER@SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Forward the port to connect to the DevTools-API of your browser:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C&amp;lt;/code&amp;gt;&lt;br /&gt;
4. Tell your local Chrome to use custom settings:&lt;br /&gt;
&amp;lt;code&amp;gt;/path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, all in one command:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C -f USER@SERVER &amp;amp;&amp;amp; ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C -f &amp;amp;&amp;amp; /path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation for the SSH settings:&lt;br /&gt;
* VARIABLE-PORT-B &amp;amp; VARIABLE-PORT-A : Choose these as you like. Bear in mind that you will need root rights if the port number is 1023 or lower&lt;br /&gt;
* -N: Tells SSH not to open an actual command prompt&lt;br /&gt;
* -C: Compress all data passed through the tunnel&lt;br /&gt;
* -q: Quiet mode. Causes most warning and diagnostic messages to be suppressed&lt;br /&gt;
*-R: Open a tunnel binding to localhost on the remote machine, going to localhost on the local machine&lt;br /&gt;
* -f: Fork the process into background&lt;br /&gt;
&lt;br /&gt;
Explanation for the Chrome settings:&lt;br /&gt;
* --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039; : Tells Chrome to send requests to localhost through the tunnel&lt;br /&gt;
* --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A : To use the SOCKS5 tunnel we just set up&lt;br /&gt;
* --remote-debugging-port=VARIABLE-PORT-B &amp;amp; --remote-debugging-address=0.0.0.0 : To use the SSH tunnel we just set up&lt;br /&gt;
&lt;br /&gt;
=== Using Docker to start selenium server ===&lt;br /&gt;
==== What is Docker ====&lt;br /&gt;
Docker is a app container,  it&#039;s a kind of virtual machine, but only for one app, service,  so you can download&lt;br /&gt;
a docker image and run a selenium server without worry in how to configure selenium in your machine, one for chrome, others for firefox, you either don&#039;t need to install the browsers in your machine&lt;br /&gt;
To install docker follow this link; https://docs.docker.com/engine/installation/&lt;br /&gt;
&lt;br /&gt;
==== Selenium docker images ====&lt;br /&gt;
There is many docker images available,  for many browser, the complete list is in https://hub.docker.com/u/selenium/&lt;br /&gt;
for moodle you can use standalone version.&lt;br /&gt;
You can download  specific selenium version too,  for example,  for firefox,  moodle recommend selenium 2.53.1, see: [https://docs.moodle.org/dev/Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium What version do I need?]&lt;br /&gt;
&lt;br /&gt;
so  the command will be:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
docker run -d -p4444:4444 selenium/standalone-firefox:2.53.1-beryllium&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
to see all available version click in tags.   For firefox you can find at: https://hub.docker.com/r/selenium/standalone-firefox/tags/&lt;br /&gt;
&lt;br /&gt;
==== Change config.php file ====&lt;br /&gt;
In config.php file you must change the $CFG-&amp;gt;behat_wwwroot=   to your network card (NIC) ip address,  you can&#039;t use &lt;br /&gt;
localhost , 127.0.0.1, ...  or selenium docker server  will fail&lt;br /&gt;
&lt;br /&gt;
=== Increasing timeouts ===&lt;br /&gt;
&lt;br /&gt;
You may see errors such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Javascript code and/or AJAX requests are not ready after 10 seconds. &lt;br /&gt;
There is a Javascript error or the code is extremely slow.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sometimes this indicates a genuine problem with the code, but if you are using a slow computer, it could just mean that the browser was not yet ready. You may find that the test works if you run it again. If you get this error frequently, it might be useful to increase the timeout.&lt;br /&gt;
&lt;br /&gt;
It is possible to increase this timeout by adding a line in your config.php. (Requires Moodle versions 3.5 (from 3.5.6), 3.6 (from 3.6.4), or 3.7+.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_increasetimeout = 2;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will increase all the timeouts by a factor of 2; if that isn&#039;t sufficient, you could use 3. &lt;br /&gt;
&lt;br /&gt;
Increasing timeouts will make tests run a bit slower (because there are points where Behat waits up to a timeout to make sure something doesn&#039;t happen) so don&#039;t do this unless you need to.&lt;br /&gt;
&lt;br /&gt;
== NOTE ==&lt;br /&gt;
# Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Disable acceptance test environment ===&lt;br /&gt;
if you want to prevent access to test environment&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --disable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Trouble shooting ==&lt;br /&gt;
&lt;br /&gt;
=== New step definitions or features are not executed === &lt;br /&gt;
If you are adding new tests or steps definitions update the tests list&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --enable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; For parallel runs, all options for initialising parallel runs are valid &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests are failing ===&lt;br /&gt;
&lt;br /&gt;
If you followed all the steps and you receive an unknown weird error probably your browser version is not compatible with the Selenium version you are running.  Please refer Working combinations to ensure you have correct [[Acceptance_testing/Browsers#Working_combinations_of_OS.2BBrowser.2Bselenium]] of them to run acceptance test.&lt;br /&gt;
&lt;br /&gt;
=== The tests are failing, and the error message is completely useless ===&lt;br /&gt;
&lt;br /&gt;
For example, it just says &amp;quot;Error writing to database&amp;quot; with no stack trace.&lt;br /&gt;
&lt;br /&gt;
Add -vv command-line option to get very verbose output.&lt;br /&gt;
&lt;br /&gt;
=== Errors during setup (before test are launched) ===&lt;br /&gt;
Typical errors are:&lt;br /&gt;
* Behat requirement not satisfied: http://127.0.0.1/m/stable_master is not available, ensure you specified correct url and that the server is set up and started.&lt;br /&gt;
* Behat is configured but not enabled on this test site.&lt;br /&gt;
&lt;br /&gt;
In order to fix those errors please check that: the behat_dataroot has correct write permissions and that the $CFG-&amp;gt;behat* variables are placed before the lib/setup.php include:&lt;br /&gt;
 require_once(__DIR__ . &#039;/lib/setup.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Selenium server is not running ===&lt;br /&gt;
==== Chrome specific ====&lt;br /&gt;
&lt;br /&gt;
If you are using chrome, you need to ensure that the driver matches the version of the installed chrome browser – which may change on OS updates/upgrades.  Moodle or Selenium will not give the appropriate message – see [https://tracker.moodle.org/browse/MDL-67659/ MDL-67659].  One solution is the one suggested in the issue and use Andrew Nicols’ [https://github.com/andrewnicols/chromedriver-wrapper/  Chromedriver Wrapper] which will ensure you have the appropriate driver before running the tests.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
* Vagrant profile with Moodle and Behat preconfigured: https://github.com/mackensen/moodle-hat&lt;br /&gt;
* Docker containers for Moodle Developers and Behat: https://github.com/moodlehq/moodle-docker&lt;br /&gt;
* Docker environment with Behat preconfigured : https://github.com/tobiga/docker_moodle_environment&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Acceptance testing for the mobile app]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58260</id>
		<title>Running acceptance test</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58260"/>
		<updated>2021-01-28T14:48:38Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Running behat with specified theme (Since Moodle 3.2) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Short version ==&lt;br /&gt;
&lt;br /&gt;
...or how I got it to work on Ubuntu and some of the problems encountered. &lt;br /&gt;
&lt;br /&gt;
You need a bunch of browsers and terminal windows open to do this.&lt;br /&gt;
&lt;br /&gt;
==== 1. Background ====  &lt;br /&gt;
&lt;br /&gt;
# I am using the desktop version of Ubuntu 17.04 so there are no issues about running this software in headless mode. Running in headless mode was not tested.&lt;br /&gt;
# Moodle is version 3.3 and is a fully installed and working version using the &#039;standard&#039; Ubuntu LAMP stack.&lt;br /&gt;
&lt;br /&gt;
==== 2. Set up Selenium ====&lt;br /&gt;
First, you should have a look at [[Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium#Working_combinations_of_OS.2BBrowser.2Bselenium|working combinations of OS+Browser+selenium]].&lt;br /&gt;
&lt;br /&gt;
# Download the Selenium Standalone Server from [http://www.seleniumhq.org/download/ http://www.seleniumhq.org/download/]. It&#039;s a single JAR file, put it anywhere handy.&lt;br /&gt;
# Download the Chrome driver from [https://sites.google.com/a/chromium.org/chromedriver/ https://sites.google.com/a/chromium.org/chromedriver/]. Ensure you have the right version of the Chrome driver - see [[#Trouble_shooting| Trouble shooting]]. (Firefox is currently problematic. See [[Actual_Selenium_with_old_Firefox_47.0.1]] if you need to try to make it work.)&lt;br /&gt;
# Unzip the driver (it&#039;s a single file) and copy to /usr/local/bin (should work anywhere on the path)&lt;br /&gt;
# If not installed already, &#039;&amp;lt;tt&amp;gt;sudo apt install default-jre&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Start Selenium - &#039;&amp;lt;tt&amp;gt;java -jar /path/to/your/selenium/server/selenium-server-standalone-N.NN.N.jar -port 4444&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# check it works, access &#039;localhost:4444/wd/hub/&#039; in your browser and check you can create a new Chrome session.&lt;br /&gt;
&lt;br /&gt;
If running headless or the above doesn&#039;t work (&amp;quot;Selenium server is not running&amp;quot; when running the behat tests). Try the following&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;Xvfb -ac :99 -screen 0 1280x1024x16 &amp;amp;&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Then immediately, &#039;&amp;lt;tt&amp;gt;export DISPLAY=:99&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# The run the Selenium command as above&lt;br /&gt;
&lt;br /&gt;
==== 3. Set up Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Create a new &#039;dataroot&#039; area for files especially for behat adjusting permissions accordingly. &lt;br /&gt;
# If not there already, add Section 11 from config-dist.php to your config.php file and review the settings. &lt;br /&gt;
# $CFG-&amp;gt;behat_wwwroot needs to point to your Moodle site yet be different from the &#039;normal&#039; wwwroot (e.g. if you used localhost for wwwroot use 127.0.0.1 for the behat_wwwroot). Whatever you choose, make sure it works. &lt;br /&gt;
# $CFG-&amp;gt;behat_dataroot should point to the directory you created above&lt;br /&gt;
# $CFG-&amp;gt;behat_prefix should be fine. &lt;br /&gt;
# Set up $CFG-&amp;gt;behat_profiles to select Chrome as the browser...&lt;br /&gt;
&lt;br /&gt;
     $CFG-&amp;gt;behat_profiles = [&lt;br /&gt;
         &#039;default&#039; =&amp;gt; [&lt;br /&gt;
             &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
             &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
                 &#039;Behat\MinkExtension&#039; =&amp;gt; [&lt;br /&gt;
                     &#039;selenium2&#039; =&amp;gt; [&lt;br /&gt;
                         &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                     ]&lt;br /&gt;
                 ]&lt;br /&gt;
             ]&lt;br /&gt;
         ]&lt;br /&gt;
     ];&lt;br /&gt;
&lt;br /&gt;
==== 4. Configure Behat for Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;php admin/tool/behat/cli/init.php&amp;lt;/tt&amp;gt;&#039; (from the root of your Moodle install). This installs all the required software and creates the test version of Moodle. &lt;br /&gt;
&lt;br /&gt;
==== 5. Run Behat tests ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;vendor/bin/behat&amp;lt;/tt&amp;gt;&#039;. If you don&#039;t want to run all the tests add &#039;&amp;lt;tt&amp;gt;--tags=&amp;quot;@something&amp;quot;&amp;lt;/tt&amp;gt;&#039; where the @something refers to the tags at the top of most feature files. Use comma-separated list like &#039;&amp;lt;tt&amp;gt;@some_thing,@some_thing_else&amp;lt;/tt&amp;gt;&#039; to run tests from multiple areas. See upstream documentation on Gherkin filters for advanced syntax and more complex examples.&lt;br /&gt;
# After some initial setup dots should start to go by. It&#039;s a while before Selenium is first accessed. On the Linux desktop a new Chrome window appears and the testing process &#039;remote control&#039; starts (hopefully!)&lt;br /&gt;
# At the end of each line it shows you the number of steps that have completed so far.&lt;br /&gt;
#* If you are doing a full run, then as of November 2020 there are about 63,000 steps, which took around 25 hours to complete on one test machine (when not using the parallel running feature). Moodle HQ manage complete runs in ~5 hours on a well-optmised set-up, with 3 parallel workers.&lt;br /&gt;
&lt;br /&gt;
== Prerequisite ==&lt;br /&gt;
Before initializing acceptance test environment for running behat, you should ensure:&lt;br /&gt;
# [[Acceptance_testing#Requirements Meet min. system requirements for running tests]]&lt;br /&gt;
# [[Acceptance_testing#Installation Have set min. config variable in config.php for behat]]&lt;br /&gt;
# [[Acceptance_testing#Installation Downloaded composer dependencies]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Acceptance tests (also known as behat), use [http://www.seleniumhq.org/download/ Selenium server] and can be run as:&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; In single run, only one behat run is executed. So all features are executed in this single run.&lt;br /&gt;
# &#039;&#039;&#039;Parallel runs:&#039;&#039;&#039; (Since Moodle 3.0) Parallel runs allow dev&#039;s to execute multiple behat runs together. This was introduced to get acceptance tests results faster. To achieve this:&lt;br /&gt;
#* Features are divided between multiple behat runs&lt;br /&gt;
#* Symlinks behatrun{x} (x being the run process number), are created pointing to moodle directory, so site for run 1 is accessible via https://localhost/moodle/behatrun1&lt;br /&gt;
#* Process number is included as suffix to $CFG-&amp;gt;behat_prefix.&lt;br /&gt;
#* Process number is suffixed to $CFG-&amp;gt;behat_dataroot.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Initialise acceptance test environment ==&lt;br /&gt;
Before running acceptance tests, environment needs to be initialised for acceptance testing.&lt;br /&gt;
&lt;br /&gt;
=== Single run ===&lt;br /&gt;
For initialising acceptance tests for single run, above command is sufficient.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For initialising acceptance tests for parallel runs, you can use one of the following options&lt;br /&gt;
# &#039;&#039;&#039;-j=&amp;lt;number&amp;gt; or --parallel=&amp;lt;number&amp;gt;&#039;&#039;&#039; (required) Number of parallel behat run to initialise&lt;br /&gt;
# &#039;&#039;&#039;-m=&amp;lt;number&amp;gt; or --maxruns=&amp;lt;number&amp;gt;&#039;&#039;&#039;  (optional) Max parallel site which should be initialised at one time. If your system is slow, then you can initialise sites in chucks.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run from. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;--torun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run till. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;-o or --optimize-runs&#039;&#039;&#039; (optional) This option will split features with specified tags in all parallel runs, so they are executed first when parallel run gets executed.&lt;br /&gt;
# &#039;&#039;&#039;-a=&amp;lt;name&amp;gt; or --add-core-features-to-theme=&amp;lt;name&amp;gt;&#039;&#039;&#039; (optional) Since Moodle 3.2. Use this option to add all core features to specified themes (comma separated list of themes)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// Below command will initialise moodle to run 2 parallel tests.&lt;br /&gt;
php admin/tool/behat/cli/init.php --parallel=2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 2: Running acceptance test environment ==&lt;br /&gt;
=== Single run ===&lt;br /&gt;
Run either of the following commands. For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You almost always want to limit the number of tests that are run. To run all the tests in one plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml --tags mod_myplugin&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run all the tests in one .feature file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run a single scenario:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature:40&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &#039;40&#039; is the line-number of the feature file where the Scenario starts.&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For running parallel runs, use following command&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/run.php&lt;br /&gt;
&lt;br /&gt;
Following optional options are available for custom run:&lt;br /&gt;
# &#039;&#039;&#039;--feature&#039;&#039;&#039; Only execute specified feature file (Absolute path of feature file).&lt;br /&gt;
# &#039;&#039;&#039;--suite&#039;&#039;&#039; Features for specified theme will be executed.&lt;br /&gt;
# &#039;&#039;&#039;--replace&#039;&#039;&#039; Replace args string with run process number, useful for output and reruns.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun&#039;&#039;&#039; Execute run starting from (Used for parallel runs on different vms)&lt;br /&gt;
# &#039;&#039;&#039;--torun&#039;&#039;&#039; Execute run till (Used for parallel runs on different vms)&lt;br /&gt;
# Behat options can be passed for filtering features/scenarios:&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests, use the Behat tags option to skip them, &#039;&#039;&#039;--tags=&amp;quot;~@javascript&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific scenario, use the Behat name option to run it, &#039;&#039;&#039;--name=&amp;quot;Filter user accounts by role and cohort&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific feature file, use the Behat feature option to run it, &#039;&#039;&#039;--feature=&amp;quot;/PATH/TO/MOODLE/admin/tests/behat/filter_users.feature&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example: Initialise and run Behat tests for a custom plugin under a custom theme:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/init.php --parallel=3 --add-core-features-to-theme=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
 php admin/tool/behat/cli/run.php --tags=&amp;quot;@tool_myplugin&amp;quot; --suite=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Common options for running tests ===&lt;br /&gt;
==== Tests filters ====&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; iframe&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
==== Output formats ====&lt;br /&gt;
Since Moodle 3.1 option for output is:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=pretty --out=/path/to/pretty.txt --format=moodle_progress --out=std&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Before Moodle 3.1 option for output was:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=&#039;moodle_progress,pretty&#039; --out=&#039;,/path/to/pretty.txt&#039;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Following output formats are supported:&lt;br /&gt;
# &#039;&#039;&#039;progress&#039;&#039;&#039;: Prints one character per step.&lt;br /&gt;
# &#039;&#039;&#039;pretty&#039;&#039;&#039;: Prints the feature as is.&lt;br /&gt;
# &#039;&#039;&#039;junit&#039;&#039;&#039;: Outputs the failures in JUnit compatible files.&lt;br /&gt;
# &#039;&#039;&#039;moodle_progress&#039;&#039;&#039;: Prints Moodle branch information and dots for each step.&lt;br /&gt;
# &#039;&#039;&#039;moodle_list&#039;&#039;&#039;: List all scenarios.&lt;br /&gt;
# &#039;&#039;&#039;moodle_stepcount&#039;&#039;&#039;: List all features with total steps in each feature file. Used for parallel run.&lt;br /&gt;
# &#039;&#039;&#039;moodle_screenshot&#039;&#039;&#039;: (since Moodle 3.1) Take screenshot and core dump of each step. With following options you can dump either or both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;image&amp;quot;}&#039;**: will dump image only&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;}&#039;**: will dump html only.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html,image&amp;quot;}&#039;**: will dump both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;, &amp;quot;dir_permissions&amp;quot;: &amp;quot;0777&amp;quot;}&#039;**&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format. Format &#039;pretty&#039; (&#039;&#039;&#039;-f pretty&#039;&#039;&#039;) is sufficient for most cases, as it outputs each step outcomes in the command line making easier to see the progress.&lt;br /&gt;
&lt;br /&gt;
== Advance usage ==&lt;br /&gt;
=== Rerun failed scenarios ===&lt;br /&gt;
With slow systems or parallel run you might see some random failures, to rerun only failed scenarios (to eliminate random failures), use --rerun option&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; --run=&amp;quot;absolute_path_to_empty_file&amp;quot; (Behat will record failed scenarios in this file, and when run again only failed scenarios will be run)&lt;br /&gt;
# &#039;&#039;&#039;Parallel run:&#039;&#039;&#039; --rerun=&amp;quot;absolute_path_to_empty_file_{runprocess}.txt --replace=&amp;quot;{runprocess}&amp;quot; ({runprocess} will be replaced with the process number for recording fails in the specific run process).&lt;br /&gt;
&#039;&#039;&#039;Since Moodle 3.1 --rerun option don&#039;t accept any value, as it is handled internally by behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Running behat with specified theme (Since Moodle 3.2) ===&lt;br /&gt;
You can run behat with any theme installed. To execute behat with specified theme use &#039;&#039;&#039;--suite=[classic | customtheme ]&#039;&#039;&#039; option, while running behat. By default the features in theme behat folder will be executed for the suite. But if you want to run all core features with the specific theme then initialise acceptance test with --add-core-features-to-theme={THEME_NAME}, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php --add-core-features-to-theme=clean&lt;br /&gt;
vendor/bin/behat --suite=classic --tags=&amp;quot;@enrol_foobar&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If there is no --suite= parameter it will fall back to the default boost theme.  No = or quotes needed around the theme name.&lt;br /&gt;
&lt;br /&gt;
Make sure that &amp;lt;tt&amp;gt;$CFG-&amp;gt;theme&amp;lt;/tt&amp;gt; is &#039;&#039;&#039;not set&#039;&#039;&#039; in your config.php.&lt;br /&gt;
&lt;br /&gt;
==== Override behat core context for theme suite ====&lt;br /&gt;
To override behat step definitions so as to run behat with specified theme, you should create a contexts within &#039;&#039;&#039;/theme/{MYTHEME}/tests/behat/&#039;&#039;&#039; with prefix behat_theme_{MYTHEME}_ and suffixed with the context being overridden. For example, if you want to override behat_mod_forum context, then you should create a class /theme/{MYTHEME}/tests/behat/mod_forum/behat_theme_{MYTHEME}_behat_mod_forum.php&lt;br /&gt;
&lt;br /&gt;
==== Blacklist behat context or features to run in theme suite ====&lt;br /&gt;
To blacklist contexts/ features to be executed by theme suite you should create a /theme/{MYTHEME}/tests/behat/blacklist.json file with following format. Following will not use step_definitions from  behat_grade and behat_navigation while running theme suite. Also, scenarios in auth/tests/behat/login.feature and grade/tests/behat/grade_hidden_items.feature won&#039;t be executed with theme suite.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;contexts&amp;quot;: [&lt;br /&gt;
    &amp;quot;behat_grade&amp;quot;,&lt;br /&gt;
    &amp;quot;behat_navigation&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;features&amp;quot;: [&lt;br /&gt;
    &amp;quot;auth/tests/behat/login.feature&amp;quot;,&lt;br /&gt;
    &amp;quot;grade/tests/behat/grade_hidden_items.feature&amp;quot;,&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Override core behat selectors ====&lt;br /&gt;
To override behat selectors in specific theme, you should create a class behat_theme_{MYTHEME}_behat_selectors in /theme/{MYTHEME}/tests/behat/behat_theme_{MYTHEME}_behat_selectors.php extending behat_selectors.&lt;br /&gt;
&lt;br /&gt;
=== Use php built in web server ===&lt;br /&gt;
You can use php built-in-web server for executing behat runs. To do so:&lt;br /&gt;
# Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# Update $CFG-&amp;gt;behat_wwwroot = localhost:8000; in config.php&lt;br /&gt;
&lt;br /&gt;
=== Define custom options for parallel runs ===&lt;br /&gt;
You can set following custom config options for parallel runs via $CFG-&amp;gt;behat_parallel_run. It&#039;s an array of options where 1st array is for 1st run and so on.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
       array (&lt;br /&gt;
           &#039;dbtype&#039; =&amp;gt; &#039;mysqli&#039;,&lt;br /&gt;
           &#039;dblibrary&#039; =&amp;gt; &#039;native&#039;,&lt;br /&gt;
           &#039;dbhost&#039; =&amp;gt; &#039;localhost&#039;,&lt;br /&gt;
           &#039;dbname&#039; =&amp;gt; &#039;moodletest&#039;,&lt;br /&gt;
           &#039;dbuser&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;dbpass&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;behat_prefix&#039; =&amp;gt; &#039;mdl_&#039;,&lt;br /&gt;
           &#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;,&lt;br /&gt;
           &#039;behat_wwwroot&#039; =&amp;gt; &#039;http://127.0.0.1/moodle&#039;,&lt;br /&gt;
           &#039;behat_dataroot&#039; =&amp;gt; &#039;/home/example/bht_moodledata&#039;&lt;br /&gt;
       )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set different selenium servers for parallel runs, you can use following. NOTE: Running parallel (headless) runs on different selenium servers avoid random focus failures.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    $CFG-&amp;gt;behat_parallel_run = array (&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4445/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4446/wd/hub&#039;),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Write new tests and behat methods ===&lt;br /&gt;
&lt;br /&gt;
If you want to write tests for your own integration, you can do so by creating new tests with format .feature. Follow instructions in [[Writing_acceptance_tests|this page]] to write new tests. &lt;br /&gt;
&lt;br /&gt;
It is also possible to add new steps the moodle behat integration. In order to do so, you will have to create a new .php class with the prefix &#039;&#039;&#039;behat_&#039;&#039;&#039;. Copy the format from &#039;&#039;&#039;lib\behat\behat_base.php&#039;&#039;&#039;, but set your class to extend the behat_base class instead of the MinkExtension. You can define new behat steps by declaring functions with the appropriate heading. &lt;br /&gt;
&lt;br /&gt;
You will not be  able to use these steps and features right away. Check [[Running_acceptance_test#New_step_definitions_or_features_are_not_executed|this section]] for instructions on how to update the behat integration. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For further information on how to create new steps definitions, check [[Acceptance testing/Custom acceptance steps]].&lt;br /&gt;
&lt;br /&gt;
=== Running acceptance tests with different browser ===&lt;br /&gt;
&lt;br /&gt;
If you follow the steps above, Behat will run with Chrome.&lt;br /&gt;
&lt;br /&gt;
You can get it to run with other browsers. The basic idea is to expand the $CFG-&amp;gt;behat_profiles array in config.php to list more browsers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_profiles = array(&lt;br /&gt;
   &#039;chrome&#039; =&amp;gt; array(&lt;br /&gt;
       &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
       &#039;tags&#039; =&amp;gt; &#039;@javascript&#039;,&lt;br /&gt;
   )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Acceptance_testing/Browsers|More info about alternative browsers]]&lt;br /&gt;
&lt;br /&gt;
=== Start multiple selenium servers ===&lt;br /&gt;
From command line Start selenium servers at different ports (say 4444, 4445, 4446 for 3 parallel runs)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4444 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4445 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4446&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative way of running three Selenium servers in parallel:&lt;br /&gt;
&lt;br /&gt;
 $ printf %d\\n {4444..4446} | xargs -n 1 -P 3 java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port&lt;br /&gt;
&lt;br /&gt;
=== Run tests directly in Chrome, with no Selenium ===&lt;br /&gt;
&lt;br /&gt;
Historically, the tests would talk to a Selenium server, which would then tell the target browser what to do. More and more, the browsers themselves contain such a server and you can talk to them directly, which is faster and easier. Work was done to get this working with Chrome in MDL-58948, but it still needs some further setup to get it working, which is detailed in the bug ticket, and which I&#039;ll copy below:&lt;br /&gt;
&lt;br /&gt;
Replace your current behat config with the abve, the api_url is where you&#039;ll talk directly to your Chrome browser.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = [&lt;br /&gt;
    &#039;default&#039; =&amp;gt; [&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
            &#039;DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension&#039; =&amp;gt; [],&lt;br /&gt;
            &#039;Behat\MinkExtension&#039;                                          =&amp;gt; [&lt;br /&gt;
                &#039;browser_name&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                &#039;base_url&#039;     =&amp;gt; $CFG-&amp;gt;behat_wwwroot,&lt;br /&gt;
                &#039;goutte&#039;       =&amp;gt; null,&lt;br /&gt;
                &#039;selenium2&#039;    =&amp;gt; null,&lt;br /&gt;
                &#039;sessions&#039;     =&amp;gt; [&lt;br /&gt;
                    &#039;javascript&#039; =&amp;gt; [&lt;br /&gt;
                        &#039;chrome&#039; =&amp;gt; [&lt;br /&gt;
                            &#039;api_url&#039; =&amp;gt; &#039;http://localhost:9222&#039;&lt;br /&gt;
                        ]&lt;br /&gt;
                    ]&lt;br /&gt;
                ]&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    ],&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use composer to install two more required libraries:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer require --dev dmore/behat-chrome-extension&lt;br /&gt;
composer require --dev dmore/chrome-mink-driver&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you try to run the tests it will tell you that Chrome isn&#039;t running, in a second tab run the following to start Chrome (or chromium-browser on Ubuntu)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;chrome --disable-gpu --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is running headless so you won&#039;t see any windows pop up as the tests run, though it runs in the other mode too.&lt;br /&gt;
&lt;br /&gt;
Behat should now run as before, but faster.&lt;br /&gt;
&lt;br /&gt;
==== Run Chrome locally with Behat and Moodle on a remote server ====&lt;br /&gt;
If you have Moodle running on a remote (headless) server, but don&#039;t want to install a window manager, you can do the following:&lt;br /&gt;
&lt;br /&gt;
1. Go through all the steps from above&lt;br /&gt;
&lt;br /&gt;
2. Establish an SSH SOCKS5 proxy connection to your server:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C USER@SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Forward the port to connect to the DevTools-API of your browser:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C&amp;lt;/code&amp;gt;&lt;br /&gt;
4. Tell your local Chrome to use custom settings:&lt;br /&gt;
&amp;lt;code&amp;gt;/path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, all in one command:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C -f USER@SERVER &amp;amp;&amp;amp; ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C -f &amp;amp;&amp;amp; /path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation for the SSH settings:&lt;br /&gt;
* VARIABLE-PORT-B &amp;amp; VARIABLE-PORT-A : Choose these as you like. Bear in mind that you will need root rights if the port number is 1023 or lower&lt;br /&gt;
* -N: Tells SSH not to open an actual command prompt&lt;br /&gt;
* -C: Compress all data passed through the tunnel&lt;br /&gt;
* -q: Quiet mode. Causes most warning and diagnostic messages to be suppressed&lt;br /&gt;
*-R: Open a tunnel binding to localhost on the remote machine, going to localhost on the local machine&lt;br /&gt;
* -f: Fork the process into background&lt;br /&gt;
&lt;br /&gt;
Explanation for the Chrome settings:&lt;br /&gt;
* --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039; : Tells Chrome to send requests to localhost through the tunnel&lt;br /&gt;
* --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A : To use the SOCKS5 tunnel we just set up&lt;br /&gt;
* --remote-debugging-port=VARIABLE-PORT-B &amp;amp; --remote-debugging-address=0.0.0.0 : To use the SSH tunnel we just set up&lt;br /&gt;
&lt;br /&gt;
=== Using Docker to start selenium server ===&lt;br /&gt;
==== What is Docker ====&lt;br /&gt;
Docker is a app container,  it&#039;s a kind of virtual machine, but only for one app, service,  so you can download&lt;br /&gt;
a docker image and run a selenium server without worry in how to configure selenium in your machine, one for chrome, others for firefox, you either don&#039;t need to install the browsers in your machine&lt;br /&gt;
To install docker follow this link; https://docs.docker.com/engine/installation/&lt;br /&gt;
&lt;br /&gt;
==== Selenium docker images ====&lt;br /&gt;
There is many docker images available,  for many browser, the complete list is in https://hub.docker.com/u/selenium/&lt;br /&gt;
for moodle you can use standalone version.&lt;br /&gt;
You can download  specific selenium version too,  for example,  for firefox,  moodle recommend selenium 2.53.1, see: [https://docs.moodle.org/dev/Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium What version do I need?]&lt;br /&gt;
&lt;br /&gt;
so  the command will be:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
docker run -d -p4444:4444 selenium/standalone-firefox:2.53.1-beryllium&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
to see all available version click in tags.   For firefox you can find at: https://hub.docker.com/r/selenium/standalone-firefox/tags/&lt;br /&gt;
&lt;br /&gt;
==== Change config.php file ====&lt;br /&gt;
In config.php file you must change the $CFG-&amp;gt;behat_wwwroot=   to your network card (NIC) ip address,  you can&#039;t use &lt;br /&gt;
localhost , 127.0.0.1, ...  or selenium docker server  will fail&lt;br /&gt;
&lt;br /&gt;
=== Increasing timeouts ===&lt;br /&gt;
&lt;br /&gt;
You may see errors such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Javascript code and/or AJAX requests are not ready after 10 seconds. &lt;br /&gt;
There is a Javascript error or the code is extremely slow.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sometimes this indicates a genuine problem with the code, but if you are using a slow computer, it could just mean that the browser was not yet ready. You may find that the test works if you run it again. If you get this error frequently, it might be useful to increase the timeout.&lt;br /&gt;
&lt;br /&gt;
It is possible to increase this timeout by adding a line in your config.php. (Requires Moodle versions 3.5 (from 3.5.6), 3.6 (from 3.6.4), or 3.7+.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_increasetimeout = 2;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will increase all the timeouts by a factor of 2; if that isn&#039;t sufficient, you could use 3. &lt;br /&gt;
&lt;br /&gt;
Increasing timeouts will make tests run a bit slower (because there are points where Behat waits up to a timeout to make sure something doesn&#039;t happen) so don&#039;t do this unless you need to.&lt;br /&gt;
&lt;br /&gt;
== NOTE ==&lt;br /&gt;
# Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Disable acceptance test environment ===&lt;br /&gt;
if you want to prevent access to test environment&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --disable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Trouble shooting ==&lt;br /&gt;
&lt;br /&gt;
=== New step definitions or features are not executed === &lt;br /&gt;
If you are adding new tests or steps definitions update the tests list&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --enable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; For parallel runs, all options for initialising parallel runs are valid &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests are failing ===&lt;br /&gt;
&lt;br /&gt;
If you followed all the steps and you receive an unknown weird error probably your browser version is not compatible with the Selenium version you are running.  Please refer Working combinations to ensure you have correct [[Acceptance_testing/Browsers#Working_combinations_of_OS.2BBrowser.2Bselenium]] of them to run acceptance test.&lt;br /&gt;
&lt;br /&gt;
=== The tests are failing, and the error message is completely useless ===&lt;br /&gt;
&lt;br /&gt;
For example, it just says &amp;quot;Error writing to database&amp;quot; with no stack trace.&lt;br /&gt;
&lt;br /&gt;
Add -vv command-line option to get very verbose output.&lt;br /&gt;
&lt;br /&gt;
=== Errors during setup (before test are launched) ===&lt;br /&gt;
Typical errors are:&lt;br /&gt;
* Behat requirement not satisfied: http://127.0.0.1/m/stable_master is not available, ensure you specified correct url and that the server is set up and started.&lt;br /&gt;
* Behat is configured but not enabled on this test site.&lt;br /&gt;
&lt;br /&gt;
In order to fix those errors please check that: the behat_dataroot has correct write permissions and that the $CFG-&amp;gt;behat* variables are placed before the lib/setup.php include:&lt;br /&gt;
 require_once(__DIR__ . &#039;/lib/setup.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Selenium server is not running ===&lt;br /&gt;
==== Chrome specific ====&lt;br /&gt;
&lt;br /&gt;
If you are using chrome, you need to ensure that the driver matches the version of the installed chrome browser – which may change on OS updates/upgrades.  Moodle or Selenium will not give the appropriate message – see [https://tracker.moodle.org/browse/MDL-67659/ MDL-67659].  One solution is the one suggested in the issue and use Andrew Nicols’ [https://github.com/andrewnicols/chromedriver-wrapper/  Chromedriver Wrapper] which will ensure you have the appropriate driver before running the tests.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
* Vagrant profile with Moodle and Behat preconfigured: https://github.com/mackensen/moodle-hat&lt;br /&gt;
* Docker containers for Moodle Developers and Behat: https://github.com/moodlehq/moodle-docker&lt;br /&gt;
* Docker environment with Behat preconfigured : https://github.com/tobiga/docker_moodle_environment&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Acceptance testing for the mobile app]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58256</id>
		<title>Running acceptance test</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58256"/>
		<updated>2021-01-28T12:21:44Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Running behat with specified theme (Since Moodle 3.2) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Short version ==&lt;br /&gt;
&lt;br /&gt;
...or how I got it to work on Ubuntu and some of the problems encountered. &lt;br /&gt;
&lt;br /&gt;
You need a bunch of browsers and terminal windows open to do this.&lt;br /&gt;
&lt;br /&gt;
==== 1. Background ====  &lt;br /&gt;
&lt;br /&gt;
# I am using the desktop version of Ubuntu 17.04 so there are no issues about running this software in headless mode. Running in headless mode was not tested.&lt;br /&gt;
# Moodle is version 3.3 and is a fully installed and working version using the &#039;standard&#039; Ubuntu LAMP stack.&lt;br /&gt;
&lt;br /&gt;
==== 2. Set up Selenium ====&lt;br /&gt;
First, you should have a look at [[Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium#Working_combinations_of_OS.2BBrowser.2Bselenium|working combinations of OS+Browser+selenium]].&lt;br /&gt;
&lt;br /&gt;
# Download the Selenium Standalone Server from [http://www.seleniumhq.org/download/ http://www.seleniumhq.org/download/]. It&#039;s a single JAR file, put it anywhere handy.&lt;br /&gt;
# Download the Chrome driver from [https://sites.google.com/a/chromium.org/chromedriver/ https://sites.google.com/a/chromium.org/chromedriver/]. Ensure you have the right version of the Chrome driver - see [[#Trouble_shooting| Trouble shooting]]. (Firefox is currently problematic. See [[Actual_Selenium_with_old_Firefox_47.0.1]] if you need to try to make it work.)&lt;br /&gt;
# Unzip the driver (it&#039;s a single file) and copy to /usr/local/bin (should work anywhere on the path)&lt;br /&gt;
# If not installed already, &#039;&amp;lt;tt&amp;gt;sudo apt install default-jre&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Start Selenium - &#039;&amp;lt;tt&amp;gt;java -jar /path/to/your/selenium/server/selenium-server-standalone-N.NN.N.jar -port 4444&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# check it works, access &#039;localhost:4444/wd/hub/&#039; in your browser and check you can create a new Chrome session.&lt;br /&gt;
&lt;br /&gt;
If running headless or the above doesn&#039;t work (&amp;quot;Selenium server is not running&amp;quot; when running the behat tests). Try the following&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;Xvfb -ac :99 -screen 0 1280x1024x16 &amp;amp;&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Then immediately, &#039;&amp;lt;tt&amp;gt;export DISPLAY=:99&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# The run the Selenium command as above&lt;br /&gt;
&lt;br /&gt;
==== 3. Set up Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Create a new &#039;dataroot&#039; area for files especially for behat adjusting permissions accordingly. &lt;br /&gt;
# If not there already, add Section 11 from config-dist.php to your config.php file and review the settings. &lt;br /&gt;
# $CFG-&amp;gt;behat_wwwroot needs to point to your Moodle site yet be different from the &#039;normal&#039; wwwroot (e.g. if you used localhost for wwwroot use 127.0.0.1 for the behat_wwwroot). Whatever you choose, make sure it works. &lt;br /&gt;
# $CFG-&amp;gt;behat_dataroot should point to the directory you created above&lt;br /&gt;
# $CFG-&amp;gt;behat_prefix should be fine. &lt;br /&gt;
# Set up $CFG-&amp;gt;behat_profiles to select Chrome as the browser...&lt;br /&gt;
&lt;br /&gt;
     $CFG-&amp;gt;behat_profiles = [&lt;br /&gt;
         &#039;default&#039; =&amp;gt; [&lt;br /&gt;
             &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
             &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
                 &#039;Behat\MinkExtension&#039; =&amp;gt; [&lt;br /&gt;
                     &#039;selenium2&#039; =&amp;gt; [&lt;br /&gt;
                         &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                     ]&lt;br /&gt;
                 ]&lt;br /&gt;
             ]&lt;br /&gt;
         ]&lt;br /&gt;
     ];&lt;br /&gt;
&lt;br /&gt;
==== 4. Configure Behat for Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;php admin/tool/behat/cli/init.php&amp;lt;/tt&amp;gt;&#039; (from the root of your Moodle install). This installs all the required software and creates the test version of Moodle. &lt;br /&gt;
&lt;br /&gt;
==== 5. Run Behat tests ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;vendor/bin/behat&amp;lt;/tt&amp;gt;&#039;. If you don&#039;t want to run all the tests add &#039;&amp;lt;tt&amp;gt;--tags=&amp;quot;@something&amp;quot;&amp;lt;/tt&amp;gt;&#039; where the @something refers to the tags at the top of most feature files. Use comma-separated list like &#039;&amp;lt;tt&amp;gt;@some_thing,@some_thing_else&amp;lt;/tt&amp;gt;&#039; to run tests from multiple areas. See upstream documentation on Gherkin filters for advanced syntax and more complex examples.&lt;br /&gt;
# After some initial setup dots should start to go by. It&#039;s a while before Selenium is first accessed. On the Linux desktop a new Chrome window appears and the testing process &#039;remote control&#039; starts (hopefully!)&lt;br /&gt;
# At the end of each line it shows you the number of steps that have completed so far.&lt;br /&gt;
#* If you are doing a full run, then as of November 2020 there are about 63,000 steps, which took around 25 hours to complete on one test machine (when not using the parallel running feature). Moodle HQ manage complete runs in ~5 hours on a well-optmised set-up, with 3 parallel workers.&lt;br /&gt;
&lt;br /&gt;
== Prerequisite ==&lt;br /&gt;
Before initializing acceptance test environment for running behat, you should ensure:&lt;br /&gt;
# [[Acceptance_testing#Requirements Meet min. system requirements for running tests]]&lt;br /&gt;
# [[Acceptance_testing#Installation Have set min. config variable in config.php for behat]]&lt;br /&gt;
# [[Acceptance_testing#Installation Downloaded composer dependencies]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Acceptance tests (also known as behat), use [http://www.seleniumhq.org/download/ Selenium server] and can be run as:&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; In single run, only one behat run is executed. So all features are executed in this single run.&lt;br /&gt;
# &#039;&#039;&#039;Parallel runs:&#039;&#039;&#039; (Since Moodle 3.0) Parallel runs allow dev&#039;s to execute multiple behat runs together. This was introduced to get acceptance tests results faster. To achieve this:&lt;br /&gt;
#* Features are divided between multiple behat runs&lt;br /&gt;
#* Symlinks behatrun{x} (x being the run process number), are created pointing to moodle directory, so site for run 1 is accessible via https://localhost/moodle/behatrun1&lt;br /&gt;
#* Process number is included as suffix to $CFG-&amp;gt;behat_prefix.&lt;br /&gt;
#* Process number is suffixed to $CFG-&amp;gt;behat_dataroot.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Initialise acceptance test environment ==&lt;br /&gt;
Before running acceptance tests, environment needs to be initialised for acceptance testing.&lt;br /&gt;
&lt;br /&gt;
=== Single run ===&lt;br /&gt;
For initialising acceptance tests for single run, above command is sufficient.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For initialising acceptance tests for parallel runs, you can use one of the following options&lt;br /&gt;
# &#039;&#039;&#039;-j=&amp;lt;number&amp;gt; or --parallel=&amp;lt;number&amp;gt;&#039;&#039;&#039; (required) Number of parallel behat run to initialise&lt;br /&gt;
# &#039;&#039;&#039;-m=&amp;lt;number&amp;gt; or --maxruns=&amp;lt;number&amp;gt;&#039;&#039;&#039;  (optional) Max parallel site which should be initialised at one time. If your system is slow, then you can initialise sites in chucks.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run from. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;--torun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run till. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;-o or --optimize-runs&#039;&#039;&#039; (optional) This option will split features with specified tags in all parallel runs, so they are executed first when parallel run gets executed.&lt;br /&gt;
# &#039;&#039;&#039;-a=&amp;lt;name&amp;gt; or --add-core-features-to-theme=&amp;lt;name&amp;gt;&#039;&#039;&#039; (optional) Since Moodle 3.2. Use this option to add all core features to specified themes (comma separated list of themes)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// Below command will initialise moodle to run 2 parallel tests.&lt;br /&gt;
php admin/tool/behat/cli/init.php --parallel=2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 2: Running acceptance test environment ==&lt;br /&gt;
=== Single run ===&lt;br /&gt;
Run either of the following commands. For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You almost always want to limit the number of tests that are run. To run all the tests in one plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml --tags mod_myplugin&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run all the tests in one .feature file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run a single scenario:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature:40&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &#039;40&#039; is the line-number of the feature file where the Scenario starts.&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For running parallel runs, use following command&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/run.php&lt;br /&gt;
&lt;br /&gt;
Following optional options are available for custom run:&lt;br /&gt;
# &#039;&#039;&#039;--feature&#039;&#039;&#039; Only execute specified feature file (Absolute path of feature file).&lt;br /&gt;
# &#039;&#039;&#039;--suite&#039;&#039;&#039; Features for specified theme will be executed.&lt;br /&gt;
# &#039;&#039;&#039;--replace&#039;&#039;&#039; Replace args string with run process number, useful for output and reruns.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun&#039;&#039;&#039; Execute run starting from (Used for parallel runs on different vms)&lt;br /&gt;
# &#039;&#039;&#039;--torun&#039;&#039;&#039; Execute run till (Used for parallel runs on different vms)&lt;br /&gt;
# Behat options can be passed for filtering features/scenarios:&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests, use the Behat tags option to skip them, &#039;&#039;&#039;--tags=&amp;quot;~@javascript&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific scenario, use the Behat name option to run it, &#039;&#039;&#039;--name=&amp;quot;Filter user accounts by role and cohort&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific feature file, use the Behat feature option to run it, &#039;&#039;&#039;--feature=&amp;quot;/PATH/TO/MOODLE/admin/tests/behat/filter_users.feature&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example: Initialise and run Behat tests for a custom plugin under a custom theme:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/init.php --parallel=3 --add-core-features-to-theme=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
 php admin/tool/behat/cli/run.php --tags=&amp;quot;@tool_myplugin&amp;quot; --suite=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Common options for running tests ===&lt;br /&gt;
==== Tests filters ====&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; iframe&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
==== Output formats ====&lt;br /&gt;
Since Moodle 3.1 option for output is:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=pretty --out=/path/to/pretty.txt --format=moodle_progress --out=std&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Before Moodle 3.1 option for output was:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=&#039;moodle_progress,pretty&#039; --out=&#039;,/path/to/pretty.txt&#039;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Following output formats are supported:&lt;br /&gt;
# &#039;&#039;&#039;progress&#039;&#039;&#039;: Prints one character per step.&lt;br /&gt;
# &#039;&#039;&#039;pretty&#039;&#039;&#039;: Prints the feature as is.&lt;br /&gt;
# &#039;&#039;&#039;junit&#039;&#039;&#039;: Outputs the failures in JUnit compatible files.&lt;br /&gt;
# &#039;&#039;&#039;moodle_progress&#039;&#039;&#039;: Prints Moodle branch information and dots for each step.&lt;br /&gt;
# &#039;&#039;&#039;moodle_list&#039;&#039;&#039;: List all scenarios.&lt;br /&gt;
# &#039;&#039;&#039;moodle_stepcount&#039;&#039;&#039;: List all features with total steps in each feature file. Used for parallel run.&lt;br /&gt;
# &#039;&#039;&#039;moodle_screenshot&#039;&#039;&#039;: (since Moodle 3.1) Take screenshot and core dump of each step. With following options you can dump either or both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;image&amp;quot;}&#039;**: will dump image only&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;}&#039;**: will dump html only.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html,image&amp;quot;}&#039;**: will dump both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;, &amp;quot;dir_permissions&amp;quot;: &amp;quot;0777&amp;quot;}&#039;**&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format. Format &#039;pretty&#039; (&#039;&#039;&#039;-f pretty&#039;&#039;&#039;) is sufficient for most cases, as it outputs each step outcomes in the command line making easier to see the progress.&lt;br /&gt;
&lt;br /&gt;
== Advance usage ==&lt;br /&gt;
=== Rerun failed scenarios ===&lt;br /&gt;
With slow systems or parallel run you might see some random failures, to rerun only failed scenarios (to eliminate random failures), use --rerun option&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; --run=&amp;quot;absolute_path_to_empty_file&amp;quot; (Behat will record failed scenarios in this file, and when run again only failed scenarios will be run)&lt;br /&gt;
# &#039;&#039;&#039;Parallel run:&#039;&#039;&#039; --rerun=&amp;quot;absolute_path_to_empty_file_{runprocess}.txt --replace=&amp;quot;{runprocess}&amp;quot; ({runprocess} will be replaced with the process number for recording fails in the specific run process).&lt;br /&gt;
&#039;&#039;&#039;Since Moodle 3.1 --rerun option don&#039;t accept any value, as it is handled internally by behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Running behat with specified theme (Since Moodle 3.2) ===&lt;br /&gt;
You can run behat with any theme installed. To execute behat with specified theme use &#039;&#039;&#039;--suite={THEME_NAME}&#039;&#039;&#039; option, while running behat. By default the features in theme behat folder will be executed for the suite. But if you want to run all core features with the specific theme then initialise acceptance test with --add-core-features-to-theme={THEME_NAME}, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php --add-core-features-to-theme=clean&lt;br /&gt;
vendor/bin/behat --suite=clean --tags=&amp;quot;@enrol_foobar&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a core theme but it will work with custom theme, (the clean theme has been replaced by classic in later versions of Moodle).  No = or quotes needed around the theme name.&lt;br /&gt;
&lt;br /&gt;
Make sure that &amp;lt;tt&amp;gt;$CFG-&amp;gt;theme&amp;lt;/tt&amp;gt; is &#039;&#039;&#039;not set&#039;&#039;&#039; in your config.php.&lt;br /&gt;
&lt;br /&gt;
==== Override behat core context for theme suite ====&lt;br /&gt;
To override behat step definitions so as to run behat with specified theme, you should create a contexts within &#039;&#039;&#039;/theme/{MYTHEME}/tests/behat/&#039;&#039;&#039; with prefix behat_theme_{MYTHEME}_ and suffixed with the context being overridden. For example, if you want to override behat_mod_forum context, then you should create a class /theme/{MYTHEME}/tests/behat/mod_forum/behat_theme_{MYTHEME}_behat_mod_forum.php&lt;br /&gt;
&lt;br /&gt;
==== Blacklist behat context or features to run in theme suite ====&lt;br /&gt;
To blacklist contexts/ features to be executed by theme suite you should create a /theme/{MYTHEME}/tests/behat/blacklist.json file with following format. Following will not use step_definitions from  behat_grade and behat_navigation while running theme suite. Also, scenarios in auth/tests/behat/login.feature and grade/tests/behat/grade_hidden_items.feature won&#039;t be executed with theme suite.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;contexts&amp;quot;: [&lt;br /&gt;
    &amp;quot;behat_grade&amp;quot;,&lt;br /&gt;
    &amp;quot;behat_navigation&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;features&amp;quot;: [&lt;br /&gt;
    &amp;quot;auth/tests/behat/login.feature&amp;quot;,&lt;br /&gt;
    &amp;quot;grade/tests/behat/grade_hidden_items.feature&amp;quot;,&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Override core behat selectors ====&lt;br /&gt;
To override behat selectors in specific theme, you should create a class behat_theme_{MYTHEME}_behat_selectors in /theme/{MYTHEME}/tests/behat/behat_theme_{MYTHEME}_behat_selectors.php extending behat_selectors.&lt;br /&gt;
&lt;br /&gt;
=== Use php built in web server ===&lt;br /&gt;
You can use php built-in-web server for executing behat runs. To do so:&lt;br /&gt;
# Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# Update $CFG-&amp;gt;behat_wwwroot = localhost:8000; in config.php&lt;br /&gt;
&lt;br /&gt;
=== Define custom options for parallel runs ===&lt;br /&gt;
You can set following custom config options for parallel runs via $CFG-&amp;gt;behat_parallel_run. It&#039;s an array of options where 1st array is for 1st run and so on.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
       array (&lt;br /&gt;
           &#039;dbtype&#039; =&amp;gt; &#039;mysqli&#039;,&lt;br /&gt;
           &#039;dblibrary&#039; =&amp;gt; &#039;native&#039;,&lt;br /&gt;
           &#039;dbhost&#039; =&amp;gt; &#039;localhost&#039;,&lt;br /&gt;
           &#039;dbname&#039; =&amp;gt; &#039;moodletest&#039;,&lt;br /&gt;
           &#039;dbuser&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;dbpass&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;behat_prefix&#039; =&amp;gt; &#039;mdl_&#039;,&lt;br /&gt;
           &#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;,&lt;br /&gt;
           &#039;behat_wwwroot&#039; =&amp;gt; &#039;http://127.0.0.1/moodle&#039;,&lt;br /&gt;
           &#039;behat_dataroot&#039; =&amp;gt; &#039;/home/example/bht_moodledata&#039;&lt;br /&gt;
       )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set different selenium servers for parallel runs, you can use following. NOTE: Running parallel (headless) runs on different selenium servers avoid random focus failures.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    $CFG-&amp;gt;behat_parallel_run = array (&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4445/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4446/wd/hub&#039;),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Write new tests and behat methods ===&lt;br /&gt;
&lt;br /&gt;
If you want to write tests for your own integration, you can do so by creating new tests with format .feature. Follow instructions in [[Writing_acceptance_tests|this page]] to write new tests. &lt;br /&gt;
&lt;br /&gt;
It is also possible to add new steps the moodle behat integration. In order to do so, you will have to create a new .php class with the prefix &#039;&#039;&#039;behat_&#039;&#039;&#039;. Copy the format from &#039;&#039;&#039;lib\behat\behat_base.php&#039;&#039;&#039;, but set your class to extend the behat_base class instead of the MinkExtension. You can define new behat steps by declaring functions with the appropriate heading. &lt;br /&gt;
&lt;br /&gt;
You will not be  able to use these steps and features right away. Check [[Running_acceptance_test#New_step_definitions_or_features_are_not_executed|this section]] for instructions on how to update the behat integration. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For further information on how to create new steps definitions, check [[Acceptance testing/Custom acceptance steps]].&lt;br /&gt;
&lt;br /&gt;
=== Running acceptance tests with different browser ===&lt;br /&gt;
&lt;br /&gt;
If you follow the steps above, Behat will run with Chrome.&lt;br /&gt;
&lt;br /&gt;
You can get it to run with other browsers. The basic idea is to expand the $CFG-&amp;gt;behat_profiles array in config.php to list more browsers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_profiles = array(&lt;br /&gt;
   &#039;chrome&#039; =&amp;gt; array(&lt;br /&gt;
       &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
       &#039;tags&#039; =&amp;gt; &#039;@javascript&#039;,&lt;br /&gt;
   )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Acceptance_testing/Browsers|More info about alternative browsers]]&lt;br /&gt;
&lt;br /&gt;
=== Start multiple selenium servers ===&lt;br /&gt;
From command line Start selenium servers at different ports (say 4444, 4445, 4446 for 3 parallel runs)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4444 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4445 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4446&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative way of running three Selenium servers in parallel:&lt;br /&gt;
&lt;br /&gt;
 $ printf %d\\n {4444..4446} | xargs -n 1 -P 3 java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port&lt;br /&gt;
&lt;br /&gt;
=== Run tests directly in Chrome, with no Selenium ===&lt;br /&gt;
&lt;br /&gt;
Historically, the tests would talk to a Selenium server, which would then tell the target browser what to do. More and more, the browsers themselves contain such a server and you can talk to them directly, which is faster and easier. Work was done to get this working with Chrome in MDL-58948, but it still needs some further setup to get it working, which is detailed in the bug ticket, and which I&#039;ll copy below:&lt;br /&gt;
&lt;br /&gt;
Replace your current behat config with the abve, the api_url is where you&#039;ll talk directly to your Chrome browser.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = [&lt;br /&gt;
    &#039;default&#039; =&amp;gt; [&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
            &#039;DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension&#039; =&amp;gt; [],&lt;br /&gt;
            &#039;Behat\MinkExtension&#039;                                          =&amp;gt; [&lt;br /&gt;
                &#039;browser_name&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                &#039;base_url&#039;     =&amp;gt; $CFG-&amp;gt;behat_wwwroot,&lt;br /&gt;
                &#039;goutte&#039;       =&amp;gt; null,&lt;br /&gt;
                &#039;selenium2&#039;    =&amp;gt; null,&lt;br /&gt;
                &#039;sessions&#039;     =&amp;gt; [&lt;br /&gt;
                    &#039;javascript&#039; =&amp;gt; [&lt;br /&gt;
                        &#039;chrome&#039; =&amp;gt; [&lt;br /&gt;
                            &#039;api_url&#039; =&amp;gt; &#039;http://localhost:9222&#039;&lt;br /&gt;
                        ]&lt;br /&gt;
                    ]&lt;br /&gt;
                ]&lt;br /&gt;
            ]&lt;br /&gt;
        ]&lt;br /&gt;
    ],&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use composer to install two more required libraries:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer require --dev dmore/behat-chrome-extension&lt;br /&gt;
composer require --dev dmore/chrome-mink-driver&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you try to run the tests it will tell you that Chrome isn&#039;t running, in a second tab run the following to start Chrome (or chromium-browser on Ubuntu)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;chrome --disable-gpu --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is running headless so you won&#039;t see any windows pop up as the tests run, though it runs in the other mode too.&lt;br /&gt;
&lt;br /&gt;
Behat should now run as before, but faster.&lt;br /&gt;
&lt;br /&gt;
==== Run Chrome locally with Behat and Moodle on a remote server ====&lt;br /&gt;
If you have Moodle running on a remote (headless) server, but don&#039;t want to install a window manager, you can do the following:&lt;br /&gt;
&lt;br /&gt;
1. Go through all the steps from above&lt;br /&gt;
&lt;br /&gt;
2. Establish an SSH SOCKS5 proxy connection to your server:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C USER@SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Forward the port to connect to the DevTools-API of your browser:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C&amp;lt;/code&amp;gt;&lt;br /&gt;
4. Tell your local Chrome to use custom settings:&lt;br /&gt;
&amp;lt;code&amp;gt;/path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, all in one command:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C -f USER@SERVER &amp;amp;&amp;amp; ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C -f &amp;amp;&amp;amp; /path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation for the SSH settings:&lt;br /&gt;
* VARIABLE-PORT-B &amp;amp; VARIABLE-PORT-A : Choose these as you like. Bear in mind that you will need root rights if the port number is 1023 or lower&lt;br /&gt;
* -N: Tells SSH not to open an actual command prompt&lt;br /&gt;
* -C: Compress all data passed through the tunnel&lt;br /&gt;
* -q: Quiet mode. Causes most warning and diagnostic messages to be suppressed&lt;br /&gt;
*-R: Open a tunnel binding to localhost on the remote machine, going to localhost on the local machine&lt;br /&gt;
* -f: Fork the process into background&lt;br /&gt;
&lt;br /&gt;
Explanation for the Chrome settings:&lt;br /&gt;
* --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039; : Tells Chrome to send requests to localhost through the tunnel&lt;br /&gt;
* --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A : To use the SOCKS5 tunnel we just set up&lt;br /&gt;
* --remote-debugging-port=VARIABLE-PORT-B &amp;amp; --remote-debugging-address=0.0.0.0 : To use the SSH tunnel we just set up&lt;br /&gt;
&lt;br /&gt;
=== Using Docker to start selenium server ===&lt;br /&gt;
==== What is Docker ====&lt;br /&gt;
Docker is a app container,  it&#039;s a kind of virtual machine, but only for one app, service,  so you can download&lt;br /&gt;
a docker image and run a selenium server without worry in how to configure selenium in your machine, one for chrome, others for firefox, you either don&#039;t need to install the browsers in your machine&lt;br /&gt;
To install docker follow this link; https://docs.docker.com/engine/installation/&lt;br /&gt;
&lt;br /&gt;
==== Selenium docker images ====&lt;br /&gt;
There is many docker images available,  for many browser, the complete list is in https://hub.docker.com/u/selenium/&lt;br /&gt;
for moodle you can use standalone version.&lt;br /&gt;
You can download  specific selenium version too,  for example,  for firefox,  moodle recommend selenium 2.53.1, see: [https://docs.moodle.org/dev/Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium What version do I need?]&lt;br /&gt;
&lt;br /&gt;
so  the command will be:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
docker run -d -p4444:4444 selenium/standalone-firefox:2.53.1-beryllium&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
to see all available version click in tags.   For firefox you can find at: https://hub.docker.com/r/selenium/standalone-firefox/tags/&lt;br /&gt;
&lt;br /&gt;
==== Change config.php file ====&lt;br /&gt;
In config.php file you must change the $CFG-&amp;gt;behat_wwwroot=   to your network card (NIC) ip address,  you can&#039;t use &lt;br /&gt;
localhost , 127.0.0.1, ...  or selenium docker server  will fail&lt;br /&gt;
&lt;br /&gt;
=== Increasing timeouts ===&lt;br /&gt;
&lt;br /&gt;
You may see errors such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Javascript code and/or AJAX requests are not ready after 10 seconds. &lt;br /&gt;
There is a Javascript error or the code is extremely slow.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sometimes this indicates a genuine problem with the code, but if you are using a slow computer, it could just mean that the browser was not yet ready. You may find that the test works if you run it again. If you get this error frequently, it might be useful to increase the timeout.&lt;br /&gt;
&lt;br /&gt;
It is possible to increase this timeout by adding a line in your config.php. (Requires Moodle versions 3.5 (from 3.5.6), 3.6 (from 3.6.4), or 3.7+.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_increasetimeout = 2;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will increase all the timeouts by a factor of 2; if that isn&#039;t sufficient, you could use 3. &lt;br /&gt;
&lt;br /&gt;
Increasing timeouts will make tests run a bit slower (because there are points where Behat waits up to a timeout to make sure something doesn&#039;t happen) so don&#039;t do this unless you need to.&lt;br /&gt;
&lt;br /&gt;
== NOTE ==&lt;br /&gt;
# Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Disable acceptance test environment ===&lt;br /&gt;
if you want to prevent access to test environment&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --disable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Trouble shooting ==&lt;br /&gt;
&lt;br /&gt;
=== New step definitions or features are not executed === &lt;br /&gt;
If you are adding new tests or steps definitions update the tests list&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --enable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; For parallel runs, all options for initialising parallel runs are valid &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests are failing ===&lt;br /&gt;
&lt;br /&gt;
If you followed all the steps and you receive an unknown weird error probably your browser version is not compatible with the Selenium version you are running.  Please refer Working combinations to ensure you have correct [[Acceptance_testing/Browsers#Working_combinations_of_OS.2BBrowser.2Bselenium]] of them to run acceptance test.&lt;br /&gt;
&lt;br /&gt;
=== The tests are failing, and the error message is completely useless ===&lt;br /&gt;
&lt;br /&gt;
For example, it just says &amp;quot;Error writing to database&amp;quot; with no stack trace.&lt;br /&gt;
&lt;br /&gt;
Add -vv command-line option to get very verbose output.&lt;br /&gt;
&lt;br /&gt;
=== Errors during setup (before test are launched) ===&lt;br /&gt;
Typical errors are:&lt;br /&gt;
* Behat requirement not satisfied: http://127.0.0.1/m/stable_master is not available, ensure you specified correct url and that the server is set up and started.&lt;br /&gt;
* Behat is configured but not enabled on this test site.&lt;br /&gt;
&lt;br /&gt;
In order to fix those errors please check that: the behat_dataroot has correct write permissions and that the $CFG-&amp;gt;behat* variables are placed before the lib/setup.php include:&lt;br /&gt;
 require_once(__DIR__ . &#039;/lib/setup.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Selenium server is not running ===&lt;br /&gt;
==== Chrome specific ====&lt;br /&gt;
&lt;br /&gt;
If you are using chrome, you need to ensure that the driver matches the version of the installed chrome browser – which may change on OS updates/upgrades.  Moodle or Selenium will not give the appropriate message – see [https://tracker.moodle.org/browse/MDL-67659/ MDL-67659].  One solution is the one suggested in the issue and use Andrew Nicols’ [https://github.com/andrewnicols/chromedriver-wrapper/  Chromedriver Wrapper] which will ensure you have the appropriate driver before running the tests.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
* Vagrant profile with Moodle and Behat preconfigured: https://github.com/mackensen/moodle-hat&lt;br /&gt;
* Docker containers for Moodle Developers and Behat: https://github.com/moodlehq/moodle-docker&lt;br /&gt;
* Docker environment with Behat preconfigured : https://github.com/tobiga/docker_moodle_environment&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Acceptance testing for the mobile app]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Callbacks&amp;diff=58221</id>
		<title>Callbacks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Callbacks&amp;diff=58221"/>
		<updated>2021-01-19T21:03:28Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* List of one-to-many callbacks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle does not have well-defined Hooks API but still allows plugins to hook into different processes by &#039;&#039;&#039;implementing callbacks&#039;&#039;&#039;. See also [[Communication Between Components]].&lt;br /&gt;
&lt;br /&gt;
Some old APIs that were created before object-oriented programming use only callbacks. One of them is [[Activity modules]].&lt;br /&gt;
&lt;br /&gt;
==Types of callbacks in Moodle==&lt;br /&gt;
&lt;br /&gt;
=== Callback functions one-to-many ===&lt;br /&gt;
&lt;br /&gt;
Core has a &amp;quot;hook point&amp;quot; where it allows plugins to execute some code, modify variables or return a result. Sometimes (especially for old callbacks) only plugins of a specific plugin type are allowed, however this is not recommended for the new callbacks because the list of callbacks is now cached and performance is not a constraint any more. If plugins want to implement the function for this callback they normally must place it in &#039;&#039;&#039;lib.php&#039;&#039;&#039; with the name &#039;&#039;&#039;pluginfullname_callbackname()&#039;&#039;&#039;. Here pluginname should be a full plugin name with a prefix, however activity modules can often omit the &amp;quot;mod_&amp;quot; prefix for historical reasons. Implementing this type of callback is optional and the &amp;quot;hook point&amp;quot; does not care how many and which plugins implement callback. Also &amp;quot;hook point&amp;quot; does not check if the plugin is enabled on this site, inside the callback plugins must check it themselves if it is important. Methods &#039;&#039;&#039;get_plugin_list_with_function()&#039;&#039;&#039; and &#039;&#039;&#039;get_plugins_with_function()&#039;&#039;&#039; are normally used in the &amp;quot;hook points&amp;quot; to find all plugins implementing a callback.&lt;br /&gt;
&lt;br /&gt;
This document aims to cover ALL callbacks of this type that are present in Moodle core APIs or in standard Moodle plugins.&lt;br /&gt;
&lt;br /&gt;
=== Callback functions one-to-one ===&lt;br /&gt;
&lt;br /&gt;
Core API (or plugins such as blocks or reports) looks for and executes a method from the plugin/component that &amp;quot;owns&amp;quot; some entity, usually for checking permissions, pre-processing or providing the human-readable representation of this entity. Similar to one-to-many callbacks, the component/plugin must define a function with the name &#039;&#039;&#039;pluginfullname_callbackname()&#039;&#039;&#039; in lib.php . In some cases the function &#039;&#039;must&#039;&#039; be present or otherwise an exception is thrown or debugging message is displayed. Methods &#039;&#039;&#039;component_callback()&#039;&#039;&#039; and &#039;&#039;&#039;component_callback_exists()&#039;&#039;&#039; are normally used to find an implementation of a callback. Unlike one-to-many callbacks the implementing functions can exist not only in plugins but also in core components.&lt;br /&gt;
&lt;br /&gt;
The list of one-to-one callbacks may not be 100% complete in this document, the aim is to cover the &amp;quot;magic&amp;quot; functions that are actually used despite IDE hints.&lt;br /&gt;
&lt;br /&gt;
=== Other ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Files in the specific location&#039;&#039;&#039;. Core APIs may look for plugins that have a file with a specific file name, for example &#039;&#039;&#039;version.php&#039;&#039;&#039;, &#039;&#039;&#039;settings.php&#039;&#039;&#039;, &#039;&#039;&#039;styles.css&#039;&#039;&#039;, &#039;&#039;&#039;module.js&#039;&#039;&#039;, files in &#039;&#039;&#039;db/&#039;&#039;&#039; folder, etc. See [[Plugin files]]&lt;br /&gt;
* &#039;&#039;&#039;Event observers&#039;&#039;&#039;. Each plugin can implement event observers that execute code when event is triggered. See [[Events API#Event_dispatching_and_observers|Events API]] about how to listen to events. Event observers can not always substitute callbacks because they do not return any value and can only happen in case of event. Many &amp;quot;hook points&amp;quot; are necessary before something has happened or when nothing is happening at all, for example a report/summary is gathered. However if it is possible to achieve the desired outcome with event observer, Moodle will not accept requests for adding a &amp;quot;hook point&amp;quot;.&lt;br /&gt;
* Callbacks that are specified in the db/* file, for example in &#039;&#039;&#039;db/service.php&#039;&#039;&#039; developers must specify callback responsible for implementing web service, in &#039;&#039;&#039;db/tags.php&#039;&#039;&#039; developers specify callback for finding tagged items, etc. These types of callbacks are not covered on this page, information about them can be found in the respective APIs.&lt;br /&gt;
&lt;br /&gt;
== Callbacks and external / webservices / consumers (mobile / apps) support ==&lt;br /&gt;
&lt;br /&gt;
=== The problem ===&lt;br /&gt;
&lt;br /&gt;
Our external functions are able to [[Web service API functions|perform a lot of actions]] against core. Those external functions use to implement their functionality reusing [[Core APIs]]. And, those APIs can contain hook points/callbacks to customize Moodle behavior.&lt;br /&gt;
&lt;br /&gt;
Of course, ultimately, those external functions are used by the [[Web_services| web services layer]] providing all the functionality over REST/XMLRCP/SOAP &amp;quot;protocols&amp;quot;. All those &amp;quot;clients&amp;quot; consuming Moodle Webservices (integrations in general, mobile &amp;amp; desktop apps...) should work ok, and we must guarantee that all the code executed in those underlying external functions (that may include hook points/callbacks) is supported by them.&lt;br /&gt;
&lt;br /&gt;
In the other side, some of those callbacks may be focussed entirely in the web version of Moodle and have no application outside from there. Also, sometime, there are callbacks which goal is incompatible with uses from web service consumers, mainly because the consumers don&#039;t support this or that Moodle functionality used by the callback implementations.&lt;br /&gt;
&lt;br /&gt;
Imagine a callback that provides to the consumer with something that it&#039;s not able to manage (say a mustache template, or a moodle form, or any other stuff in general that only core is able to provide). It&#039;s a pretty &amp;quot;possible&amp;quot; case a we need a way to handle it in an organised way.&lt;br /&gt;
&lt;br /&gt;
=== The solution ===&lt;br /&gt;
&lt;br /&gt;
To be able advance with those &amp;quot;problematic&amp;quot; hooks (not being supported by web-service consumers), it has been agreed to proceed with the following points in order to allow them to work via web, avoiding them to impact to consumers and registering the need of introducing (future) viable solutions to enable consumers to work with them.&lt;br /&gt;
&lt;br /&gt;
All the following points must be considered as real requirements in order to allow a new callback (called from externals/web services) to land to core.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Create a linked MOBILE issue&#039;&#039;&#039; requesting the callback to be supported in the app (for the record and future reference). Clearly explaining which are the externals / web services affected, what should be supported and, ideally, a way to provide that.&lt;br /&gt;
# &#039;&#039;&#039;Clearly indicate in the issue&#039;&#039;&#039; introducing the new callback if the hook is supported or not via WebServices. Callbacks documentation (below in this page) &#039;&#039;&#039;must include the comment&#039;&#039;&#039; &#039;&#039;&amp;quot;Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-xxxx and MOBILE-xxxx for more info.&amp;quot;&#039;&#039;&amp;quot; (where the MDL and MOBILE issues are the related ones).&lt;br /&gt;
# &#039;&#039;&#039;Add manual tests&#039;&#039;&#039; in the issue for checking that the related functionality in the mobile / desktop app is not broken and everything continues working ok.&lt;br /&gt;
# Check that the &#039;&#039;&#039;modified code or APIs do not impact on the external / WebServices&#039;&#039;&#039; API. You can just check if the modified function is used by the external API just adding a debug message and then running WebServices.&lt;br /&gt;
# If you need to add code in an API already used by the external API, you can always &#039;&#039;&#039;use the WS_SERVER constant&#039;&#039;&#039; to check if the current request comes from the WS layer to &#039;&#039;&#039;avoid its execution&#039;&#039;&#039;. With links to the corresponding MDL-xxxx and MOBILE-xxxx issues.&lt;br /&gt;
# In any case, &#039;&#039;&#039;it&#039;s the responsibility of every plugin implementing a not compatible callback to prevent any action&#039;&#039;&#039; that may affect / impact the WS layer. Core (hook points) will always perform the calls to the callbacks, unconditionally.&lt;br /&gt;
&lt;br /&gt;
== List of Moodle callbacks ==&lt;br /&gt;
&lt;br /&gt;
=== List of one-to-many callbacks ===&lt;br /&gt;
&lt;br /&gt;
To implement one of these callbacks plugins must add a function &#039;&#039;&#039;pluginfullname_callbackname()&#039;&#039;&#039; in &#039;&#039;&#039;lib.php&#039;&#039;&#039; unless stated otherwise. The &#039;&#039;pluginfullname&#039;&#039; is the name of the plugin with the frankenstyle prefix. For activity modules it is acceptable to omit the &#039;&#039;mod_&#039;&#039; prefix. Refer to the linked documentation or search Moodle code by the callback name to find where it is called, what arguments are supplied and what return value is expected.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Callback&lt;br /&gt;
! Plugin type&lt;br /&gt;
! Version&lt;br /&gt;
! Comments&lt;br /&gt;
|-&lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Navigation, see [[Navigation API]]&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| extend_navigation_course&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| before Moodle 3.0 was only supported by &#039;&#039;report&#039;&#039; and &#039;&#039;tool&#039;&#039; plugin types&lt;br /&gt;
|-&lt;br /&gt;
| extend_settings_navigation&lt;br /&gt;
| local, booktool&lt;br /&gt;
|&lt;br /&gt;
| &#039;&#039;Note, modules have a one-to-one callback with the same name, see below&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| extend_navigation&lt;br /&gt;
| local&lt;br /&gt;
|&lt;br /&gt;
| &#039;&#039;Note, modules have a one-to-one callback with the same name, see below&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| extend_navigation_user_settings&lt;br /&gt;
| *&lt;br /&gt;
| 3.0+&lt;br /&gt;
| before Moodle 3.0 was only supported by &#039;&#039;tool&#039;&#039; plugin types&lt;br /&gt;
|-&lt;br /&gt;
| extend_navigation_category_settings&lt;br /&gt;
| *&lt;br /&gt;
| 3.0+&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| extend_navigation_frontpage&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| extend_navigation_user&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;My profile, see [[My profile API]]&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| myprofile_navigation&lt;br /&gt;
| *&lt;br /&gt;
| 2.9+&lt;br /&gt;
|&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Before-actions hooks&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| course_module_background_deletion_recommended&lt;br /&gt;
| *&lt;br /&gt;
| 3.2+&lt;br /&gt;
| see [https://github.com/moodle/moodle/blob/MOODLE_32_STABLE/lib/upgrade.txt#L142 upgrade.txt]&lt;br /&gt;
|-&lt;br /&gt;
| pre_block_delete&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| pre_course_category_delete&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| pre_course_delete&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| pre_course_module_delete&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| pre_user_delete&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;[[Login_callbacks]]&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#after_config | after_config]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+&lt;br /&gt;
| Triggered as soon as practical on every moodle bootstrap after config has been loaded. The $USER object is available at this point too.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#after_require_login | after_require_login]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.7+&lt;br /&gt;
| eg Add permissions logic across a site or course&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#check_password_policy | check_password_policy]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.6+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#print_password_policy | print_password_policy]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#pre_signup_requests | pre_signup_requests]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.5&lt;br /&gt;
| eg to do actions before sign up such as acceptance of policies, validations, etc&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#extend_change_password_form | extend_change_password_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Injecting form elements into the change password form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#extend_set_password_form | extend_set_password_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Injecting form elements into the set password form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#extend_forgot_password_form | extend_forgot_password_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Injecting form elements into the forgot password form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#extend_signup_form | extend_signup_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Injecting form elements into the signup form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#validate_extend_change_password_form | validate_extend_change_password_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Adding additional validation to the change password form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#validate_extend_set_password_form | validate_extend_set_password_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Adding additional validation to the set password form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#validate_extend_forgot_password_form | validate_extend_forgot_password_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Adding additional validation to the forgot password form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#validate_extend_signup_form | validate_extend_signup_form]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Adding additional validation to the signup form. Note: This hook is not compatible with the Webservices API or the Moodle mobile app. See MDL-66173 and MOBILE-3181 for more info.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#post_change_password_requests | post_change_password_requests]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Fire additional actions after a user changes password.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#post_set_password_requests | post_set_password_requests]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Fire additional actions after a user resets password.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#post_forgot_password_requests | post_forgot_password_requests]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Fire additional actions after a user submits a password reset request.&lt;br /&gt;
|-&lt;br /&gt;
| [[Login_callbacks#post_signup_requests | post_signup_requests]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.8+ (WIP)&lt;br /&gt;
| eg Fire additional actions after a user creates an account.&lt;br /&gt;
|-&lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Page rendering, see [[Output_callbacks]]&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| [[Output_callbacks#add_htmlattributes | add_htmlattributes]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| eg Add open graph xml namespace attributes&lt;br /&gt;
|-&lt;br /&gt;
| [[Output_callbacks#before_footer | before_footer]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| eg injecting JS across the site, like analytics&lt;br /&gt;
|-&lt;br /&gt;
| [[Output_callbacks#before_http_headers | before_http_headers]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| Setting http headers across the site like CSP&lt;br /&gt;
|-&lt;br /&gt;
| [[Output_callbacks#before_standard_html_head | before_standard_html_head]]&lt;br /&gt;
&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| A better API alternative to appending to $CFG-&amp;gt;additionalhtmlhead&lt;br /&gt;
|-&lt;br /&gt;
| [[Output_callbacks#before_standard_top_of_body_html | before_standard_top_of_body_html]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| [[Output_callbacks#render_navbar_output | render_navbar_output]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.2+&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Course module edit form&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| coursemodule_edit_post_actions&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| coursemodule_standard_elements&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| Takes parameters $formwrapper and $mform, allows manipulation of editing form, e.g. additional fields. See  https://github.com/marcusgreen/moodle-local_callbacks&lt;br /&gt;
|-&lt;br /&gt;
| coursemodule_validation&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Modules&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| check_updates_since&lt;br /&gt;
| mod&lt;br /&gt;
| 3.2+&lt;br /&gt;
| See [[NEWMODULE_Documentation]]&lt;br /&gt;
|-&lt;br /&gt;
| dndupload_register&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Admin&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| bulk_user_actions&lt;br /&gt;
| *&lt;br /&gt;
| 3.9+&lt;br /&gt;
| Any plugin typically an admin tool can add new bulk user actions&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Other&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| get_fontawesome_icon_map&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| https://docs.moodle.org/dev/Moodle_icons#Font_awesome_icons&lt;br /&gt;
|-&lt;br /&gt;
| get_question_bank_search_conditions&lt;br /&gt;
| local&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| oauth2_system_scopes&lt;br /&gt;
| *&lt;br /&gt;
| 3.3+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| rss_get_feed&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| supports_logstore&lt;br /&gt;
| report&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_shortcuts&lt;br /&gt;
| ltisource&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| before_launch&lt;br /&gt;
| ltisource&lt;br /&gt;
| 2.8+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| [[Miscellaneous_callbacks#control_view_profile | control_view_profile]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.6+&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| [[Miscellaneous_callbacks#store_profiling_data | store_profiling_data ]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.6+&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| [[Miscellaneous_callbacks#override_webservice_execution | override_webservice_execution]]&lt;br /&gt;
| *&lt;br /&gt;
| 3.6+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Deprecated&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| cron&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| See [[Task API]]&lt;br /&gt;
|-&lt;br /&gt;
| delete_course&lt;br /&gt;
| mod,report,coursereport,format&lt;br /&gt;
| &lt;br /&gt;
| Replace with observer to course_contents_deleted event&lt;br /&gt;
|-&lt;br /&gt;
| print_overview&lt;br /&gt;
| mod&lt;br /&gt;
| up to 3.2&lt;br /&gt;
| New dashboard uses [[Calendar API]] to populate events on the timeline&lt;br /&gt;
|-&lt;br /&gt;
| report_extend_navigation&lt;br /&gt;
| coursereport&lt;br /&gt;
| &lt;br /&gt;
| Plugin type &#039;&#039;coursereport&#039;&#039; is deprecated, plugin type &#039;&#039;report&#039;&#039; should be used instead&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
if Moodle version is not specified, this means that callback existed for a long time and can be found in all [[Releases|currently supported]] Moodle versions&lt;br /&gt;
&lt;br /&gt;
=== List of one-to-one callbacks ===&lt;br /&gt;
&lt;br /&gt;
To implement one of these callbacks plugins must add a function &#039;&#039;&#039;pluginfullname_callbackname()&#039;&#039;&#039; in &#039;&#039;&#039;lib.php&#039;&#039;&#039; unless stated otherwise. The &#039;&#039;pluginfullname&#039;&#039; is the name of the plugin with the frankenstyle prefix. For activity modules it is acceptable to omit the &#039;&#039;mod_&#039;&#039; prefix. Refer to the linked documentation or search Moodle code by the callback name to find where it is called, what arguments are supplied and what return value is expected.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Callback&lt;br /&gt;
! Plugin type&lt;br /&gt;
! Version&lt;br /&gt;
! Comments&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Comments support&#039;&#039;&#039;, see [[Comment API]]&lt;br /&gt;
|-&lt;br /&gt;
| comment_add&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| comment_display&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| comment_permissions&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| comment_template&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| comment_url&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| comment_validate&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Gradebook&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| export_%_settings_definition&lt;br /&gt;
| gradeexport&lt;br /&gt;
| &lt;br /&gt;
| % is a plugin name &#039;&#039;without&#039;&#039; prefix&lt;br /&gt;
|-&lt;br /&gt;
| import_%_settings_definition&lt;br /&gt;
| gradeimport&lt;br /&gt;
| &lt;br /&gt;
| % is a plugin name &#039;&#039;without&#039;&#039; prefix&lt;br /&gt;
|-&lt;br /&gt;
| report_%_profilereport&lt;br /&gt;
| gradereport&lt;br /&gt;
| &lt;br /&gt;
| % is a plugin name &#039;&#039;without&#039;&#039; prefix&lt;br /&gt;
|-&lt;br /&gt;
| report_%_settings_definition&lt;br /&gt;
| gradereport&lt;br /&gt;
| &lt;br /&gt;
| % is a plugin name &#039;&#039;without&#039;&#039; prefix&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Groups support&#039;&#039;&#039;, see [[Groups API]]&lt;br /&gt;
|-&lt;br /&gt;
| allow_group_member_remove&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| restore_group_member&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| For plugins that create their own groups&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Installation and upgrade&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| xmldb_%_install&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Located in db/install.php , % refer to the full plugin name, in case of modules without prefix&lt;br /&gt;
|-&lt;br /&gt;
| xmldb_%_install_recovery&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Located in db/install.php , % refer to the full plugin name, in case of modules without prefix&lt;br /&gt;
|-&lt;br /&gt;
| xmldb_%_uninstall&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Located in db/uninstall.php , % refer to the full plugin name, in case of modules without prefix&lt;br /&gt;
|-&lt;br /&gt;
| xmldb_%_upgrade&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Located in db/upgrade.php , % refer to the full plugin name, in case of modules without prefix&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;LTI source&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| add_instance_hook&lt;br /&gt;
| ltisource&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;messagetype&#039;&#039;&lt;br /&gt;
| ltisource&lt;br /&gt;
| &lt;br /&gt;
| Callback name is the type of the message&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Question bank support&#039;&#039;&#039;, see [[Question API]]&lt;br /&gt;
|-&lt;br /&gt;
| question_pluginfile&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| question_preview_pluginfile&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| questions_in_use&lt;br /&gt;
| *&lt;br /&gt;
| since 3.7.5, 3.8.2 (previously only &amp;quot;mod&amp;quot;)&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Ratings support&#039;&#039;&#039;, see [[Rating API]]&lt;br /&gt;
|-&lt;br /&gt;
| rating_can_see_item_ratings&lt;br /&gt;
| *&lt;br /&gt;
| 2.9.2+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| rating_can_see_item_ratings&lt;br /&gt;
| *&lt;br /&gt;
| 2.9.2+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| rating_get_item_fields&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| rating_permissions&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| rating_validate&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Themes&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| $THEME-&amp;gt;csspostprocess&lt;br /&gt;
| theme&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| $THEME-&amp;gt;extralesscallback&lt;br /&gt;
| theme&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| $THEME-&amp;gt;lessvariablescallback&lt;br /&gt;
| theme&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| page_init&lt;br /&gt;
| theme&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Modules: Calendar and dashboard&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| core_calendar_event_action_shows_item_count&lt;br /&gt;
| mod&lt;br /&gt;
| 3.3+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| core_calendar_is_event_visible&lt;br /&gt;
| mod&lt;br /&gt;
| 3.3+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| core_calendar_provide_event_action&lt;br /&gt;
| mod&lt;br /&gt;
| 3.3+&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Modules: Course cache&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| cm_info_dynamic&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| cm_info_view&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_coursemodule_info&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Modules: Course reset&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| reset_course_form_defaults&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| reset_course_form_definition&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| reset_userdata&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Modules&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| delete_instance&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| dndupload_handle&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| export_contents&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| Used in WS get_course_contents&lt;br /&gt;
|-&lt;br /&gt;
| extend_settings_navigation&lt;br /&gt;
| mod,booktool&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| extends_navigation&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_completion_active_rule_descriptions&lt;br /&gt;
| mod&lt;br /&gt;
| 3.3+&lt;br /&gt;
| Must be present for modules implementing custom completion rules&lt;br /&gt;
|-&lt;br /&gt;
| get_completion_state&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_extra_capabilities&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_file_areas&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_recent_mod_activity&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| get_shortcuts&lt;br /&gt;
| mod&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| grade_item_update&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| grading_areas_list&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| print_recent_activity&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| print_recent_mod_activity&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| refresh_events&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| rescale_activity_grades&lt;br /&gt;
| mod&lt;br /&gt;
| 3.1+&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| scale_used_anywhere&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| update_grades&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| user_complete&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| user_outline&lt;br /&gt;
| mod&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Glossary formats&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| glossary_print_entry_%&lt;br /&gt;
| for glossary formats&lt;br /&gt;
| &lt;br /&gt;
| Glossary formats is not a plugin type yet, however the list of formats is not hardcoded in the mod_glossary, instead the methods similar to callbacks are used for each subfolder in mod/glossar/format. % refer to the subfolder name, the functions are expected in lib.php&lt;br /&gt;
|-&lt;br /&gt;
| glossary_show_entry_%&lt;br /&gt;
| for glossary formats&lt;br /&gt;
| &lt;br /&gt;
|  - &amp;quot; -&lt;br /&gt;
|-&lt;br /&gt;
| glossary_show_entry_%&lt;br /&gt;
| for glossary formats&lt;br /&gt;
| &lt;br /&gt;
| - &amp;quot; -&lt;br /&gt;
|-&lt;br /&gt;
| glossary_show_entry_%&lt;br /&gt;
| for glossary formats&lt;br /&gt;
| &lt;br /&gt;
| - &amp;quot; -&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Other&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| global_db_replace&lt;br /&gt;
| block&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| inplace_editable&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| See [[Inplace editable]]&lt;br /&gt;
|-&lt;br /&gt;
| output_fragment_*&lt;br /&gt;
| *&lt;br /&gt;
| 3.1+&lt;br /&gt;
| see [[Fragment]]&lt;br /&gt;
|-&lt;br /&gt;
| page_type_list&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Used when displaying page types in block configuration&lt;br /&gt;
|-&lt;br /&gt;
| params_for_js&lt;br /&gt;
| atto&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| pluginfile&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Callback checking permissions and preparing the file for serving plugin files, see [[File API]]. Note, in case of &#039;&#039;block&#039;&#039; plugins the list of arguments is slightly different&lt;br /&gt;
|-&lt;br /&gt;
| restore_role_assignment&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| For plugins that create their own role assignments&lt;br /&gt;
|-&lt;br /&gt;
| strings_for_js&lt;br /&gt;
| atto&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| supports&lt;br /&gt;
| *&lt;br /&gt;
| &lt;br /&gt;
| Required for activity modules&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4 align=center | &#039;&#039;&#039;Deprecated&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| ajax_section_move&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| ajax_support&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| delete_course&lt;br /&gt;
| mod&lt;br /&gt;
| up to 3.1&lt;br /&gt;
| use event observer&lt;br /&gt;
|-&lt;br /&gt;
| display_content&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| get_post_actions&lt;br /&gt;
| mod,booktool&lt;br /&gt;
| &lt;br /&gt;
| Only called if legacy log is used on the site&lt;br /&gt;
|-&lt;br /&gt;
| get_section_name&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| get_section_url&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| get_types&lt;br /&gt;
| mod,ltisource&lt;br /&gt;
| up to 3.0&lt;br /&gt;
| Replaced with &#039;&#039;get_shortcuts&#039;&#039; in 3.1&lt;br /&gt;
|-&lt;br /&gt;
| get_view_actions&lt;br /&gt;
| mod,booktool&lt;br /&gt;
| &lt;br /&gt;
| Only called if legacy log is used on the site&lt;br /&gt;
|-&lt;br /&gt;
| load_content&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| scale_used&lt;br /&gt;
| mod&lt;br /&gt;
| up to 3.0&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| uses_sections&lt;br /&gt;
| format&lt;br /&gt;
| up to 2.3&lt;br /&gt;
| See [[Course formats]]&lt;br /&gt;
|-&lt;br /&gt;
| question_list_instances&lt;br /&gt;
| mod&lt;br /&gt;
| up to 3.8&lt;br /&gt;
| Use &amp;quot;questions_in_use&amp;quot; instead&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notes:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
if Moodle version is not specified, this means that callback existed for a long time and can be found in all [[Releases|currently supported]] Moodle versions&lt;br /&gt;
&lt;br /&gt;
== Adding new callbacks to core ==&lt;br /&gt;
&lt;br /&gt;
If you are preparing a patch for core which adds a new callback here are some things which should be considered.&lt;br /&gt;
&lt;br /&gt;
TBA see https://tracker.moodle.org/browse/MDL-60510&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58060</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58060"/>
		<updated>2020-11-14T15:43:38Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Code Formatting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Intellisense ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: [[File:phpcs_sniff.png]]&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v2.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
To do so, run the following in your terminal from your moodle folder:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer global require &amp;quot;squizlabs/php_codesniffer=2.*&amp;quot;&lt;br /&gt;
composer require --dev &amp;quot;blackboard-open-source/moodle-coding-standard&amp;quot; # installs moodle&#039;s coding standard&lt;br /&gt;
phpcs  --config-set  installed_paths vendor/blackboard-open-source/moodle-coding-standard # adds moodle&#039;s standard to phpcs&lt;br /&gt;
phpcs -i # checks which standards are available to phpcs&lt;br /&gt;
phpcs --config-set default_standard moodle # sets moodle as the default standard for phpcs&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
If it is installed moodle will show up in the output of `phpcs -i`, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Formatting ==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, configure it to be the default formatter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
== Behat/Gherkin/Cucumber Formatting ==&lt;br /&gt;
This plugin offers colour syntax formatting for behat .feature files. &lt;br /&gt;
I have not found a plugin that will format .feature files consistent with the expected indentations&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=Blodwynn.featurehighlight&lt;br /&gt;
&lt;br /&gt;
== Automated testing ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
&lt;br /&gt;
== Docblocks ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;code&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/code&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58016</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58016"/>
		<updated>2020-11-07T22:20:31Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Debugging */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions. &lt;br /&gt;
&lt;br /&gt;
It allows the setting of breakpoints where the contents of variables can be inspected. Breakpoints can be conditional, e.g. break execution of a loop when a variable reaches a certain value.&lt;br /&gt;
&lt;br /&gt;
== Intellisense ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: [[File:phpcs_sniff.png]]&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v2.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
To do so, run the following in your terminal from your moodle folder:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer global require &amp;quot;squizlabs/php_codesniffer=2.*&amp;quot;&lt;br /&gt;
composer require --dev &amp;quot;blackboard-open-source/moodle-coding-standard&amp;quot; # installs moodle&#039;s coding standard&lt;br /&gt;
phpcs  --config-set  installed_paths vendor/blackboard-open-source/moodle-coding-standard # adds moodle&#039;s standard to phpcs&lt;br /&gt;
phpcs -i # checks which standards are available to phpcs&lt;br /&gt;
phpcs --config-set default_standard moodle # sets moodle as the default standard for phpcs&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
If it is installed moodle will show up in the output of `phpcs -i`, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Formatting ==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, configure it to be the default formatter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automated testing ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
&lt;br /&gt;
== Docblocks ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;code&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/code&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58014</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=58014"/>
		<updated>2020-11-07T22:01:00Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Automated testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://en.wikipedia.org/wiki/Visual_Studio_Code VSCode] is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug PHP Debug] adds debugging capability for PHP files, which is essential. Follow the extension&#039;s installation instructions.&lt;br /&gt;
&lt;br /&gt;
== Intellisense ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense] is the standard php plugin for [https://code.visualstudio.com/docs/editor/intellisense intellisense] features.&lt;br /&gt;
&lt;br /&gt;
== Linting ==&lt;br /&gt;
[https://en.wikipedia.org/wiki/Lint_(software) Linting] plugins will show wavy red lines under code that does not conform: [[File:phpcs_sniff.png]]&lt;br /&gt;
The linters used for development are:&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint stylelint] for CSS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint ESLint] for JS&lt;br /&gt;
* [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] for PHP. It requires [https://github.com/squizlabs/PHP_CodeSniffer phpcs v2.* (package)] installed and configured to use moodle&#039;s standards.&lt;br /&gt;
To do so, run the following in your terminal from your moodle folder:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer global require &amp;quot;squizlabs/php_codesniffer=2.*&amp;quot;&lt;br /&gt;
composer require --dev &amp;quot;blackboard-open-source/moodle-coding-standard&amp;quot; # installs moodle&#039;s coding standard&lt;br /&gt;
phpcs  --config-set  installed_paths vendor/blackboard-open-source/moodle-coding-standard # adds moodle&#039;s standard to phpcs&lt;br /&gt;
phpcs -i # checks which standards are available to phpcs&lt;br /&gt;
phpcs --config-set default_standard moodle # sets moodle as the default standard for phpcs&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
If it is installed moodle will show up in the output of `phpcs -i`, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Formatting ==&lt;br /&gt;
If you have [https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer PHP Sniffer] installed, configure it to be the default formatter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// add this [php] key/value pair in vscode&#039;s user settings (settings.json):&lt;br /&gt;
{&lt;br /&gt;
  // ...&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Automated testing ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit Yet Another PHPUnit] lets you run automated tests from within vscode.&lt;br /&gt;
&lt;br /&gt;
It inserts a link just above the class name that says &#039;Run class tests&#039; which will run all the tests in a class and links above each function that says Run test that will run just that test.&lt;br /&gt;
&lt;br /&gt;
[[File:yet_another_phpunit.png]]&lt;br /&gt;
&lt;br /&gt;
== Docblocks ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker PHP DocBlocker] to create a docblock by typing /** at the top of a function and it grabs the parameters, including types if given and creates a PHPDoc block.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete ==&lt;br /&gt;
[https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets Moodle - Snippets &amp;amp; Autocomplete] offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;lt;code&amp;gt;&amp;quot;files.trimTrailingWhitespace&amp;quot;: true&amp;lt;/code&amp;gt; setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:yet_another_phpunit.png&amp;diff=58013</id>
		<title>File:yet another phpunit.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:yet_another_phpunit.png&amp;diff=58013"/>
		<updated>2020-11-07T21:56:29Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: Yet another php unit plugin for VSCode&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Yet another php unit plugin for VSCode&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57988</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57988"/>
		<updated>2020-11-04T20:51:41Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer global require &amp;quot;squizlabs/php_codesniffer=2.*&amp;quot;&lt;br /&gt;
composer global install&lt;br /&gt;
composer require --dev &amp;quot;blackboard-open-source/moodle-coding-standard&amp;quot;&lt;br /&gt;
phpcs  --config-set  installed_paths vendor/blackboard-open-source/moodle-coding-standard&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
&lt;br /&gt;
Configure it to be the default formatter in settings like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57987</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57987"/>
		<updated>2020-11-04T20:51:12Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
composer global require &amp;quot;squizlabs/php_codesniffer=2.*&amp;quot;&lt;br /&gt;
composer global install&lt;br /&gt;
composer require --dev &amp;quot;blackboard-open-source/moodle-coding-standard&amp;quot;&lt;br /&gt;
phpcs  --config-set  installed_paths vendor/blackboard-open-source/moodle-coding-standard&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
&lt;br /&gt;
Configure it to be the default formatter in settings like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57986</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57986"/>
		<updated>2020-11-04T20:36:05Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
&lt;br /&gt;
Configure it to be the default formatter in settings like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57985</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57985"/>
		<updated>2020-11-04T20:35:27Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
Configure it to be the default formatter in settings like this&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;[php]&amp;quot;: {&lt;br /&gt;
    &amp;quot;editor.defaultFormatter&amp;quot;: &amp;quot;wongjn.php-sniffer&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57984</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57984"/>
		<updated>2020-11-04T20:15:51Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57983</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57983"/>
		<updated>2020-11-04T20:15:34Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57982</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57982"/>
		<updated>2020-11-04T20:14:56Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=wongjn.php-sniffer&lt;br /&gt;
This may be a good alternative &lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57981</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57981"/>
		<updated>2020-11-04T19:49:17Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
For this to work your instance of phpcs needs to have the moodle coding standards installed. &lt;br /&gt;
&lt;br /&gt;
This link may help&lt;br /&gt;
&lt;br /&gt;
https://askubuntu.com/questions/572956/adding-a-standard-to-php-codesniffer&lt;br /&gt;
&lt;br /&gt;
You can check if it is installed from the command line with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
phpcs -i&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If it is installed moodle will show up in the output, here is a typcial example, note moodle is listed as the last but one item.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
The installed coding standards are PEAR, PHPCS, Zend, PSR2, MySource, Squiz, PSR1, moodle and PHPCompatibility&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://github.com/wongjn/vscode-php-sniffer&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57958</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57958"/>
		<updated>2020-10-23T09:56:04Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== PHP Linting ==&lt;br /&gt;
https://docs.moodle.org/dev/Linting#Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://github.com/wongjn/vscode-php-sniffer&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Javascript_Modules&amp;diff=57909</id>
		<title>Javascript Modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Javascript_Modules&amp;diff=57909"/>
		<updated>2020-10-12T08:47:47Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* ES6 Modules (Moodle v3.8 and above) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.9}}&lt;br /&gt;
&lt;br /&gt;
= Javascript Modules =&lt;br /&gt;
&lt;br /&gt;
== What is a Javascript module and why do I care? ==&lt;br /&gt;
&lt;br /&gt;
A Javascript module is nothing more than a collection of Javascript code that can be used (reliably) from other pieces of Javascript. &lt;br /&gt;
&lt;br /&gt;
== Why should I package my code as a module? ==&lt;br /&gt;
&lt;br /&gt;
By packaging your code as a module you break your code up into smaller reusable pieces. This is good because:&lt;br /&gt;
&lt;br /&gt;
a) Each smaller piece is simpler to understand / debug&lt;br /&gt;
&lt;br /&gt;
b) Each smaller piece is simpler to test&lt;br /&gt;
&lt;br /&gt;
c) You can re-use common code instead of duplicating it&lt;br /&gt;
&lt;br /&gt;
= How do I write a Javascript module in Moodle? =&lt;br /&gt;
&lt;br /&gt;
Since version 2.9, Moodle supports Javascript modules written using the Asynchronous Module Definition ([https://github.com/amdjs/amdjs-api/wiki/AMD AMD]) API. This is a standard API for creating Javascript modules and you will find many useful third party libraries that are already using this format. &lt;br /&gt;
&lt;br /&gt;
To edit or create an AMD module in Moodle you need to do a couple of things. &lt;br /&gt;
&lt;br /&gt;
Since version 3.8, Moodle supports [https://github.com/lukehoban/es6features#readme ECMAScript 2015 features] (aka ES6) in a cross browser compatible way thanks to [https://babeljs.io/ Babel JS]. In order to achieve the compatibility with older browsers Babel will compile the newer ES6 features back into ES5 Javascript. Unfortunately this means that in order for your Javascript changes to show in the browser they must be compiled by running [[Grunt]], even with the cachejs config setting set to false (i.e. &amp;quot;Development mode&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Note that, for Moodle 3.10 and up (see MDLSITE-6130), any new Javascript module &#039;&#039;&#039;must&#039;&#039;&#039; be written on ES6.&lt;br /&gt;
&lt;br /&gt;
== Install NVM and Node ==&lt;br /&gt;
&lt;br /&gt;
The recommended way of installing NodeJS is via the [https://github.com/nvm-sh/nvm Node Version Manager], or NVM. NVM allows you to have several different versions of NodeJS installed at and in-use at any once on your computer. Supported versions of Moodle all use version {{NodeJSExactVersion}} of NodeJS.&lt;br /&gt;
&lt;br /&gt;
https://github.com/nvm-sh/nvm#installing-and-updating&lt;br /&gt;
&lt;br /&gt;
Confirm it is working:&lt;br /&gt;
&lt;br /&gt;
 $ nvm --version&lt;br /&gt;
 0.35.3&lt;br /&gt;
&lt;br /&gt;
After you have installed &#039;&#039;&#039;nvm&#039;&#039;&#039;, you should install the correct version of NodeJS by running the following commands from your Moodle directory:&lt;br /&gt;
&lt;br /&gt;
 nvm install&lt;br /&gt;
 nvm use&lt;br /&gt;
&lt;br /&gt;
If your primary use of NodeJS is for Moodle then we recommend that you set NodeJS version {{NodeJSExactVersion}} as your default version. You can do this by running:&lt;br /&gt;
&lt;br /&gt;
 nvm alias default {{NodeJSExactVersion}}&lt;br /&gt;
&lt;br /&gt;
== Install grunt ==&lt;br /&gt;
&lt;br /&gt;
The AMD modules in Moodle must be processed by some build tools before they will be visible to your web browser. We use &amp;quot;[[grunt]]&amp;quot; as a build tool to wrap our different processes. Grunt is a build tool written in Javascript that runs in the &amp;quot;[http://nodejs.org/ nodejs]&amp;quot; environment.&lt;br /&gt;
&lt;br /&gt;
Once this is done, you can run the the following commands from your Moodle directory:&lt;br /&gt;
&lt;br /&gt;
 npm install&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This may mention vulnerabilities, that&#039;s fine and doesn&#039;t apply.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 npm install -g grunt-cli&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v2.9 to v3.7)  ==&lt;br /&gt;
&lt;br /&gt;
To avoid having to constantly run grunt, make sure you set the following in your config.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Prevent JS caching&lt;br /&gt;
$CFG-&amp;gt;cachejs = false;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Moodle will now run your module from the amd/src module. Don&#039;t forget to switch this off and run &#039;grunt&#039; before deploying the new version!&lt;br /&gt;
&lt;br /&gt;
In this mode - if you get a strange message in your javascript console like &amp;quot;No define call for core/first&amp;quot; it means you have a syntax error in the javascript you are developing. &lt;br /&gt;
Or, &amp;quot;No define call for theme_XXX/loader&amp;quot; as you are probably missing the &#039;src&#039; folder with relevant JS files. which might happen when you turn debugging ON on a theme that was bought, without &#039;src&#039; folder :-(&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v3.8 and above)  ==&lt;br /&gt;
&lt;br /&gt;
All Javascript code is now compiled using Babel which means Moodle will only ever serve minified Javascript to the browser, even in development mode. However in development mode Moodle will also send the browser the corresponding source map files for each of the Javascript modules. The source map files will tell the browser how to map the minified source code back to the unminified original source code so that the original source files will be displayed in the sources section of the browser&#039;s development tools.&lt;br /&gt;
&lt;br /&gt;
While in development mode each of the Javascript modules will appear in the browser&#039;s source tree as separate modules (no more giant first.js file!) and they will also be loaded with individual network requests (this is a compromise we had to make thanks to some browser bugs with source map files).&lt;br /&gt;
&lt;br /&gt;
To enable development mode set the &#039;&#039;&#039;cachejs&#039;&#039;&#039; config value to &#039;&#039;&#039;false&#039;&#039;&#039; in the admin settings or directly in your config.php file:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Prevent JS caching&lt;br /&gt;
$CFG-&amp;gt;cachejs = false;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since all Javascript must now be compiled you must run [[Grunt]] in order for you changes to appear in the browser. However rather than running Grunt manually each time on either the whole project or each file you modified, it is recommended that you just run the &#039;&#039;&#039;grunt watch&#039;&#039;&#039; task at the root of your Moodle directory. The grunt watch task will listen for changes to the Javascript files in the Moodle directory and will automatically lint and compile only the file that is changed after each change is detected. This removes the need to manually run grunt after each change.&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v3.10 and above)  ==&lt;br /&gt;
&lt;br /&gt;
All the above for Moodle 3.8 and up applies, plus (see MDLSITE-6130), any new Javascript module must be written on ES6.&lt;br /&gt;
&lt;br /&gt;
== Running grunt ==&lt;br /&gt;
&lt;br /&gt;
You can run grunt in your plugin&#039;s &#039;amd&#039; directory and it will only operate on your modules. If you&#039;re having problems or just want to check your work it is worth running for the &#039;lint&#039; feature. This can find basic problems. This sub-directory support wont work on Windows unfortunately but there is an alternative: Run grunt from the top directory with the --root=path/to/dir to limit execution to a sub-directory.&lt;br /&gt;
&lt;br /&gt;
See [[Grunt#Running_grunt]] for more details of specific grunt commands which can be used.&lt;br /&gt;
&lt;br /&gt;
If you get the error message&lt;br /&gt;
&lt;br /&gt;
 /usr/bin/env: node: No such file or directory&lt;br /&gt;
&lt;br /&gt;
Then see the thread https://github.com/nodejs/node-v0.x-archive/issues/3911&lt;br /&gt;
&lt;br /&gt;
On Ubuntu 14.04 this fixed it for me:&lt;br /&gt;
&lt;br /&gt;
 sudo ln -fs /usr/bin/nodejs /usr/local/bin/node&lt;br /&gt;
&lt;br /&gt;
Note: Once you have run grunt and built your code, you will then need to purge Moodle caches otherwise the changes made to your minified files may not be picked up by Moodle.&lt;br /&gt;
&lt;br /&gt;
== ES6 Modules (Moodle v3.8 and above) ==&lt;br /&gt;
&lt;br /&gt;
In addition to AMD module syntax Moodle now supports the [https://github.com/lukehoban/es6features#modules ES6 syntax] for writing Javascript modules. All modules (defined using either syntax) are compatible with one another. Behind the scenes the ES6 module syntax is converted into an AMD syntax as part of the Babel compiling process.&lt;br /&gt;
&lt;br /&gt;
Note that, for Moodle 3.10 and up (see MDLSITE-6130), any new Javascript module must be written on ES6.&lt;br /&gt;
&lt;br /&gt;
The call from a PHP file takes the same format&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;myplugin/myfile&#039;,&#039;init&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And a minimal ES6 file will work with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
export const init = () =&amp;gt; {&lt;br /&gt;
    window.console.log(&#039;we have been started&#039;);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export default ===&lt;br /&gt;
There is one slight difference between the ES6 definition for exporting modules and the RequireJS (AMD) definition.&lt;br /&gt;
&lt;br /&gt;
ES6 allows you to export a “default” value which is actually no different to exporting a named value where the name is “default”. Unfortunately, RequireJS allows for unnamed default exports (e.g. you can do &amp;quot;return SomeClass;&amp;quot;) which can be imported by just requiring them in other AMD modules.&lt;br /&gt;
&lt;br /&gt;
That’s a bit confusing, get to the point! Well, it basically means that in Moodle you won’t be able to write an ES6 module that exports both a default and named exports, e.g. &amp;quot;export default function() {...}&amp;quot; and &amp;quot;export const FOO = &#039;bar&#039;&amp;quot; in the same module. The export default will simply override all other exports in that module.&lt;br /&gt;
&lt;br /&gt;
=== Inline Javascript ===&lt;br /&gt;
Another important note is that ES6 support is only for stand alone Javascript files because it relies on the compilation from Babel and Grunt. That means any inline Javascript (either in PHP or in Mustache templates) won&#039;t support the ES6 features. Instead it would be best to keep the inline Javascript as minimal as possible and only use it to load a stand alone Javascript module.&lt;br /&gt;
&lt;br /&gt;
== Minimum (getting started) module for plugins ==&lt;br /&gt;
&lt;br /&gt;
This shows the absolute minimum module you need to get started adding modules to your plugins. It&#039;s actually quite simple...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// Put this file in path/to/plugin/amd/src&lt;br /&gt;
// You can call it anything you like&lt;br /&gt;
&lt;br /&gt;
define([&#039;jquery&#039;], function($) {&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        init: function() {&lt;br /&gt;
&lt;br /&gt;
            // Put whatever you like here. $ is available&lt;br /&gt;
            // to you as normal.&lt;br /&gt;
            $(&amp;quot;.someclass&amp;quot;).change(function() {&lt;br /&gt;
                alert(&amp;quot;It changed!!&amp;quot;);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code passes the jquery module into our function (parameter $). There are a number of other useful modules available in Moodle, some of which you&#039;ll probably need in a practical application. See [[Useful_core_Javascript_modules]]. Simply list them in both the define() first parameter and the function callback. E.g.,&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
    define([&#039;jquery&#039;, &#039;core/str&#039;, &#039;core/ajax&#039;], function($, str, ajax) {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The idea here is that we will run the &#039;init&#039; function from our (PHP) code to set things up. This is called from PHP like this...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;frankenstyle_path/your_js_filename&#039;, &#039;init&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to supply the complete &#039;[[Frankenstyle]]&#039; path. The .js is not needed. &lt;br /&gt;
&lt;br /&gt;
js_call_amd takes a third parameter which is an &#039;&#039;array&#039;&#039; of parameters. These will translate to individual parameters in the &#039;init&#039; function call. For example...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;block_iomad_company_admin/department_select&#039;, &#039;init&#039;, array($first, $last));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
    return {&lt;br /&gt;
        init: function(first, last) {&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A more comprehensive explanation follows...&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Hello World&amp;quot; I am a Javascript Module ==&lt;br /&gt;
Lets now create a simple Javascript module so we can see how to lay things out. &lt;br /&gt;
&lt;br /&gt;
Each Javascript module is contained in a single source file in the &amp;lt;componentdir&amp;gt;/amd/src folder. The final name of the module is taken from the file name and the component name. E.g. block_overview/amd/src/helloworld.js would be a module named &amp;quot;block_overview/helloworld&amp;quot;. the name of the module is important when you want to call it from somewhere else in the code. &lt;br /&gt;
&lt;br /&gt;
After running grunt - the minified Javascript files are stored in the &amp;lt;componentdir&amp;gt;/amd/build folder. The javascript files are renamed to show that they are minified (helloworld.js becomes helloworld.min.js). &lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to add the built files (the ones in amd/build) to your git commits, or in production no-one will see your changes. &lt;br /&gt;
&lt;br /&gt;
Lets create a simple module now:&lt;br /&gt;
&lt;br /&gt;
blocks/overview/amd/src/helloworld.js&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// Standard license block omitted.&lt;br /&gt;
/*&lt;br /&gt;
 * @package    block_overview&lt;br /&gt;
 * @copyright  2015 Someone cool&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * @module block_overview/helloworld&lt;br /&gt;
  */&lt;br /&gt;
define([&#039;jquery&#039;], function($) {&lt;br /&gt;
&lt;br /&gt;
     /** &lt;br /&gt;
      * Give me blue.&lt;br /&gt;
      * @access private&lt;br /&gt;
      * @return {string}&lt;br /&gt;
      */&lt;br /&gt;
     var makeItBlue = function() {&lt;br /&gt;
          // We can use our jquery dependency here.&lt;br /&gt;
          return $(&#039;.blue&#039;).show();&lt;br /&gt;
     };&lt;br /&gt;
      &lt;br /&gt;
    /**&lt;br /&gt;
     * @constructor&lt;br /&gt;
     * @alias module:block_overview/helloworld&lt;br /&gt;
     */&lt;br /&gt;
    var greeting = function() {&lt;br /&gt;
        /** @access private */&lt;br /&gt;
        var privateThoughts = &#039;I like the colour blue&#039;;&lt;br /&gt;
        &lt;br /&gt;
        /** @access public */&lt;br /&gt;
        this.publicThoughts = &#039;I like the colour orange&#039;;&lt;br /&gt;
&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * A formal greeting.&lt;br /&gt;
     * @access public&lt;br /&gt;
     * @return {string}&lt;br /&gt;
     */&lt;br /&gt;
    greeting.prototype.formal = function() {&lt;br /&gt;
        return &#039;How do you do?&#039;;&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * An informal greeting.&lt;br /&gt;
     * @access public&lt;br /&gt;
     * @return {string}&lt;br /&gt;
     */&lt;br /&gt;
    greeting.prototype.informal = function() {&lt;br /&gt;
        return &#039;Wassup!&#039;;&lt;br /&gt;
    };&lt;br /&gt;
    return greeting;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The most interesting line above is:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define([&#039;jquery&#039;], function($) {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All AMD modules must call &amp;quot;define()&amp;quot; as the first and only global scoped piece of code. This ensures the javascript code contains no global variables and will not conflict with any other loaded module. The name of the module does not need to be specified because it is determined from the filename and component (but it can be listed in a comment for JSDoc as shown here). &lt;br /&gt;
&lt;br /&gt;
The first argument to &amp;quot;define&amp;quot; is the list of dependencies for the module. This argument must be passed as an array, even if there is only one. In this example &amp;quot;jquery&amp;quot; is a dependency. &amp;quot;jquery&amp;quot; is shipped as a core module is available to all AMD modules. &lt;br /&gt;
&lt;br /&gt;
The second argument to &amp;quot;define&amp;quot; is the function that defines the module. This function will receive as arguments, each of the requested dependencies in the same order they were requested. In this example we receive JQuery as an argument and we name the variable &amp;quot;$&amp;quot; (it&#039;s a JQuery thing). We can then access JQuery normally through the $ variable which is in scope for any code in our module. &lt;br /&gt;
&lt;br /&gt;
The rest of the code in this example is a standard way to define a Javascript module with public/private variables and methods. There are many ways to do this, this is only one.&lt;br /&gt;
&lt;br /&gt;
It is important that we are returning &#039;greeting&#039;. If there is no return then your module will be declared as undefined.&lt;br /&gt;
&lt;br /&gt;
== Loading modules dynamically ==&lt;br /&gt;
What do you do if you don&#039;t know in advance which modules will be required? Stuffing all possible required modules in the define call is one solution, but it&#039;s ugly and it only works for code that is in an AMD module (what about inline code in the page?). AMD lets you load a dependency any time you like. &lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Load a new dependency.&lt;br /&gt;
require([&#039;mod_wiki/timer&#039;], function(timer) {&lt;br /&gt;
   // timer is available to do my bidding.&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Including an external javascript/jquery library ==&lt;br /&gt;
If you want to include a javascript / jquery library downloaded from the internet you can do so as follows:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning: if the library you download, supports AMD but is already &amp;quot;named&amp;quot; you will not be able to include it directly&#039;&#039;&#039;&lt;br /&gt;
e.g. &lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
        define(&amp;quot;typeahead.js&amp;quot;, *[ &amp;quot;jquery&amp;quot; ], function(a0) {&lt;br /&gt;
            return factory(a0);&lt;br /&gt;
        });&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work, as moodle injects it&#039;s own define name when loading the library.&lt;br /&gt;
&lt;br /&gt;
If the library is in AMD format and has a define:&lt;br /&gt;
e.g. i want to include the jquery final countdown timer on my page ( hilios.github.io/jQuery.countdown/ )&lt;br /&gt;
* download the module in both normal and minified versions&lt;br /&gt;
* place the modules in your moodle install e.g. your custom theme dir, or plugin dir&lt;br /&gt;
* /theme/mytheme/amd/src/jquery.countdown.js&lt;br /&gt;
&lt;br /&gt;
you can now include the module and initialise it (there are multiple ways to do this)&lt;br /&gt;
php:&lt;br /&gt;
&lt;br /&gt;
1. Create your own AMD module and initialise it:&lt;br /&gt;
&lt;br /&gt;
In your PHP file:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;requires-&amp;gt;js_call_amd(&#039;theme_mytheme/countdowntimer&#039;, &#039;initialise&#039;, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Javascript module:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// /theme/mytheme/amd/src/countdowntimer.js&lt;br /&gt;
define([&#039;jquery&#039;, &#039;theme_mytheme/jquery.countdown&#039;], function($, c) {&lt;br /&gt;
    return {&lt;br /&gt;
        initialise: function ($params) {&lt;br /&gt;
           $(&#039;#clock&#039;).countdown(&#039;2020/10/10&#039;, function(event) {&lt;br /&gt;
             $(this).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
           });&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Put the javascript into a mustache template:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// /theme/mytheme/templates/countdowntimer.mustache&lt;br /&gt;
&amp;lt;span id=&amp;quot;clock&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
{{#js}}&lt;br /&gt;
require([&#039;jquery&#039;, &#039;theme_mytheme/jquery.countdown&#039;], function($) {&lt;br /&gt;
           $(&#039;#clock&#039;).countdown(&#039;2020/10/10&#039;, function(event) {&lt;br /&gt;
             $(this).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
           });&lt;br /&gt;
});&lt;br /&gt;
{{/js}}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Call the javascript directly from php (although who would want to put javascript into php? ergh):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_amd_inline(&#039;&lt;br /&gt;
require([&#039;theme_mytheme/jquery.countdown&#039;], function(min) {&lt;br /&gt;
           $(&#039;#clock&#039;).countdown(&#039;2020/10/10&#039;, function(event) {&lt;br /&gt;
             $(this).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
           });&lt;br /&gt;
});&lt;br /&gt;
&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Note: It could be useful when you wish to pass a big chunk of data from php directly into a JS variable, to workaround MDL-62468 .&amp;lt;br&amp;gt;&lt;br /&gt;
Example: https://github.com/moodle/moodle/blob/master/media/player/videojs/classes/plugin.php#L386&lt;br /&gt;
&lt;br /&gt;
===More examples of including 3rd-party JS modules===&lt;br /&gt;
* [https://moodle.org/mod/forum/discuss.php?d=327579#p1317252 Adding custom js via AMD (highcharts) to essential theme]&lt;br /&gt;
&lt;br /&gt;
== Embedding AMD code in a page ==&lt;br /&gt;
So you have created lots of cool Javascript modules. Great. How do we actually call them? Any javascript code that calls an AMD module must execute AFTER the requirejs module loader has finished loading. We have provided a function &amp;quot;js_call_amd&amp;quot; that will call a single function from an AMD module with parameters.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_call_amd($modulename, $functionname, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
that will &amp;quot;do the right thing&amp;quot; with your block of AMD code and execute it at the end of the page, after our AMD module loader has loaded. &lt;br /&gt;
Notes:&lt;br /&gt;
* the $modulename is the &#039;componentname/modulename&#039; discussed above&lt;br /&gt;
* the $functionname is the name of a public function exposed by the amd module. &lt;br /&gt;
* the $params is an array of params passed as arguments to the function. These should be simple types that can be handled by json_encode (no recursive arrays, or complex classes please). &lt;br /&gt;
* if the size of the params array is too large (&amp;gt; 1Kb), this will produce a developer warning. Do not attempt to pass large amounts of data through this function, it will pollute the page size. A preferred approach is to pass css selectors for DOM elements that contain data-attributes for any required data, or fetch data via ajax in the background.&lt;br /&gt;
&lt;br /&gt;
AMD / JS code can also be embedded on a page via mustache templates&lt;br /&gt;
see here: https://docs.moodle.org/dev/Templates#What_if_a_template_contains_javascript.3F&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== npm-shrinkwrap.json sha1 / sha512 changes ===&lt;br /&gt;
&lt;br /&gt;
If grunt changes all the hashes in npm-shrinkwrap.json then try this:&lt;br /&gt;
&lt;br /&gt;
 rm -rf node_modules &amp;amp;&amp;amp; npm i&lt;br /&gt;
&lt;br /&gt;
== But I have a mega JS file I don&#039;t want loaded on every page? ==&lt;br /&gt;
Loading all JS files at once and stuffing them in the browser cache is the right choice for MOST js files, there are probably some exceptions. For these files, you can rename the javascript file to end with the suffix &amp;quot;-lazy.js&amp;quot; which indicates that the module will not be loaded by default, it will be requested the first time it is used. There is no difference in usage for lazy loaded modules, the require() call looks exactly the same, it&#039;s just that the module name will also have the &amp;quot;-lazy&amp;quot; suffix.&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
* [https://assets.moodlemoot.org/sites/15/20171004085436/JavaScript-AMD-with-RequireJS-presented-by-Daniel-Roperto-Catalyst.pdf JavaScript AMD with RequireJS] presented by Daniel Roperto, Catalyst. (MoodleMOOT AU 2017)&lt;br /&gt;
* [[Useful_core_Javascript_modules]]&lt;br /&gt;
*[[Guide_to_adding_third_party_jQuery_for_AMD]] by Patrick Thibaudeau&lt;br /&gt;
*[https://moodle.org/mod/forum/discuss.php?d=378112#p1524459 How to get variables from PHP into javascript AMD modules in M3.5] Justin Hunt, on Moodle forums.&lt;br /&gt;
*MDL-67327 JavaScript issues when not following the official documentation, since Moodle 3.8&lt;br /&gt;
&lt;br /&gt;
[[Category:AJAX]]&lt;br /&gt;
[[Category:Javascript]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Javascript_Modules&amp;diff=57908</id>
		<title>Javascript Modules</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Javascript_Modules&amp;diff=57908"/>
		<updated>2020-10-12T08:47:18Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* ES6 Modules (Moodle v3.8 and above) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.9}}&lt;br /&gt;
&lt;br /&gt;
= Javascript Modules =&lt;br /&gt;
&lt;br /&gt;
== What is a Javascript module and why do I care? ==&lt;br /&gt;
&lt;br /&gt;
A Javascript module is nothing more than a collection of Javascript code that can be used (reliably) from other pieces of Javascript. &lt;br /&gt;
&lt;br /&gt;
== Why should I package my code as a module? ==&lt;br /&gt;
&lt;br /&gt;
By packaging your code as a module you break your code up into smaller reusable pieces. This is good because:&lt;br /&gt;
&lt;br /&gt;
a) Each smaller piece is simpler to understand / debug&lt;br /&gt;
&lt;br /&gt;
b) Each smaller piece is simpler to test&lt;br /&gt;
&lt;br /&gt;
c) You can re-use common code instead of duplicating it&lt;br /&gt;
&lt;br /&gt;
= How do I write a Javascript module in Moodle? =&lt;br /&gt;
&lt;br /&gt;
Since version 2.9, Moodle supports Javascript modules written using the Asynchronous Module Definition ([https://github.com/amdjs/amdjs-api/wiki/AMD AMD]) API. This is a standard API for creating Javascript modules and you will find many useful third party libraries that are already using this format. &lt;br /&gt;
&lt;br /&gt;
To edit or create an AMD module in Moodle you need to do a couple of things. &lt;br /&gt;
&lt;br /&gt;
Since version 3.8, Moodle supports [https://github.com/lukehoban/es6features#readme ECMAScript 2015 features] (aka ES6) in a cross browser compatible way thanks to [https://babeljs.io/ Babel JS]. In order to achieve the compatibility with older browsers Babel will compile the newer ES6 features back into ES5 Javascript. Unfortunately this means that in order for your Javascript changes to show in the browser they must be compiled by running [[Grunt]], even with the cachejs config setting set to false (i.e. &amp;quot;Development mode&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Note that, for Moodle 3.10 and up (see MDLSITE-6130), any new Javascript module &#039;&#039;&#039;must&#039;&#039;&#039; be written on ES6.&lt;br /&gt;
&lt;br /&gt;
== Install NVM and Node ==&lt;br /&gt;
&lt;br /&gt;
The recommended way of installing NodeJS is via the [https://github.com/nvm-sh/nvm Node Version Manager], or NVM. NVM allows you to have several different versions of NodeJS installed at and in-use at any once on your computer. Supported versions of Moodle all use version {{NodeJSExactVersion}} of NodeJS.&lt;br /&gt;
&lt;br /&gt;
https://github.com/nvm-sh/nvm#installing-and-updating&lt;br /&gt;
&lt;br /&gt;
Confirm it is working:&lt;br /&gt;
&lt;br /&gt;
 $ nvm --version&lt;br /&gt;
 0.35.3&lt;br /&gt;
&lt;br /&gt;
After you have installed &#039;&#039;&#039;nvm&#039;&#039;&#039;, you should install the correct version of NodeJS by running the following commands from your Moodle directory:&lt;br /&gt;
&lt;br /&gt;
 nvm install&lt;br /&gt;
 nvm use&lt;br /&gt;
&lt;br /&gt;
If your primary use of NodeJS is for Moodle then we recommend that you set NodeJS version {{NodeJSExactVersion}} as your default version. You can do this by running:&lt;br /&gt;
&lt;br /&gt;
 nvm alias default {{NodeJSExactVersion}}&lt;br /&gt;
&lt;br /&gt;
== Install grunt ==&lt;br /&gt;
&lt;br /&gt;
The AMD modules in Moodle must be processed by some build tools before they will be visible to your web browser. We use &amp;quot;[[grunt]]&amp;quot; as a build tool to wrap our different processes. Grunt is a build tool written in Javascript that runs in the &amp;quot;[http://nodejs.org/ nodejs]&amp;quot; environment.&lt;br /&gt;
&lt;br /&gt;
Once this is done, you can run the the following commands from your Moodle directory:&lt;br /&gt;
&lt;br /&gt;
 npm install&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This may mention vulnerabilities, that&#039;s fine and doesn&#039;t apply.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 npm install -g grunt-cli&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v2.9 to v3.7)  ==&lt;br /&gt;
&lt;br /&gt;
To avoid having to constantly run grunt, make sure you set the following in your config.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Prevent JS caching&lt;br /&gt;
$CFG-&amp;gt;cachejs = false;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Moodle will now run your module from the amd/src module. Don&#039;t forget to switch this off and run &#039;grunt&#039; before deploying the new version!&lt;br /&gt;
&lt;br /&gt;
In this mode - if you get a strange message in your javascript console like &amp;quot;No define call for core/first&amp;quot; it means you have a syntax error in the javascript you are developing. &lt;br /&gt;
Or, &amp;quot;No define call for theme_XXX/loader&amp;quot; as you are probably missing the &#039;src&#039; folder with relevant JS files. which might happen when you turn debugging ON on a theme that was bought, without &#039;src&#039; folder :-(&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v3.8 and above)  ==&lt;br /&gt;
&lt;br /&gt;
All Javascript code is now compiled using Babel which means Moodle will only ever serve minified Javascript to the browser, even in development mode. However in development mode Moodle will also send the browser the corresponding source map files for each of the Javascript modules. The source map files will tell the browser how to map the minified source code back to the unminified original source code so that the original source files will be displayed in the sources section of the browser&#039;s development tools.&lt;br /&gt;
&lt;br /&gt;
While in development mode each of the Javascript modules will appear in the browser&#039;s source tree as separate modules (no more giant first.js file!) and they will also be loaded with individual network requests (this is a compromise we had to make thanks to some browser bugs with source map files).&lt;br /&gt;
&lt;br /&gt;
To enable development mode set the &#039;&#039;&#039;cachejs&#039;&#039;&#039; config value to &#039;&#039;&#039;false&#039;&#039;&#039; in the admin settings or directly in your config.php file:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Prevent JS caching&lt;br /&gt;
$CFG-&amp;gt;cachejs = false;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since all Javascript must now be compiled you must run [[Grunt]] in order for you changes to appear in the browser. However rather than running Grunt manually each time on either the whole project or each file you modified, it is recommended that you just run the &#039;&#039;&#039;grunt watch&#039;&#039;&#039; task at the root of your Moodle directory. The grunt watch task will listen for changes to the Javascript files in the Moodle directory and will automatically lint and compile only the file that is changed after each change is detected. This removes the need to manually run grunt after each change.&lt;br /&gt;
&lt;br /&gt;
== Development mode (Moodle v3.10 and above)  ==&lt;br /&gt;
&lt;br /&gt;
All the above for Moodle 3.8 and up applies, plus (see MDLSITE-6130), any new Javascript module must be written on ES6.&lt;br /&gt;
&lt;br /&gt;
== Running grunt ==&lt;br /&gt;
&lt;br /&gt;
You can run grunt in your plugin&#039;s &#039;amd&#039; directory and it will only operate on your modules. If you&#039;re having problems or just want to check your work it is worth running for the &#039;lint&#039; feature. This can find basic problems. This sub-directory support wont work on Windows unfortunately but there is an alternative: Run grunt from the top directory with the --root=path/to/dir to limit execution to a sub-directory.&lt;br /&gt;
&lt;br /&gt;
See [[Grunt#Running_grunt]] for more details of specific grunt commands which can be used.&lt;br /&gt;
&lt;br /&gt;
If you get the error message&lt;br /&gt;
&lt;br /&gt;
 /usr/bin/env: node: No such file or directory&lt;br /&gt;
&lt;br /&gt;
Then see the thread https://github.com/nodejs/node-v0.x-archive/issues/3911&lt;br /&gt;
&lt;br /&gt;
On Ubuntu 14.04 this fixed it for me:&lt;br /&gt;
&lt;br /&gt;
 sudo ln -fs /usr/bin/nodejs /usr/local/bin/node&lt;br /&gt;
&lt;br /&gt;
Note: Once you have run grunt and built your code, you will then need to purge Moodle caches otherwise the changes made to your minified files may not be picked up by Moodle.&lt;br /&gt;
&lt;br /&gt;
== ES6 Modules (Moodle v3.8 and above) ==&lt;br /&gt;
&lt;br /&gt;
In addition to AMD module syntax Moodle now supports the [https://github.com/lukehoban/es6features#modules ES6 syntax] for writing Javascript modules. All modules (defined using either syntax) are compatible with one another. Behind the scenes the ES6 module syntax is converted into an AMD syntax as part of the Babel compiling process.&lt;br /&gt;
&lt;br /&gt;
Note that, for Moodle 3.10 and up (see MDLSITE-6130), any new Javascript module must be written on ES6.&lt;br /&gt;
&lt;br /&gt;
The call from a PHP file takes the same format&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;myplugin/myfile&#039;,&#039;myfunction&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And a minimal ES6 file will work with &lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
export const init = () =&amp;gt; {&lt;br /&gt;
    window.console.log(&#039;we have been started&#039;);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Export default ===&lt;br /&gt;
There is one slight difference between the ES6 definition for exporting modules and the RequireJS (AMD) definition.&lt;br /&gt;
&lt;br /&gt;
ES6 allows you to export a “default” value which is actually no different to exporting a named value where the name is “default”. Unfortunately, RequireJS allows for unnamed default exports (e.g. you can do &amp;quot;return SomeClass;&amp;quot;) which can be imported by just requiring them in other AMD modules.&lt;br /&gt;
&lt;br /&gt;
That’s a bit confusing, get to the point! Well, it basically means that in Moodle you won’t be able to write an ES6 module that exports both a default and named exports, e.g. &amp;quot;export default function() {...}&amp;quot; and &amp;quot;export const FOO = &#039;bar&#039;&amp;quot; in the same module. The export default will simply override all other exports in that module.&lt;br /&gt;
&lt;br /&gt;
=== Inline Javascript ===&lt;br /&gt;
Another important note is that ES6 support is only for stand alone Javascript files because it relies on the compilation from Babel and Grunt. That means any inline Javascript (either in PHP or in Mustache templates) won&#039;t support the ES6 features. Instead it would be best to keep the inline Javascript as minimal as possible and only use it to load a stand alone Javascript module.&lt;br /&gt;
&lt;br /&gt;
== Minimum (getting started) module for plugins ==&lt;br /&gt;
&lt;br /&gt;
This shows the absolute minimum module you need to get started adding modules to your plugins. It&#039;s actually quite simple...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// Put this file in path/to/plugin/amd/src&lt;br /&gt;
// You can call it anything you like&lt;br /&gt;
&lt;br /&gt;
define([&#039;jquery&#039;], function($) {&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        init: function() {&lt;br /&gt;
&lt;br /&gt;
            // Put whatever you like here. $ is available&lt;br /&gt;
            // to you as normal.&lt;br /&gt;
            $(&amp;quot;.someclass&amp;quot;).change(function() {&lt;br /&gt;
                alert(&amp;quot;It changed!!&amp;quot;);&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code passes the jquery module into our function (parameter $). There are a number of other useful modules available in Moodle, some of which you&#039;ll probably need in a practical application. See [[Useful_core_Javascript_modules]]. Simply list them in both the define() first parameter and the function callback. E.g.,&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
    define([&#039;jquery&#039;, &#039;core/str&#039;, &#039;core/ajax&#039;], function($, str, ajax) {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The idea here is that we will run the &#039;init&#039; function from our (PHP) code to set things up. This is called from PHP like this...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;frankenstyle_path/your_js_filename&#039;, &#039;init&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to supply the complete &#039;[[Frankenstyle]]&#039; path. The .js is not needed. &lt;br /&gt;
&lt;br /&gt;
js_call_amd takes a third parameter which is an &#039;&#039;array&#039;&#039; of parameters. These will translate to individual parameters in the &#039;init&#039; function call. For example...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $PAGE-&amp;gt;requires-&amp;gt;js_call_amd(&#039;block_iomad_company_admin/department_select&#039;, &#039;init&#039;, array($first, $last));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
    return {&lt;br /&gt;
        init: function(first, last) {&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A more comprehensive explanation follows...&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Hello World&amp;quot; I am a Javascript Module ==&lt;br /&gt;
Lets now create a simple Javascript module so we can see how to lay things out. &lt;br /&gt;
&lt;br /&gt;
Each Javascript module is contained in a single source file in the &amp;lt;componentdir&amp;gt;/amd/src folder. The final name of the module is taken from the file name and the component name. E.g. block_overview/amd/src/helloworld.js would be a module named &amp;quot;block_overview/helloworld&amp;quot;. the name of the module is important when you want to call it from somewhere else in the code. &lt;br /&gt;
&lt;br /&gt;
After running grunt - the minified Javascript files are stored in the &amp;lt;componentdir&amp;gt;/amd/build folder. The javascript files are renamed to show that they are minified (helloworld.js becomes helloworld.min.js). &lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to add the built files (the ones in amd/build) to your git commits, or in production no-one will see your changes. &lt;br /&gt;
&lt;br /&gt;
Lets create a simple module now:&lt;br /&gt;
&lt;br /&gt;
blocks/overview/amd/src/helloworld.js&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// Standard license block omitted.&lt;br /&gt;
/*&lt;br /&gt;
 * @package    block_overview&lt;br /&gt;
 * @copyright  2015 Someone cool&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * @module block_overview/helloworld&lt;br /&gt;
  */&lt;br /&gt;
define([&#039;jquery&#039;], function($) {&lt;br /&gt;
&lt;br /&gt;
     /** &lt;br /&gt;
      * Give me blue.&lt;br /&gt;
      * @access private&lt;br /&gt;
      * @return {string}&lt;br /&gt;
      */&lt;br /&gt;
     var makeItBlue = function() {&lt;br /&gt;
          // We can use our jquery dependency here.&lt;br /&gt;
          return $(&#039;.blue&#039;).show();&lt;br /&gt;
     };&lt;br /&gt;
      &lt;br /&gt;
    /**&lt;br /&gt;
     * @constructor&lt;br /&gt;
     * @alias module:block_overview/helloworld&lt;br /&gt;
     */&lt;br /&gt;
    var greeting = function() {&lt;br /&gt;
        /** @access private */&lt;br /&gt;
        var privateThoughts = &#039;I like the colour blue&#039;;&lt;br /&gt;
        &lt;br /&gt;
        /** @access public */&lt;br /&gt;
        this.publicThoughts = &#039;I like the colour orange&#039;;&lt;br /&gt;
&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * A formal greeting.&lt;br /&gt;
     * @access public&lt;br /&gt;
     * @return {string}&lt;br /&gt;
     */&lt;br /&gt;
    greeting.prototype.formal = function() {&lt;br /&gt;
        return &#039;How do you do?&#039;;&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * An informal greeting.&lt;br /&gt;
     * @access public&lt;br /&gt;
     * @return {string}&lt;br /&gt;
     */&lt;br /&gt;
    greeting.prototype.informal = function() {&lt;br /&gt;
        return &#039;Wassup!&#039;;&lt;br /&gt;
    };&lt;br /&gt;
    return greeting;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The most interesting line above is:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define([&#039;jquery&#039;], function($) {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All AMD modules must call &amp;quot;define()&amp;quot; as the first and only global scoped piece of code. This ensures the javascript code contains no global variables and will not conflict with any other loaded module. The name of the module does not need to be specified because it is determined from the filename and component (but it can be listed in a comment for JSDoc as shown here). &lt;br /&gt;
&lt;br /&gt;
The first argument to &amp;quot;define&amp;quot; is the list of dependencies for the module. This argument must be passed as an array, even if there is only one. In this example &amp;quot;jquery&amp;quot; is a dependency. &amp;quot;jquery&amp;quot; is shipped as a core module is available to all AMD modules. &lt;br /&gt;
&lt;br /&gt;
The second argument to &amp;quot;define&amp;quot; is the function that defines the module. This function will receive as arguments, each of the requested dependencies in the same order they were requested. In this example we receive JQuery as an argument and we name the variable &amp;quot;$&amp;quot; (it&#039;s a JQuery thing). We can then access JQuery normally through the $ variable which is in scope for any code in our module. &lt;br /&gt;
&lt;br /&gt;
The rest of the code in this example is a standard way to define a Javascript module with public/private variables and methods. There are many ways to do this, this is only one.&lt;br /&gt;
&lt;br /&gt;
It is important that we are returning &#039;greeting&#039;. If there is no return then your module will be declared as undefined.&lt;br /&gt;
&lt;br /&gt;
== Loading modules dynamically ==&lt;br /&gt;
What do you do if you don&#039;t know in advance which modules will be required? Stuffing all possible required modules in the define call is one solution, but it&#039;s ugly and it only works for code that is in an AMD module (what about inline code in the page?). AMD lets you load a dependency any time you like. &lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Load a new dependency.&lt;br /&gt;
require([&#039;mod_wiki/timer&#039;], function(timer) {&lt;br /&gt;
   // timer is available to do my bidding.&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Including an external javascript/jquery library ==&lt;br /&gt;
If you want to include a javascript / jquery library downloaded from the internet you can do so as follows:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning: if the library you download, supports AMD but is already &amp;quot;named&amp;quot; you will not be able to include it directly&#039;&#039;&#039;&lt;br /&gt;
e.g. &lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
        define(&amp;quot;typeahead.js&amp;quot;, *[ &amp;quot;jquery&amp;quot; ], function(a0) {&lt;br /&gt;
            return factory(a0);&lt;br /&gt;
        });&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work, as moodle injects it&#039;s own define name when loading the library.&lt;br /&gt;
&lt;br /&gt;
If the library is in AMD format and has a define:&lt;br /&gt;
e.g. i want to include the jquery final countdown timer on my page ( hilios.github.io/jQuery.countdown/ )&lt;br /&gt;
* download the module in both normal and minified versions&lt;br /&gt;
* place the modules in your moodle install e.g. your custom theme dir, or plugin dir&lt;br /&gt;
* /theme/mytheme/amd/src/jquery.countdown.js&lt;br /&gt;
&lt;br /&gt;
you can now include the module and initialise it (there are multiple ways to do this)&lt;br /&gt;
php:&lt;br /&gt;
&lt;br /&gt;
1. Create your own AMD module and initialise it:&lt;br /&gt;
&lt;br /&gt;
In your PHP file:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;requires-&amp;gt;js_call_amd(&#039;theme_mytheme/countdowntimer&#039;, &#039;initialise&#039;, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Javascript module:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// /theme/mytheme/amd/src/countdowntimer.js&lt;br /&gt;
define([&#039;jquery&#039;, &#039;theme_mytheme/jquery.countdown&#039;], function($, c) {&lt;br /&gt;
    return {&lt;br /&gt;
        initialise: function ($params) {&lt;br /&gt;
           $(&#039;#clock&#039;).countdown(&#039;2020/10/10&#039;, function(event) {&lt;br /&gt;
             $(this).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
           });&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Put the javascript into a mustache template:&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
// /theme/mytheme/templates/countdowntimer.mustache&lt;br /&gt;
&amp;lt;span id=&amp;quot;clock&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
{{#js}}&lt;br /&gt;
require([&#039;jquery&#039;, &#039;theme_mytheme/jquery.countdown&#039;], function($) {&lt;br /&gt;
           $(&#039;#clock&#039;).countdown(&#039;2020/10/10&#039;, function(event) {&lt;br /&gt;
             $(this).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
           });&lt;br /&gt;
});&lt;br /&gt;
{{/js}}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Call the javascript directly from php (although who would want to put javascript into php? ergh):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_amd_inline(&#039;&lt;br /&gt;
require([&#039;theme_mytheme/jquery.countdown&#039;], function(min) {&lt;br /&gt;
           $(&#039;#clock&#039;).countdown(&#039;2020/10/10&#039;, function(event) {&lt;br /&gt;
             $(this).html(event.strftime(&#039;%D days %H:%M:%S&#039;));&lt;br /&gt;
           });&lt;br /&gt;
});&lt;br /&gt;
&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Note: It could be useful when you wish to pass a big chunk of data from php directly into a JS variable, to workaround MDL-62468 .&amp;lt;br&amp;gt;&lt;br /&gt;
Example: https://github.com/moodle/moodle/blob/master/media/player/videojs/classes/plugin.php#L386&lt;br /&gt;
&lt;br /&gt;
===More examples of including 3rd-party JS modules===&lt;br /&gt;
* [https://moodle.org/mod/forum/discuss.php?d=327579#p1317252 Adding custom js via AMD (highcharts) to essential theme]&lt;br /&gt;
&lt;br /&gt;
== Embedding AMD code in a page ==&lt;br /&gt;
So you have created lots of cool Javascript modules. Great. How do we actually call them? Any javascript code that calls an AMD module must execute AFTER the requirejs module loader has finished loading. We have provided a function &amp;quot;js_call_amd&amp;quot; that will call a single function from an AMD module with parameters.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;js_call_amd($modulename, $functionname, $params);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
that will &amp;quot;do the right thing&amp;quot; with your block of AMD code and execute it at the end of the page, after our AMD module loader has loaded. &lt;br /&gt;
Notes:&lt;br /&gt;
* the $modulename is the &#039;componentname/modulename&#039; discussed above&lt;br /&gt;
* the $functionname is the name of a public function exposed by the amd module. &lt;br /&gt;
* the $params is an array of params passed as arguments to the function. These should be simple types that can be handled by json_encode (no recursive arrays, or complex classes please). &lt;br /&gt;
* if the size of the params array is too large (&amp;gt; 1Kb), this will produce a developer warning. Do not attempt to pass large amounts of data through this function, it will pollute the page size. A preferred approach is to pass css selectors for DOM elements that contain data-attributes for any required data, or fetch data via ajax in the background.&lt;br /&gt;
&lt;br /&gt;
AMD / JS code can also be embedded on a page via mustache templates&lt;br /&gt;
see here: https://docs.moodle.org/dev/Templates#What_if_a_template_contains_javascript.3F&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== npm-shrinkwrap.json sha1 / sha512 changes ===&lt;br /&gt;
&lt;br /&gt;
If grunt changes all the hashes in npm-shrinkwrap.json then try this:&lt;br /&gt;
&lt;br /&gt;
 rm -rf node_modules &amp;amp;&amp;amp; npm i&lt;br /&gt;
&lt;br /&gt;
== But I have a mega JS file I don&#039;t want loaded on every page? ==&lt;br /&gt;
Loading all JS files at once and stuffing them in the browser cache is the right choice for MOST js files, there are probably some exceptions. For these files, you can rename the javascript file to end with the suffix &amp;quot;-lazy.js&amp;quot; which indicates that the module will not be loaded by default, it will be requested the first time it is used. There is no difference in usage for lazy loaded modules, the require() call looks exactly the same, it&#039;s just that the module name will also have the &amp;quot;-lazy&amp;quot; suffix.&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
* [https://assets.moodlemoot.org/sites/15/20171004085436/JavaScript-AMD-with-RequireJS-presented-by-Daniel-Roperto-Catalyst.pdf JavaScript AMD with RequireJS] presented by Daniel Roperto, Catalyst. (MoodleMOOT AU 2017)&lt;br /&gt;
* [[Useful_core_Javascript_modules]]&lt;br /&gt;
*[[Guide_to_adding_third_party_jQuery_for_AMD]] by Patrick Thibaudeau&lt;br /&gt;
*[https://moodle.org/mod/forum/discuss.php?d=378112#p1524459 How to get variables from PHP into javascript AMD modules in M3.5] Justin Hunt, on Moodle forums.&lt;br /&gt;
*MDL-67327 JavaScript issues when not following the official documentation, since Moodle 3.8&lt;br /&gt;
&lt;br /&gt;
[[Category:AJAX]]&lt;br /&gt;
[[Category:Javascript]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=57894</id>
		<title>Question types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Question_types&amp;diff=57894"/>
		<updated>2020-10-06T20:50:10Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Question type plug in template */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Question_engine_2}}&lt;br /&gt;
=Question type plug in development=&lt;br /&gt;
This page explains how to write a question type that works with the new Moodle [[Question Engine 2|question engine]], the question engine introduced with Moodle 2.1 .&lt;br /&gt;
&lt;br /&gt;
For instructions on making a question type for versions of Moodle prior to Moodle 2.1, see [[Question_type_plugin_how_to]].&lt;br /&gt;
&lt;br /&gt;
Previous section: [[Developing a Question Behaviour|Developing a Question Behaviour]]&lt;br /&gt;
&lt;br /&gt;
==Existing question type plug ins are helpful guides==&lt;br /&gt;
&lt;br /&gt;
To learn to write question types, you are highly encouraged to read the code of some of the existing question types included in the Moodle code base, also there are many more examples of question types in the [https://github.com/moodleou/ Open University github repository] and even more examples of question types can be found in [https://moodle.org/plugins/browse.php?list=category&amp;amp;id=29 the question type category of the Moodle plugins database].&lt;br /&gt;
&lt;br /&gt;
===Existing question types and some of their features===&lt;br /&gt;
&lt;br /&gt;
Below is a list of question types with their features, it is a good idea to examine the code of these question types especially ones that have features you may need for your new question type.&lt;br /&gt;
&lt;br /&gt;
If your question type will be GPLed then of course you can reuse the code in these question types either by cut and paste or by inheriting code from these question types.&lt;br /&gt;
&lt;br /&gt;
* Questions included in Moodle&lt;br /&gt;
** true false, short answer&lt;br /&gt;
*** simplest question types&lt;br /&gt;
** Essay question type (essay)&lt;br /&gt;
*** manually not automatically graded.&lt;br /&gt;
** Calculated question &lt;br /&gt;
*** Uses a multipage question editing form&lt;br /&gt;
** Multiple choice (multichoice)&lt;br /&gt;
*** there is actually no reason why you should only have a single &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class for your question type. You may decide, depending on the question options, to use different definition classes where question options cause questions to behave in different ways. The multiple-choice question type does this, using different definition and renderer classes for single-response and multiple-response questions (but with common subclasses). This is possible because your question type can override the &amp;lt;tt&amp;gt;question_type::make_question_instance&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;question_definition::get_renderer&amp;lt;/tt&amp;gt; methods.&lt;br /&gt;
* Contrib questions&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddwtos Drag and drop into text (ddwtos)] &lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddmarker Drag and drop markers question type (ddmarker)]&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_ddimageortext Drag and drop (image or text) onto image (ddimageortext)]&lt;br /&gt;
*** inherits code from Select missing words (gapselect).&lt;br /&gt;
*** also contains base classes which inherit from Select missing words (gapselect) and are used by Drag and drop markers&lt;br /&gt;
*** Use of YUI js module to add more interactivity.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_oumultiresponse OU multiple response (oumultiresponse)]&lt;br /&gt;
*** Question with multiple parts where grade is calculated by part for multiple attempts, student is given the grade for each part for the first time they got that part right or partially right.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatch Pmatch question type (pmatch)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_pmatchjme Pattern match with JME editor (pmatchjme)]&lt;br /&gt;
*** Embeds a JAVA applet in the question which collects the student response and sends that to the server.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qbehaviour_opaque Question managed by a remote engine (opaque)]&lt;br /&gt;
*** communicates with an external system by a web service protocol based on SOAP to &amp;quot;delegate the rendering of questions, the scoring of responses and the generation of feedback to a remote question engine.&amp;quot; See https://docs.moodle.org/dev/Opaque&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_gapselect Select missing words (gapselect)]&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumeric Variable numeric question type (varnumeric)]&lt;br /&gt;
*** Code inherited from Variable numeric set.&lt;br /&gt;
** [https://moodle.org/plugins/view.php?plugin=qtype_varnumericset Variable numeric set question type (varnumericset)]&lt;br /&gt;
&lt;br /&gt;
==Question type plug in template==&lt;br /&gt;
&lt;br /&gt;
There is a [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/ question type plug in template available on github]. See the [https://github.com/marcusgreen/moodle-qtype_TEMPLATE/blob/master/README.md README.md] file on the front page of the repository for more info about this template and how you are recommended to use it.&lt;br /&gt;
&lt;br /&gt;
==The question engine itself is well commented==&lt;br /&gt;
&lt;br /&gt;
Also note that all the question engine code has extensive PHP documenter comments that should explain the purpose of every class and method. This document is supposed to provide an overview of the key points to get you started. It does not attempt to duplicate all the details in the PHPdocs.&lt;br /&gt;
&lt;br /&gt;
This document assumes that you understand the data model, where a question attempt comprises a number of steps, and each step has some properties like a state and a mark, and an array of submitted data. [[Question_Engine_2:Overview|See the question engine overview doc for background]].&lt;br /&gt;
&lt;br /&gt;
===Changes in the question type plug in api between Moodle versions===&lt;br /&gt;
&lt;br /&gt;
[https://github.com/moodle/moodle/blob/master/question/type/upgrade.txt question/type/upgrade.txt] details the changes in the question type plug in api between Moodle versions.&lt;br /&gt;
&lt;br /&gt;
==File layout==&lt;br /&gt;
&lt;br /&gt;
Question types live in a folder in &amp;lt;tt&amp;gt;question/type&amp;lt;/tt&amp;gt;. The layout inside this folder follows the typical layout for a Moodle plugin. For example, inside the &amp;lt;tt&amp;gt;question/type/mytype/&amp;lt;/tt&amp;gt; folder we would have:&lt;br /&gt;
&lt;br /&gt;
; edit_YOURQTYPENAME_form.php : is the moodle_form used to define your question editing form. See [lib/formslib.php_Form_Definition] for details of how to use the formslib api.&lt;br /&gt;
; questiontype.php : Defines the &amp;lt;tt&amp;gt;qtype_mytype&amp;lt;/tt&amp;gt; class. This must extend &amp;lt;tt&amp;gt;question_type&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; question.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_question&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; renderer.php : This contains the definition of the &amp;lt;tt&amp;gt;qtype_mytype_renderer&amp;lt;/tt&amp;gt; class, which should extend the &amp;lt;tt&amp;gt;qtype_renderer&amp;lt;/tt&amp;gt; base class.&lt;br /&gt;
; tests/... : Contains the [[PHPUnit|unit tests]] and [[Acceptance_testing|Behat tests]] for this question type. You are strongly encouraged to write thorough unit tests to ensure the correctness of your question type.&lt;br /&gt;
; lang/en/qtype_myqtype.php : English language strings for this question type. You can, of course, include other languages too. The language file must define at least the strings giving the model a name etc., for example : &lt;br /&gt;
&lt;br /&gt;
    $string[&#039;pluginname&#039;] = &#039;YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginname_help&#039;] = &#039;Create a .. description of your question type&#039;; // This is the text of the help icon show by the heading above the add/edit form when a question of this type is being edited.&lt;br /&gt;
    $string[&#039;pluginname_link&#039;] = &#039;question/type/YOURQTYPENAME&#039;;&lt;br /&gt;
    $string[&#039;pluginnameadding&#039;] = &#039;Adding a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnameediting&#039;] = &#039;Editing a YOURQTYPENAME question&#039;;&lt;br /&gt;
    $string[&#039;pluginnamesummary&#039;] = &#039;A YOURQTYPENAME question type which allows...&#039;; // This is the text relating to this question type shown in the question-type chooser dialogue.&lt;br /&gt;
&lt;br /&gt;
; lib.php : There is an importnat callback here that is called by the question engine to allow access to files used by questions. As with other plugins, you can put library code here, but in modern Moodle code it is better to use the classes/ folder.&lt;br /&gt;
; db/install.xml, db/upgrade.php : For creating any database tables required, [[Installing_and_upgrading_plugin_database_tables|as normal]]. See [[#Database_tables]] below.&lt;br /&gt;
; db/access.php : Defines any capabilities required by this question type. This is very rarely needed.&lt;br /&gt;
; version.php : [[version.php|version information]] for the question type. Also you can included in here which version no of core Moodle and/or other question types this module requires. Bumping up the question version will trigger the appropriate code in upgrade.php to be run when someone accesses {yourwwwroot}/admin/.&lt;br /&gt;
; styles.css : contains the styles used by your question type. You should preface all your selectors with .que.YOURQTYPENAME so that the styles are only applied to your question type which is wrapped in a div with class &#039;que&#039; and &#039;YOURQTYPENAME&#039;.&lt;br /&gt;
; pix/icon.svg: is the 16 * 16 px icon that appears next to your question type in the question type selection panel. (Can aslo be .png or .gif.)&lt;br /&gt;
; backup/moodle2/ : contains the files to implement backup and restore for your question type.&lt;br /&gt;
; classes/ : As with any Moodle plugin, you can put any extra classes you want to use to organise your code in here, and they will be [[Automatic_class_loading|auto-loaded]].&lt;br /&gt;
; settings.php (optional) : Admin menu settings that are for every question of this type. See [[Admin settings]] for info on how to add a settings page for your question type and the examples in some question types.&lt;br /&gt;
; amd/ : any [[Javascript_Modules|JavaScript modules]] your question type needs. (Old YUI-style JavaScript in yui/ or module.js would still work, but is not recommended.)&lt;br /&gt;
&lt;br /&gt;
==Database tables==&lt;br /&gt;
&lt;br /&gt;
Note that question types should only have database tables for the question definition. All runtime data is managed by the question engine.&lt;br /&gt;
&lt;br /&gt;
Question definitions should use the core table &amp;lt;tt&amp;gt;question&amp;lt;/tt&amp;gt;, and can use the core table &amp;lt;tt&amp;gt;question_answers&amp;lt;/tt&amp;gt;. You only need to define database tables if your question definition requires extra information that cannot be stored in either of these.&lt;br /&gt;
&lt;br /&gt;
==Question type and question definition classes==&lt;br /&gt;
&lt;br /&gt;
===The question definition class is in question.php===&lt;br /&gt;
&lt;br /&gt;
This holds the definition of a particular question of this type. For example, an object of type qtype_shortanswer_question is a short-answer question instance. If you load three short-answer questions from the question bank, then you will get three instances of that class. This class is not just the question definition, it can also track the current state of a question as a student attempts it. For example, for a multiple-choice question, the class will store what order the choices have been randomly shuffled into for that student. To put it another way, the question_definition often works with a particular question_attempt.&lt;br /&gt;
&lt;br /&gt;
===The question type class is in questiontype.php===&lt;br /&gt;
&lt;br /&gt;
In contrast, the question type class represents the question type. For example, the qtype_shortanswer class represents the &#039;short answer&#039; type of question, and there will normally only be a single instance of this class. It has several responsiblities, including providing meta-data about this question type (e.g. public function name()). It knows how to load, save and delete questions of this type to and from the database (get_question_options and save_question_options, delete_question) and hence how to construct instances of the qtype_shortanswer_question class. It provides methods to help with editing questions of this type. It can also provide the implmentation for import and export in various formats.&lt;br /&gt;
&lt;br /&gt;
==Renderer class==&lt;br /&gt;
&lt;br /&gt;
Renderers are all about generating HTML output. The overall output of questions is controlled by the &amp;lt;tt&amp;gt;core_question_renderer::question(...)&amp;lt;/tt&amp;gt;, which in turn calls other methods of itself, the question type renderer and the behaviour renderer, to generate the various bits of output. See [[Question_Engine_2:Overview#What_are_the_parts_of_a_question.3F|this overview of the parts of a question]].&lt;br /&gt;
&lt;br /&gt;
Once again, in what follows, I only list the methods your are most likely to want to override.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===formulation_and_controls===&lt;br /&gt;
&lt;br /&gt;
This displays the question text, and the controls the student will use to input their response. Some question types choose to display some feedback embedded in this area, for example ticks and crosses next to parts of the student&#039;s response.&lt;br /&gt;
&lt;br /&gt;
The output code must respect the &amp;lt;tt&amp;gt;question_display_options&amp;lt;/tt&amp;gt; and only reveal as much information as the calling code wants revealed. For example, the teacher creating a quiz may not want the correct answer revealed until after the quiz close date. Also, when outputting the controls, you need to respect the &amp;lt;tt&amp;gt;-&amp;gt;readonly&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
&lt;br /&gt;
===specific_feedback===&lt;br /&gt;
&lt;br /&gt;
Anything returned by this method is included in the &#039;outcome&#039; area of the question, it is some feedback that particularly relates to the response the student gave. This method is only called if the display options allow this to be shows, so you don&#039;t have to worry about testing that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===correct_response===&lt;br /&gt;
&lt;br /&gt;
This would also be included in the &#039;outcome&#039; area. This should be an automatically generated (from the question definition) display of what the correct answer to the question is.&lt;br /&gt;
&lt;br /&gt;
==Unit tests==&lt;br /&gt;
&lt;br /&gt;
For a general introduction, see the [[PHPUnit|Moodle unit testing documentation]].&lt;br /&gt;
&lt;br /&gt;
The most important parts of your question type to test are the parts of the &amp;lt;tt&amp;gt;question_definition&amp;lt;/tt&amp;gt; class that process the students responses, including the compare and grade methods. The best way to start is probably to look at the tests for some of the standard question types.&lt;br /&gt;
&lt;br /&gt;
Another useful type of test for questions are &#039;walkthrough&#039; tests. These are implemented in using PHPunit, even though they are more integration tests than unit tests. There is [https://github.com/moodle/moodle/blob/master/question/engine/tests/helpers.php#L728 a detailed comment on the base class that explains more] and there are some nice examples in the core questions and also in the [https://github.com/moodleou/moodle-qtype_oumultiresponse/blob/master/tests/walkthrough_test.php OU Multi response github repository].&lt;br /&gt;
&lt;br /&gt;
Finally, it is good to have a few Behat tests, to check that everything works end-to-end. However, since Behat is much slower than unit tests, it is best to test all the details of the grading in PHPunit.&lt;br /&gt;
&lt;br /&gt;
==Manually testing a question type==&lt;br /&gt;
&lt;br /&gt;
The following provides a thorough test of a new question type. A lot of the following can now be done with [[Acceptance_testing|Behat]].&lt;br /&gt;
&lt;br /&gt;
# Create some new questions of your type, exercising each significantly different combination of options.&lt;br /&gt;
# Go back to the editing form for each question to make sure that the options were saved accurately and that you can change them and that the changes are then saved.&lt;br /&gt;
# Try typing invalid input into the editing form, and ensure it is rejected.&lt;br /&gt;
# Preview each of your new questions using a variety of question behaviours. Check the mark and feedback for a range of correct and incorrect responses.&lt;br /&gt;
# Add your questions to some quizzes, using a range of behaviours, and different numbers of questions per page.&lt;br /&gt;
# Preview those quizzes several times, entering a range of correct and incorrect responses. Note that during this testing, some useful behind-the-scenes data (e.g. question summary, the exact behaviour being used) is shown in the Technical information region, so you probably want to expand that region, and check what is going on there.&lt;br /&gt;
# Now log in as a student and take the quizzes for real.&lt;br /&gt;
# If the question type uses complex CSS or JavaScript, repeat this testing in different web browsers.&lt;br /&gt;
# View all of the quiz reports, and ensure that they correctly display the information about your questions.&lt;br /&gt;
# Backup the course, restore it as a new course, and ensure that all your questions have been copied across accurately.&lt;br /&gt;
# Export your questions from the original course to each of the import/export formats your support. Import these questions to a new question category, and ensure they have been copied accurately (within the limits to which your question type can be represented in each format).&lt;br /&gt;
# Edit the questions so that there is a link to another part of the course (e.g. a Page resource) in every place that HTML can be entered. Repeat the backup and restore test and verify that the URLs in the restored question have been updated to point to the new copy of the Page resource in the new course.&lt;br /&gt;
# Edit the question to add an image to every HTML field that supports it. Repeat the Editing, Preview, Backup/restore and Export/import tests, and verify that the images always work, and that you don&#039;t end up with broken image links.&lt;br /&gt;
# Move the category containing the questions with images to a new context in the question bank, and make sure that the image links don&#039;t break.&lt;br /&gt;
# Check that all the unit tests for your question type pass.&lt;br /&gt;
# Run code-checker (https://moodle.org/plugins/view.php?plugin=local_codechecker) over your plugin to check the coding style.&lt;br /&gt;
# Check your question type against Accessibility guidelines, for example the [http://www.w3.org/WAI/intro/wcag.php Web Content Accessibility Guidelines].&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
Next section: [[Using_the_question_engine_from_module|Using the question engine from a module]].&lt;br /&gt;
&lt;br /&gt;
* The PHP documenter comments that explain the purposes of every method in the question engine code.&lt;br /&gt;
* Back to [[Question_Engine_2|Question Engine 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57746</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57746"/>
		<updated>2020-08-04T21:20:56Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: /* Show coding standards issues (plugin) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://github.com/wongjn/vscode-php-sniffer&lt;br /&gt;
&lt;br /&gt;
[[File:phpcs_sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:phpcs_sniff.png&amp;diff=57745</id>
		<title>File:phpcs sniff.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:phpcs_sniff.png&amp;diff=57745"/>
		<updated>2020-08-04T21:20:31Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57744</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57744"/>
		<updated>2020-08-04T21:19:24Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://github.com/wongjn/vscode-php-sniffer&lt;br /&gt;
&lt;br /&gt;
[[File:sniff.png]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=File:sniff.png&amp;diff=57743</id>
		<title>File:sniff.png</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=File:sniff.png&amp;diff=57743"/>
		<updated>2020-08-04T21:17:18Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57742</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57742"/>
		<updated>2020-08-04T21:16:47Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://github.com/wongjn/vscode-php-sniffer&lt;br /&gt;
&lt;br /&gt;
[[File:sniff.jpg|thumb]]&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57718</id>
		<title>Setting up VSCode</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_VSCode&amp;diff=57718"/>
		<updated>2020-07-18T08:54:45Z</updated>

		<summary type="html">&lt;p&gt;Marcusgreen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;VSCode stub&lt;br /&gt;
https://en.wikipedia.org/wiki/Visual_Studio_Code&lt;br /&gt;
&lt;br /&gt;
VSCode is a an Integrated Development Environment from Microsoft available under the MIT License.&lt;br /&gt;
It works on Linux/Windows/OSX. It has a large number of plugins available, most entirely free/libre. It has good support&lt;br /&gt;
for Xdebug.&lt;br /&gt;
&lt;br /&gt;
== Moodle specific Snippets and autocomplete (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=MateuszLesiak.vscode-moodle-snippets&lt;br /&gt;
&lt;br /&gt;
Offers some useful Moodle specific code completion popups.&lt;br /&gt;
&lt;br /&gt;
== Code Formatting (indentation) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=kokororin.vscode-phpfmt&lt;br /&gt;
&lt;br /&gt;
== Show coding standards issues (plugin) ==&lt;br /&gt;
If you have Code Sniffer set up&lt;br /&gt;
https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Sniffs/Sniff.php&lt;br /&gt;
(or https://github.com/moodlehq/moodle-local_codechecker)&lt;br /&gt;
This plugin will show a wavy red line under code that does not conform.&lt;br /&gt;
https://github.com/wongjn/vscode-php-sniffer&lt;br /&gt;
&lt;br /&gt;
== Run phpunit tests from within IDE (plugin) ==&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=danilopolani.yet-another-phpunit&lt;br /&gt;
&lt;br /&gt;
A file of unit tests or individual test can be run from within the IDE&lt;br /&gt;
&lt;br /&gt;
== Generate PHP Doc blocks ==&lt;br /&gt;
Type /** at the top of the function and it grabs the parameters, including types if given and creates a PHPDoc block&lt;br /&gt;
&lt;br /&gt;
https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker&lt;br /&gt;
== Auto trim trailing white space == &lt;br /&gt;
To ensure trailing white space is trimmed do the following &lt;br /&gt;
&lt;br /&gt;
Open VS User Settings (Preferences &amp;gt; Settings &amp;gt; User Settings tab).&lt;br /&gt;
Click the {} icon in the top-right part of the window. This will open a document.&lt;br /&gt;
&lt;br /&gt;
Add a new &amp;quot;files.trimTrailingWhitespace&amp;quot;: true setting to the User Settings document if it&#039;s not already there. &lt;br /&gt;
This is so you aren&#039;t editing the Default Setting directly, but instead adding to it.&lt;br /&gt;
&lt;br /&gt;
Save the User Settings file.&lt;/div&gt;</summary>
		<author><name>Marcusgreen</name></author>
	</entry>
</feed>