# Tests for LanguageCSVExporter There are two kinds of tests: - **Unit tests** (`Unit/`, PHPUnit) run without a ProcessWire installation or database. The used ProcessWire classes are replaced by small stubs (`stubs/ProcessWireStubs.php`). They run in a few milliseconds and also on GitHub Actions for every push. - **WireTests** (`LanguageCSVExporter.test.php`) run inside a real ProcessWire installation with the real database, modules, languages, translation files and `LanguagePorter`. ## Unit tests ### Requirements - PHP 8.2 or higher and Composer (the module itself runs with PHP 7.2 or higher) ### Installation Run once inside this `tests` folder: ``` composer install ``` ### Run the tests Inside this `tests` folder: ``` vendor/bin/phpunit ``` On Windows use `vendor\bin\phpunit`. ### What is tested | File | Content | |------|---------| | `Unit/PrimaryModuleTest.php` | Detection of the primary module in a shared folder: exact name, case-insensitive, GitHub download folders (`-main`, `-master`, versions), class prefix, no primary module | | `Unit/OwnershipRulesTest.php` | File assignment for a module bundle (`FrontendForms` + companion module + module in a subfolder + uninstalled module), renamed folder, folders with similar names, warning without primary module, Windows paths | | `Unit/FileBelongsToModuleTest.php` | Which source files belong to a primary or guest module, path normalization | | `Unit/MergeCsvExportsTest.php` | Joining the exports of the single files: header once, rows byte-identical (backslash at the end, multi-line texts, quotes, UTF-8), files without rows, line breaks | | `Unit/CreateCsvExportTest.php` | Translation files (both file fields, unregistered files in the files folder like RockLanguage copies them, no source file, duplicates), export of primary/guest/sub-module, options passed to LanguagePorter, skipped files, error messages, `display_errors` is off during the export and restored (also after an exception) | | `Unit/TranslatableTextsTest.php` | All texts shown to the user are translatable (no hard-coded texts in exceptions, labels, descriptions, notices; module info with `__()`), numbered placeholders, inserted values | | `Unit/LanguageFilesTest.php` | Translation files in `languages/`: format, hashes, all texts translated, no outdated texts, placeholders kept | | `Unit/FilenameAndDownloadTest.php` | File name of the download (special characters, path traversal, empty names), download from memory | The form, the CSRF protection, the permission and the real `LanguagePorter` are tested by the WireTests below. ## WireTests ### Requirements - ProcessWire 3.0.267 or newer with the module **Wire Tests** installed (Modules > Refresh > Wire Tests > Install) - LanguageSupport installed and LanguageCSVExporter installed ### Run the tests From the ProcessWire root directory: ``` php index.php test site/modules/LanguageCSVExporter/tests/LanguageCSVExporter.test.php ``` The full path is required. WireTests does not search subfolders of site modules (exclusion `site/modules/*/*/` in the core), so `php index.php test LanguageCSVExporter` does not find this file. Some checks need an installed module with registered translations for at least one language (translate at least one module file via **Setup > Languages > (language) > Find Files to Translate**). Without such a module these checks are skipped and a note is shown. ### What is tested - Installation: module, version, permission (not for guests), admin page below Setup, no own install/uninstall code - Admin form: module and language select, button text, only installed modules, all languages, CSRF token - Detection of the primary module and file assignment on real core folders (`wire/modules/LanguageSupport/`, `wire/modules/Markup/`) - Joining the exports of the single files and the registered translation files of every language - Export without translations: understandable error message - Export of a real module: header columns, only files of the module, compared with the raw `LanguagePorter` export; PHP notices/deprecations (WireTests runs with `display_errors=1`) do not end up in the CSV - Form submission: errors (no translations, unknown module, unknown language, invalid CSRF token) are shown and the form is rendered again; a valid request sends the CSV as download (intercepted by a hook, nothing is sent) - Translations (for every language with a translation file for this module): all texts translated, no outdated translations, admin page and error messages in the language of the user - No temporary files in the language files folders or in the cache - Web server rules: `.module` and test files must return 403 (skipped if the site is not reachable via HTTP from the command line) - Live export of a translation ending with a backslash (e.g. a Windows path): it is included and the rows are byte-identical to the `LanguagePorter` export The test changes one translation file temporarily (for the backslash test) and restores it at the end, together with POST values, notices and session notices - also if a check fails. Nevertheless, run it on a development or staging copy first. ## Security This folder is protected by a `.htaccess` file (Apache). On other web servers (e.g. Nginx) deny the access to `site/modules/LanguageCSVExporter/tests/` in the server configuration or do not upload this folder to the live server. The folder is excluded from the release archives via `.gitattributes`.