Files
opensourcepos/tests
jekkos 690f43578d Use Content-Type application/json for AJAX responses (#4357)
Complete Content-Type application/json fix for all AJAX responses

- Add missing return statements to all ->response->setJSON() calls
- Fix Items.php method calls from JSON() to setJSON()
- Convert echo statements to proper JSON responses
- Ensure consistent Content-Type headers across all controllers
- Fix 46+ instances across 12 controller files
- Change Config.php methods to : ResponseInterface (all return setJSON only):
  - postSaveRewards(), postSaveBarcode(), postSaveReceipt()
  - postSaveInvoice(), postRemoveLogo()
  - Update PHPDoc @return tags

- Change Receivings.php _reload() to : string (only returns view)
- Change Receivings.php methods to : string (all return _reload()):
  - getIndex(), postSelectSupplier(), postChangeMode(), postAdd()
  - postEditItem(), getDeleteItem(), getRemoveSupplier()
  - postComplete(), postRequisitionComplete(), getReceipt(), postCancelReceiving()
- Change postSave() to : ResponseInterface (returns setJSON)
- Update all PHPDoc @return tags

Fix XSS vulnerabilities in sales templates, login, and config pages

This commit addresses 5 XSS vulnerabilities by adding proper escaping
to all user-controlled configuration values in HTML contexts.

Fixed Files:
- app/Views/sales/invoice.php: Escaped company_logo (URL context) and company (HTML)
- app/Views/sales/work_order.php: Escaped company_logo (URL context)
- app/Views/sales/receipt_email.php: Added file path validation and escaping for logo
- app/Views/login.php: Escaped all config values in title, logo src, and alt
- app/Views/configs/info_config.php: Escaped company_logo (URL context)

Security Impact:
- Prevents stored XSS attacks if configuration is compromised
- Defense-in-depth principle applied to administrative interfaces
- Follows OWASP best practices for output encoding

Testing:
- Verified no script execution with XSS payloads in config values
- Confirmed proper escaping in HTML, URL, and file contexts
- All templates render correctly with valid configuration

Severity: High (4 files), Medium-High (1 file)
CVSS Score: ~6.1
CWE: CWE-79 (Improper Neutralization of Input During Web Page Generation)

Fix critical password validation bypass and add unit tests

This commit addresses a critical security vulnerability where the password
minimum length check was performed on the HASHED password (always 60
characters for bcrypt) instead of the actual password before hashing.

Vulnerability Details:
- Original code: strlen($employee_data['password']) >= 8
- This compared the hash length (always 60) instead of raw password
- Impact: Users could set 1-character passwords like "a"
- Severity: Critical (enables brute force attacks on weak passwords)
- CVE-like issue: CWE-307 (Improper Restriction of Excessive Authentication Attempts)

Fix Applied:
- Validate password length BEFORE hashing
- Clear error message when password is too short
- Added unit tests to verify minimum length enforcement
- Regression test to prevent future vulnerability re-introduction

Test Coverage:
- testPasswordMinLength_Rejects7Characters: Verify 7 chars rejected
- testPasswordMinLength_Accepts8Characters: Verify 8 chars accepted
- testPasswordMinLength_RejectsEmptyString: Verify empty rejected
- testPasswordMinLength_RejectsWhitespaceOnly: Verify whitespace rejected
- testPasswordMinLength_AcceptsSpecialCharacters: Verify special chars OK
- testPasswordMinLength_RejectsPreviousBehavior: Regression test for bug

Files Modified:
- app/Controllers/Home.php: Fixed password validation logic
- tests/Controllers/HomeTest.php: Added comprehensive unit tests

Security Impact:
- Enforces 8-character minimum password policy
- Prevents extremely weak passwords that facilitate brute-force attacks
- Critical for credential security and user account protection

Breaking Changes:
- Users with passwords < 8 characters will need to reset their password
- This is the intended security improvement

Severity: Critical
CVSS Score: ~7.5
CWE: CWE-305 (Authentication Bypass by Primary Weakness), CWE-307

Add GitHub Actions workflow to run PHPUnit tests

Move business logic from views to controllers for better separation of concerns

- Move logo URL computation from info_config view to Config::getIndex()
- Move image base64 encoding from receipt_email view to Sales controller
- Improves separation of concerns by keeping business logic in controllers
- Simplifies view templates to only handle presentation

Fix XSS vulnerabilities in report views - escape user-controllable summary data and labels

Fix base64 encoding URL issue in delete payment - properly URL encode base64 string

Fix remaining return type declarations for Sales controller

Fixed additional methods that call _reload():
- postAdd() - returns _reload($data)
- postAddPayment() - returns _reload($data)
- postEditItem() - returns _reload($data)
- postSuspend() - returns _reload($data)
- postSetPaymentType() - returns _reload()

All methods now return ResponseInterface|string to match _reload() signature.
This resolves PHP TypeError errors.
2026-03-04 21:42:35 +01:00
..
2024-06-15 17:19:15 +02:00

Running Application Tests

This is the quick-start to CodeIgniter testing. Its intent is to describe what it takes to set up your application and get it ready to run unit tests. It is not intended to be a full description of the test features that you can use to test your application. Those details can be found in the documentation.

Resources

Requirements

It is recommended to use the latest version of PHPUnit. At the time of this writing, we are running version 9.x. Support for this has been built into the composer.json file that ships with CodeIgniter and can easily be installed via Composer if you don't already have it installed globally.

> composer install

If running under macOS or Linux, you can create a symbolic link to make running tests a touch nicer.

> ln -s ./vendor/bin/phpunit ./phpunit

You also need to install XDebug in order for code coverage to be calculated successfully. After installing XDebug, you must add xdebug.mode=coverage in the php.ini file to enable code coverage.

Setting Up

A number of the tests use a running database. In order to set up the database edit the details for the tests group in app/Config/Database.php or .env. Make sure that you provide a database engine that is currently running on your machine. More details on a test database setup are in the Testing Your Database section of the documentation.

Running the tests

The entire test suite can be run by simply typing one command-line command from the main directory.

> ./phpunit

If you are using Windows, use the following command.

> vendor\bin\phpunit

You can limit tests to those within a single test directory by specifying the directory name after phpunit.

> ./phpunit app/Models

Generating Code Coverage

To generate coverage information, including HTML reports you can view in your browser, you can use the following command:

> ./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m

This runs all of the tests again collecting information about how many lines, functions, and files are tested. It also reports the percentage of the code that is covered by tests. It is collected in two formats: a simple text file that provides an overview as well as a comprehensive collection of HTML files that show the status of every line of code in the project.

The text file can be found at tests/coverage.txt. The HTML files can be viewed by opening tests/coverage/index.html in your favorite browser.

PHPUnit XML Configuration

The repository has a phpunit.xml.dist file in the project root that's used for PHPUnit configuration. This is used to provide a default configuration if you do not have your own configuration file in the project root.

The normal practice would be to copy phpunit.xml.dist to phpunit.xml (which is git ignored), and to tailor it as you see fit. For instance, you might wish to exclude database tests, or automatically generate HTML code coverage reports.

Test Cases

Every test needs a test case, or class that your tests extend. CodeIgniter 4 provides one class that you may use directly:

  • CodeIgniter\Test\CIUnitTestCase

Most of the time you will want to write your own test cases that extend CIUnitTestCase to hold functions and services common to your test suites.

Creating Tests

All tests go in the tests/ directory. Each test file is a class that extends a Test Case (see above) and contains methods for the individual tests. These method names must start with the word "test" and should have descriptive names for precisely what they are testing: testUserCanModifyFile() testOutputColorMatchesInput() testIsLoggedInFailsWithInvalidUser()

Writing tests is an art, and there are many resources available to help learn how. Review the links above and always pay attention to your code coverage.

Database Tests

Tests can include migrating, seeding, and testing against a mock or live database. Be sure to modify the test case (or create your own) to point to your seed and migrations and include any additional steps to be run before tests in the setUp() method. See Testing Your Database for details.