mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-11-08 23:43:32 -05:00
Merge remote-tracking branch 'OpensourcePOS/master' into feat-export-toggle-all
# Conflicts: # composer.json # composer.lock # tests/Controllers/CashupControllerTest.php # tests/Controllers/EmployeesControllerTest.php # tests/Controllers/ItemKitsControllerTest.php # tests/Controllers/SalesControllerTest.php # tests/Controllers/TaxesControllerTest.php # tests/Helpers/export_helperTest.php # tests/Helpers/tabular_helperTest.php # tests/Helpers/tax_helperTest.php
This commit is contained in:
commit
33efb401bf
76 files changed
+799
-934
No files matched your search
@@ -40,6 +40,16 @@ jobs:
|
||||
extensions: intl, mbstring, mysqli, gd, bcmath, zip
|
||||
coverage: none
|
||||
|
||||
- name: Verify PHP patch level
|
||||
run: |
|
||||
MIN="8.2.35"
|
||||
ACTUAL=$(php -r 'echo PHP_VERSION;')
|
||||
if [ "$(printf '%s\n' "$MIN" "$ACTUAL" | sort -V | head -1)" != "$MIN" ]; then
|
||||
echo "::error::PHP $ACTUAL is below patched minimum $MIN (CVE-2026-109618 / CVE-2026-109619)"
|
||||
exit 1
|
||||
fi
|
||||
echo "PHP $ACTUAL meets minimum $MIN"
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -94,6 +104,16 @@ jobs:
|
||||
env:
|
||||
GITHUB_TAG: ${{ github.ref_name }}
|
||||
|
||||
- name: Normalize version for official release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
# The tagged commit may still carry a -dev suffix in source files.
|
||||
# Strip it so the archive contents report the clean release version.
|
||||
sed -i "s/application_version = '${VERSION}-dev'/application_version = '${VERSION}'/" app/Config/App.php
|
||||
sed -i "s/\"version\": \"${VERSION}-dev\"/,\"version\": \"${VERSION}\",/" package.json 2>/dev/null || true
|
||||
echo "App.php now reports: $(grep application_version app/Config/App.php)"
|
||||
|
||||
- name: Validate release tag
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
|
||||
@@ -43,6 +43,22 @@ jobs:
|
||||
extensions: tokenizer
|
||||
coverage: none
|
||||
|
||||
- name: Verify PHP patch level
|
||||
run: |
|
||||
ACTUAL=$(php -r 'echo PHP_VERSION;')
|
||||
case "${ACTUAL%.*}" in
|
||||
8.2) MIN="8.2.35" ;;
|
||||
8.3) MIN="8.3.36" ;;
|
||||
8.4) MIN="8.4.27" ;;
|
||||
8.5) MIN="8.5.12" ;;
|
||||
*) echo "::error::Unsupported PHP branch: $ACTUAL"; exit 1 ;;
|
||||
esac
|
||||
if [ "$(printf '%s\n' "$MIN" "$ACTUAL" | sort -V | head -1)" != "$MIN" ]; then
|
||||
echo "::error::PHP $ACTUAL is below patched minimum $MIN (CVE-2026-109618 / CVE-2026-109619)"
|
||||
exit 1
|
||||
fi
|
||||
echo "PHP $ACTUAL meets minimum $MIN"
|
||||
|
||||
- name: Get composer cache directory
|
||||
run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: PHP Linting
|
||||
|
||||
on: push
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
phplint:
|
||||
|
||||
@@ -56,6 +56,22 @@ jobs:
|
||||
extensions: intl, mbstring, mysqli
|
||||
coverage: none
|
||||
|
||||
- name: Verify PHP patch level
|
||||
run: |
|
||||
ACTUAL=$(php -r 'echo PHP_VERSION;')
|
||||
case "${ACTUAL%.*}" in
|
||||
8.2) MIN="8.2.35" ;;
|
||||
8.3) MIN="8.3.36" ;;
|
||||
8.4) MIN="8.4.27" ;;
|
||||
8.5) MIN="8.5.12" ;;
|
||||
*) echo "::error::Unsupported PHP branch: $ACTUAL"; exit 1 ;;
|
||||
esac
|
||||
if [ "$(printf '%s\n' "$MIN" "$ACTUAL" | sort -V | head -1)" != "$MIN" ]; then
|
||||
echo "::error::PHP $ACTUAL is below patched minimum $MIN (CVE-2026-109618 / CVE-2026-109619)"
|
||||
exit 1
|
||||
fi
|
||||
echo "PHP $ACTUAL meets minimum $MIN"
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
@@ -28,6 +28,52 @@ This document provides guidance for AI agents working on the Open Source Point o
|
||||
- Tests must pass before submitting changes
|
||||
- **One test file per class under test.** A controller, model, library, or helper gets exactly one test file covering all of its behavior — `Item_kits.php` → `tests/Controllers/Item_kitsTest.php` (or `Item_kitsControllerTest.php`, matching this codebase's existing `*ControllerTest.php` suffix for controllers), `Sale_lib.php` → `tests/Libraries/Sale_libTest.php`, etc. Do not create feature- or endpoint-scoped test files alongside a class's main test file (e.g. no `Item_kitsBarcodeTest.php` next to `Item_kitsControllerTest.php`) — add the new test methods to the existing file for that class instead. If no test file exists yet for the class, create the one canonical file rather than a narrowly-scoped one.
|
||||
- **Name test methods as `test{MethodUnderTest}_{Behavior}`.** `PascalCase` the method under test, then an underscore, then a short behavior phrase — `testPostSave_RejectsNegativeTaxPercent`, `testSaveLocale_AcceptsValidReferenceCodeMinMax`. Start the behavior with a verb: `Accepts`/`Requires` for valid or boundary cases, `Rejects` for invalid ones. The name should read as a self-documenting sentence and needs no docblock.
|
||||
- **Resetting the test database (full migration reset, not just `$refresh`).** When a test class needs the `ospos_tests` schema fully dropped and re-migrated from scratch (e.g. so `ospos_permissions`/`app_config` get freshly seeded), `use Tests\Support\DatabaseBootstrapTrait;` and call `$this->resetDatabaseOnce()` as the first line of `setUp()`, before `parent::setUp()`:
|
||||
```php
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
class FooTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
protected $seedOnce = true;
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
`DatabaseBootstrapTrait` (`tests/Support/DatabaseBootstrapTrait.php`) wraps `TestDatabaseBootstrapSeeder::reset()` with a per-class static guard so it only runs once per test class. Do **not** reinvent this with a local `private static bool $doneBootstrap` flag, `setUpBeforeClass()`, or `Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder')` followed by a manual `Config::connect($this->DBGroup)->close()`/`resetDataCache()` in the test file — those are the old patterns the trait replaces, and the manual version reintroduces the exact stale-connection bug `TestDatabaseBootstrapSeeder::reset()` already fixes internally. Only add this trait to test classes that actually touch the real test database (`DatabaseTestTrait` users) — pure unit tests that mock everything don't need it.
|
||||
If a test class reads `config(OSPOS::class)->settings` for real (not mocking it out), also call `config(OSPOS::class)->update_settings();` right after `parent::setUp();` to force a fresh settings read post-reset. See `tests/Controllers/ReportsControllerTest.php` for that shape.
|
||||
- **Mocking OSPOS config settings.** When a test needs `config(OSPOS::class)->settings` to return fixed values instead of reading from the database, `use Tests\Support\OsposConfigFixtureTrait;` and call `$this->injectOsposSettings([...])` instead of manually constructing `new OSPOS()` + `Factories::injectMock('config', OSPOS::class, $ospos)`:
|
||||
```php
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
class FooTest extends CIUnitTestCase
|
||||
{
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->injectOsposSettings([
|
||||
'number_locale' => 'en_US',
|
||||
'currency_decimals' => 2,
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
`OSPOS::getDefaultSettings()` is `private` and only covers a handful of keys, so it is not a usable base to merge onto — each test must supply the exact settings it depends on. Use this trait regardless of whether the test also uses `DatabaseBootstrapTrait`.
|
||||
|
||||
## Build
|
||||
|
||||
|
||||
+38
-1
@@ -1,4 +1,5 @@
|
||||
[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.2...HEAD
|
||||
[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.3...HEAD
|
||||
[3.4.3]: https://github.com/opensourcepos/opensourcepos/compare/3.4.2...3.4.3
|
||||
[3.4.2]: https://github.com/opensourcepos/opensourcepos/compare/3.4.1...3.4.2
|
||||
[3.4.1]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...3.4.1
|
||||
[3.4.0]: https://github.com/opensourcepos/opensourcepos/compare/3.3.9...3.4.0
|
||||
@@ -34,6 +35,42 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [3.4.3] - 2026-10-21
|
||||
- chore: bump version to 3.4.3 by @github-actions[bot]
|
||||
- chore(deps): bump dompurify from 3.4.13 to 3.4.16 (#4723) by @dependabot[bot]
|
||||
- fix(release): delete the unstable release by name, leave drafts alone by @jekkos
|
||||
- chore(deps): bump moment from 2.30.1 to 2.31.0 (#4722) by @dependabot[bot]
|
||||
- chore(deps): bump brace-expansion (#4721) by @dependabot[bot]
|
||||
- feat(items): optimize search, attribute filtering, and sort for items view (#4652) by @objecttothis
|
||||
- fix(i18n): add missing toggle_cost_and_profit key to 32 locales (#4712) by @Rayan Abdul Cader
|
||||
- fix(expenses): refresh table when date range or filters change (#4633) by @richardmilles
|
||||
- fix(auth): return 401 JSON for AJAX requests on session timeout (#4728) by @jekkos
|
||||
- docs: add test-method naming convention to AGENTS.md (#4735) by @jekkos
|
||||
- fix(config): improve responsive layout, nested tabs behavior, and label theming (#4719) by @BudsieBuds
|
||||
- fix(taxes): reject invalid characters in tax code, category, and jurisdiction names (#4733) by @jekkos
|
||||
- fix(appconfig): refresh cached settings once and avoid stale same-request reads (#4732) by @jekkos
|
||||
- Return early from sortAndFilterCart() when no items are printable (#4713) by @Rayan Abdul Cader
|
||||
- fix: refresh cashups and items tables on filter and date range change (#4731) by @jekkos
|
||||
- chore: update Node.js version to 22 and npm-check-updates to 23.1.0 in workflows and documentation (#4741) by @BudsieBuds
|
||||
- fix(models): handle query() returning false in result-consuming methods (#4734) by @jekkos
|
||||
- feat(reports): add detailed item sales report (#4538) by @enricodelarosa
|
||||
- fix(taxes): reject negative tax rates and percentages (#4730) by @jekkos
|
||||
- fix(sales): inline invoice/quote email CSS for DOMPDF PDFs (#4747) (#4749) by @jekkos
|
||||
- docs: rewrite upgrade guide for the current CI4 install model (#4750) by @jekkos
|
||||
- refactor: move Windows build scripts into tools/build, drop CI4 migration scripts (#4729) by @jekkos
|
||||
- feat(config): scope config assets and add system info copy notifications (#4753) by @BudsieBuds
|
||||
- docs: move BUILD.md, INSTALL.md, UPGRADE.md into docs/ (#4755) by @jekkos
|
||||
- feat(tables): update loading text size and spinner to bootstrap-table (#4757) by @BudsieBuds
|
||||
- feat(db): add MySQL 8.4 support (#4048) by @Alexander Laurent
|
||||
- style(lang): add Georgian, normalize quote style across all locales, add parse tests (#4762) by @objecttothis
|
||||
- feat(install): add one-line Ubuntu installer (#4550) by @jekkos
|
||||
- fix(release): bump master version to 3.4.3-dev (#4752) by @jekkos
|
||||
- fix(config): add invoice_enable and work_order_enable to default settings fallback (#4761) by @Sai Asish Y
|
||||
- refactor(gulp): modernize build pipeline and streamline dependencies (#4759) by @BudsieBuds
|
||||
- refactor(tests): normalize test namespaces to PSR-4 and clean up composer dependencies (#4758) by @BudsieBuds
|
||||
- fix(ci): trigger PHP linting workflow on pull requests (#4764) by @BudsieBuds
|
||||
- fix(security): pin patched PHP 8.2.35+ for CVE-2026-109618/109619 (#4767) by @jekkos
|
||||
|
||||
## [3.4.2] - 2026-09-30
|
||||
- Fix writable folder permission check (#4270) (#4273) by @jekkos
|
||||
- Extended payment delete fix (#4274) by @jekkos
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM php:8.2-apache AS ospos
|
||||
FROM php:8.2.35-apache AS ospos
|
||||
LABEL maintainer="jekkos"
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
|
||||
@@ -137,7 +137,7 @@ Any person or company found breaching the license agreement might find a bunch o
|
||||
|
||||
## 🙏 Credits
|
||||
|
||||
| <div align="center">DigitalOcean</div> | <div align="center">JetBrains</div> | <div align="center">GitHub</div> |
|
||||
| --- | --- | --- |
|
||||
| <div align="center"><a href="https://www.digitalocean.com?utm_medium=opensource&utm_source=opensourcepos" target="_blank"><img src="https://github.com/user-attachments/assets/fbbf7433-ed35-407d-8946-fd03d236d350" alt="DigitalOcean Logo" height="50"></a></div> | <div align="center"><a href="https://www.jetbrains.com/idea/" target="_blank"><img src="https://github.com/opensourcepos/opensourcepos/assets/12870258/187f9bbe-4484-475c-9b58-5e5d5f931f09" alt="IntelliJ IDEA Logo" height="50"></a></div> | <div align="center"><a href="https://github.com/features/actions" target="_blank"><img src="https://github.githubassets.com/images/modules/site/icons/eyebrow-panel/actions-icon.svg" alt="GitHub Actions Logo" height="50"></a></div> |
|
||||
| Many thanks to [DigitalOcean](https://www.digitalocean.com) for providing the project with hosting credits. | Many thanks to [JetBrains](https://www.jetbrains.com/) for providing a free license of [IntelliJ IDEA](https://www.jetbrains.com/idea/) to kindly support the development of OSPOS. | Many thanks to [GitHub](https://github.com) for providing free continuous integration via GitHub Actions for open-source projects. |
|
||||
| <div align="center">JetBrains</div> | <div align="center">GitHub</div> |
|
||||
| --- | --- |
|
||||
| <div align="center"><a href="https://www.jetbrains.com/idea/" target="_blank"><img src="https://github.com/opensourcepos/opensourcepos/assets/12870258/187f9bbe-4484-475c-9b58-5e5d5f931f09" alt="IntelliJ IDEA Logo" height="50"></a></div> | <div align="center"><a href="https://github.com/features/actions" target="_blank"><img src="https://github.githubassets.com/images/modules/site/icons/eyebrow-panel/actions-icon.svg" alt="GitHub Actions Logo" height="50"></a></div> |
|
||||
| Many thanks to [JetBrains](https://www.jetbrains.com/) for providing a free license of [IntelliJ IDEA](https://www.jetbrains.com/idea/) to kindly support the development of OSPOS. | Many thanks to [GitHub](https://github.com) for providing free continuous integration via GitHub Actions for open-source projects. |
|
||||
+1
-1
@@ -12,7 +12,7 @@ class App extends BaseConfig
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $application_version = '3.4.3-dev';
|
||||
public string $application_version = '3.4.4-dev';
|
||||
|
||||
/**
|
||||
* This is the commit hash for the version you are currently using.
|
||||
|
||||
@@ -25,7 +25,7 @@ class Migration_Initial_Schema extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/initial_schema.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/initial_schema.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ class Migration_Upgrade_To_3_1_1 extends Migration
|
||||
}
|
||||
}
|
||||
|
||||
if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.0.2_to_3.1.1.sql')) {
|
||||
if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.0.2_to_3.1.1.sql', false, $this->db)) {
|
||||
throw new DatabaseException('Migration script 3.0.2_to_3.1.1.sql failed. Check logs for details.');
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_Upgrade_To_3_2_0 extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.1.1_to_3.2.0.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.1.1_to_3.2.0.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_Upgrade_To_3_2_1 extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.0_to_3.2.1.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.0_to_3.2.1.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_Attributes extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_attributes.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_attributes.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_Upgrade_To_3_3_0 extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.1_to_3.3.0.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.2.1_to_3.3.0.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ class Migration_IndiaGST extends Migration
|
||||
|
||||
// If number of entries is greater than zero then the tax data needs to be migrated
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst.sql', false, $this->db);
|
||||
|
||||
$count_of_tax_codes = $this->get_count_of_tax_code_entries();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_IndiaGST1 extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst1.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst1.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_IndiaGST2 extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst2.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst2.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_decimal_attribute_type extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_decimal_attribute_type.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_decimal_attribute_type.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_add_iso_4217 extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_add_iso_4217.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_add_iso_4217.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_PaymentTracking extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_paymenttracking.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_paymenttracking.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_RefundTracking extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper(['migration', 'locale']);
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_refundtracking.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_refundtracking.sql', false, $this->db);
|
||||
|
||||
// Add missing cash_refund amounts to payments table
|
||||
$decimals = totals_decimals();
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_DBFix extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_dbfix.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_dbfix.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_fix_attribute_datetime extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_fix_attribute_datetime.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_fix_attribute_datetime.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_PaymentDateFix extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_paymentdatefix.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_paymentdatefix.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_SalesChangePrice extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_saleschangeprice.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_saleschangeprice.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_modify_attr_links_constraint extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_modify_attr_links_constraint.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_modify_attr_links_constraint.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_add_item_kit_number extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_modify_session_datatype extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.4_modify_session_datatype.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.3.4_modify_session_datatype.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -113,7 +113,7 @@ class Migration_database_optimizations extends Migration
|
||||
}
|
||||
$this->db->transComplete();
|
||||
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql', false, $this->db);
|
||||
log_message('info', 'Finished migrating database optimizations.');
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class ConvertToCI4 extends Migration
|
||||
{
|
||||
helper('migration');
|
||||
|
||||
if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_CI4Conversion.sql')) {
|
||||
if (!executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_CI4Conversion.sql', false, $this->db)) {
|
||||
throw new DatabaseException('Migration script 3.4.0_CI4Conversion.sql failed. Check logs for details.');
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class fix_duplicate_attributes extends Migration
|
||||
|
||||
dropForeignKeyConstraints($foreignKeys, 'attribute_links');
|
||||
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_attribute_links_unique_constraint.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_attribute_links_unique_constraint.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_sessions_migration extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_migrate_sessions_table.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_migrate_sessions_table.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ class AttributeLinksUniqueConstraint extends Migration
|
||||
dropForeignKeyConstraints($foreignKeys, 'attribute_links');
|
||||
dropColumnIfExists('ospos_attribute_links', 'generated_unique_column');
|
||||
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_attribute_links_unique_constraint.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_attribute_links_unique_constraint.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_MissingConfigKeys extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_missing_config_keys.sql', true);
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_missing_config_keys.sql', true, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ class Migration_NullableTaxCategoryId extends Migration
|
||||
public function up(): void
|
||||
{
|
||||
helper('migration');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_nullable_tax_category_id.sql');
|
||||
executeScript(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_nullable_tax_category_id.sql', false, $this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ class Migration_Mysql84Utf8mb4Conversion extends Migration
|
||||
}
|
||||
|
||||
$script = APPPATH . 'Database/Migrations/sqlscripts/3.4.3_mysql84_utf8mb4_conversion.sql';
|
||||
if (!executeScript($script)) {
|
||||
if (!executeScript($script, false, $this->db)) {
|
||||
throw new RuntimeException('Failed to execute utf8mb4 conversion migration: ' . $script);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class TestDatabaseBootstrapSeeder extends Seeder
|
||||
$serverConn->close();
|
||||
|
||||
// The application's shared 'tests' connection caches listTables()
|
||||
// results in dataCache['table_names'']. Because we dropped and
|
||||
// results in dataCache['table_names']. Because we dropped and
|
||||
// recreated the schema on a SEPARATE server connection above, that
|
||||
// cache is now stale. Reset it so subsequent listTables()/tableExists()
|
||||
// calls re-query the server instead of trusting a dropped schema's table
|
||||
|
||||
@@ -8,9 +8,10 @@ use Config\Database;
|
||||
* Executes a SQL migration script.
|
||||
* @param string $path Path to migration script.
|
||||
* @param bool $withTransaction Whether to wrap execution in a transaction.
|
||||
* @param BaseConnection|null $db Connection to use (defaults to the default connection).
|
||||
* @return bool Whether the migration executed successfully.
|
||||
*/
|
||||
function executeScript(string $path, bool $withTransaction = false): bool
|
||||
function executeScript(string $path, bool $withTransaction = false, ?BaseConnection $db = null): bool
|
||||
{
|
||||
$version = explode('_', basename($path, '.sql'), 2)[0];
|
||||
log_message('info', "Migrating to $version (file: $path)");
|
||||
@@ -18,7 +19,7 @@ function executeScript(string $path, bool $withTransaction = false): bool
|
||||
$sqls = explode(';', file_get_contents($path));
|
||||
array_pop($sqls);
|
||||
|
||||
$db = Database::connect();
|
||||
$db ??= Database::connect();
|
||||
|
||||
if ($withTransaction) {
|
||||
$db->transStart();
|
||||
@@ -84,8 +85,8 @@ function dropForeignKeyConstraints(array $foreignKeys, string $table): void
|
||||
* TODO: This function should be moved to a more global location since it may be needed outside of migrations.
|
||||
* @return string The prefix before overriding.
|
||||
*/
|
||||
function overridePrefix(string $prefix = ''): string {
|
||||
$db = Database::connect();
|
||||
function overridePrefix(string $prefix = '', ?BaseConnection $db = null): string {
|
||||
$db ??= Database::connect();
|
||||
|
||||
$originalPrefix = $db->getPrefix();
|
||||
$db->setPrefix($prefix);
|
||||
@@ -136,47 +137,50 @@ function createPrimaryKey(string $table, string $index): void {
|
||||
function dropAllForeignKeyConstraints(?string $table = null, ?string $column = null, ?BaseConnection $db = null): array {
|
||||
$db ??= Database::connect();
|
||||
$prefixedTable = $table !== null ? $db->getPrefix() . $table : null;
|
||||
$prefix = overridePrefix();
|
||||
|
||||
$builder = $db->table('information_schema.KEY_COLUMN_USAGE kcu');
|
||||
$builder->distinct();
|
||||
$builder->select('kcu.CONSTRAINT_NAME, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, kcu.ORDINAL_POSITION, rc.DELETE_RULE, rc.UPDATE_RULE');
|
||||
$builder->join(
|
||||
'information_schema.REFERENTIAL_CONSTRAINTS rc',
|
||||
'kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND kcu.TABLE_NAME = rc.TABLE_NAME',
|
||||
'left'
|
||||
);
|
||||
|
||||
if ($table !== null && $column !== null) {
|
||||
$scopedBuilder = $db->table('information_schema.KEY_COLUMN_USAGE scoped');
|
||||
$scopedBuilder->distinct();
|
||||
$scopedBuilder->select('scoped.CONSTRAINT_NAME, scoped.TABLE_NAME');
|
||||
$scopedBuilder->where('scoped.TABLE_SCHEMA', $db->database);
|
||||
$scopedBuilder->groupStart();
|
||||
$scopedBuilder->where('scoped.REFERENCED_TABLE_NAME', $prefixedTable);
|
||||
$scopedBuilder->where('scoped.REFERENCED_COLUMN_NAME', $column);
|
||||
$scopedBuilder->groupEnd();
|
||||
$scopedBuilder->orGroupStart();
|
||||
$scopedBuilder->where('scoped.TABLE_NAME', $prefixedTable);
|
||||
$scopedBuilder->where('scoped.COLUMN_NAME', $column);
|
||||
$scopedBuilder->groupEnd();
|
||||
$prefix = overridePrefix('', $db);
|
||||
|
||||
try {
|
||||
$builder = $db->table('information_schema.KEY_COLUMN_USAGE kcu');
|
||||
$builder->distinct();
|
||||
$builder->select('kcu.CONSTRAINT_NAME, kcu.TABLE_NAME, kcu.COLUMN_NAME, kcu.REFERENCED_TABLE_NAME, kcu.REFERENCED_COLUMN_NAME, kcu.ORDINAL_POSITION, rc.DELETE_RULE, rc.UPDATE_RULE');
|
||||
$builder->join(
|
||||
'(' . $scopedBuilder->getCompiledSelect() . ') matched',
|
||||
'matched.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND matched.TABLE_NAME = kcu.TABLE_NAME',
|
||||
'inner',
|
||||
false
|
||||
'information_schema.REFERENTIAL_CONSTRAINTS rc',
|
||||
'kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND kcu.TABLE_NAME = rc.TABLE_NAME',
|
||||
'left'
|
||||
);
|
||||
|
||||
if ($table !== null && $column !== null) {
|
||||
$scopedBuilder = $db->table('information_schema.KEY_COLUMN_USAGE scoped');
|
||||
$scopedBuilder->distinct();
|
||||
$scopedBuilder->select('scoped.CONSTRAINT_NAME, scoped.TABLE_NAME');
|
||||
$scopedBuilder->where('scoped.TABLE_SCHEMA', $db->database);
|
||||
$scopedBuilder->groupStart();
|
||||
$scopedBuilder->where('scoped.REFERENCED_TABLE_NAME', $prefixedTable);
|
||||
$scopedBuilder->where('scoped.REFERENCED_COLUMN_NAME', $column);
|
||||
$scopedBuilder->groupEnd();
|
||||
$scopedBuilder->orGroupStart();
|
||||
$scopedBuilder->where('scoped.TABLE_NAME', $prefixedTable);
|
||||
$scopedBuilder->where('scoped.COLUMN_NAME', $column);
|
||||
$scopedBuilder->groupEnd();
|
||||
|
||||
$builder->join(
|
||||
'(' . $scopedBuilder->getCompiledSelect() . ') matched',
|
||||
'matched.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME AND matched.TABLE_NAME = kcu.TABLE_NAME',
|
||||
'inner',
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$builder->where('kcu.TABLE_SCHEMA', $db->database);
|
||||
$builder->where('rc.CONSTRAINT_NAME IS NOT NULL', null, false);
|
||||
$builder->orderBy('kcu.CONSTRAINT_NAME');
|
||||
$builder->orderBy('kcu.ORDINAL_POSITION');
|
||||
|
||||
$result = $builder->get();
|
||||
} finally {
|
||||
overridePrefix($prefix, $db);
|
||||
}
|
||||
|
||||
$builder->where('kcu.TABLE_SCHEMA', $db->database);
|
||||
$builder->where('rc.CONSTRAINT_NAME IS NOT NULL', null, false);
|
||||
$builder->orderBy('kcu.CONSTRAINT_NAME');
|
||||
$builder->orderBy('kcu.ORDINAL_POSITION');
|
||||
|
||||
$result = $builder->get();
|
||||
overridePrefix($prefix);
|
||||
|
||||
if ($result === false) {
|
||||
$detail = 'unknown error';
|
||||
try {
|
||||
@@ -346,18 +350,20 @@ function foreignKeyExists(string $constraintName, string $tableName): bool {
|
||||
|
||||
$prefix = overridePrefix();
|
||||
|
||||
$db = Database::connect();
|
||||
$builder = $db->table('INFORMATION_SCHEMA.TABLE_CONSTRAINTS');
|
||||
$builder->select('CONSTRAINT_NAME');
|
||||
$builder->where('TABLE_SCHEMA', $db->database);
|
||||
$builder->where('TABLE_NAME', $prefix . $tableName);
|
||||
$builder->where('CONSTRAINT_TYPE', 'FOREIGN KEY');
|
||||
$builder->where('CONSTRAINT_NAME', $constraintName);
|
||||
$query = $builder->get();
|
||||
try {
|
||||
$db = Database::connect();
|
||||
$builder = $db->table('INFORMATION_SCHEMA.TABLE_CONSTRAINTS');
|
||||
$builder->select('CONSTRAINT_NAME');
|
||||
$builder->where('TABLE_SCHEMA', $db->database);
|
||||
$builder->where('TABLE_NAME', $prefix . $tableName);
|
||||
$builder->where('CONSTRAINT_TYPE', 'FOREIGN KEY');
|
||||
$builder->where('CONSTRAINT_NAME', $constraintName);
|
||||
$query = $builder->get();
|
||||
|
||||
overridePrefix($prefix);
|
||||
|
||||
return $query->getNumRows() > 0;
|
||||
return $query->getNumRows() > 0;
|
||||
} finally {
|
||||
overridePrefix($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,23 +377,26 @@ function dropColumnIfExists(string $table, string $column): void
|
||||
{
|
||||
$prefix = overridePrefix();
|
||||
|
||||
$db = Database::connect();
|
||||
$builder = $db->table('information_schema.COLUMNS');
|
||||
try {
|
||||
$db = Database::connect();
|
||||
$builder = $db->table('information_schema.COLUMNS');
|
||||
|
||||
// Check if the column exists in the table
|
||||
$builder->select('COLUMN_NAME')
|
||||
->where('TABLE_SCHEMA', $db->database)
|
||||
->where('TABLE_NAME', $prefix . $table)
|
||||
->where('COLUMN_NAME', $column);
|
||||
// Check if the column exists in the table
|
||||
$builder->select('COLUMN_NAME')
|
||||
->where('TABLE_SCHEMA', $db->database)
|
||||
->where('TABLE_NAME', $prefix . $table)
|
||||
->where('COLUMN_NAME', $column);
|
||||
|
||||
$query = $builder->get();
|
||||
$query = $builder->get();
|
||||
|
||||
if ($query->getNumRows() > 0)
|
||||
{
|
||||
// Drop the column if it exists
|
||||
$db->query("ALTER TABLE `" . $prefix . "$table` DROP COLUMN `$column`");
|
||||
if ($query->getNumRows() > 0)
|
||||
{
|
||||
// Drop the column if it exists
|
||||
$db->query("ALTER TABLE `" . $prefix . "$table` DROP COLUMN `$column`");
|
||||
}
|
||||
} finally {
|
||||
overridePrefix($prefix);
|
||||
}
|
||||
overridePrefix($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-11
@@ -25,27 +25,22 @@
|
||||
"matrix": "https://matrix.to/#/#opensourcepos_Lobby:gitter.im"
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"php": ">=8.2.35 <8.3 || >=8.3.36 <8.4 || >=8.4.27",
|
||||
"ext-intl": "*",
|
||||
"codeigniter4/framework": "4.7.4",
|
||||
"dompdf/dompdf": "^3.1.6",
|
||||
"ezyang/htmlpurifier": "^4.17",
|
||||
"laminas/laminas-escaper": "2.18.0",
|
||||
"ezyang/htmlpurifier": "^4.19",
|
||||
"openspout/openspout": "^4.28",
|
||||
"paragonie/random_compat": "^2.0.21",
|
||||
"picqer/php-barcode-generator": "^2.4.0",
|
||||
"setasign/tfpdf": "^1.34",
|
||||
"tamtamchik/namecase": "^3.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeigniter/coding-standard": "^1.8",
|
||||
"fakerphp/faker": "^1.23.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.47.1",
|
||||
"codeigniter/coding-standard": "^1.9",
|
||||
"friendsofphp/php-cs-fixer": "^3.95",
|
||||
"kint-php/kint": "^5.0.4",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"nexusphp/cs-config": "^3.6",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.2",
|
||||
"predis/predis": "^1.1 || ^2.0"
|
||||
"nexusphp/cs-config": "^3.29",
|
||||
"phpunit/phpunit": "^10.5.16 || ^11.2"
|
||||
},
|
||||
"replace": {
|
||||
"psr/log": "*"
|
||||
@@ -53,6 +48,7 @@
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Config\\": "app/Config/",
|
||||
"CodeIgniter\\": "vendor/codeigniter4/framework/system/"
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
|
||||
Generated
+312
-630
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1,6 +1,6 @@
|
||||
## Server Requirements
|
||||
|
||||
- PHP version `8.2` to `8.4` are supported, PHP version `≤ 8.1` is NOT supported. Please note that PHP needs to have the extensions `php-json`, `php-gd`, `php-bcmath`, `php-intl`, `php-openssl`, `php-mbstring`, `php-curl` and `php-xml` installed and enabled. An unstable master build can be downloaded in the releases section.
|
||||
- PHP version `8.2.35` to `8.4.27` are supported (minimum patch levels required for CVE-2026-109618 / CVE-2026-109619 security fixes). PHP version `≤ 8.1` is NOT supported. Please note that PHP needs to have the extensions `php-json`, `php-gd`, `php-bcmath`, `php-intl`, `php-openssl`, `php-mbstring`, `php-curl` and `php-xml` installed and enabled. An unstable master build can be downloaded in the releases section.
|
||||
- MySQL `5.7` is supported, also MariaDB replacement `10.x` is supported and might offer better performance.
|
||||
- Apache `2.4` is supported. Nginx should work fine too, see [wiki page here](https://github.com/opensourcepos/opensourcepos/wiki/Local-Deployment-using-LEMP).
|
||||
- Raspberry PI based installations proved to work, see [wiki page here](<https://github.com/opensourcepos/opensourcepos/wiki/Installing-on-Raspberry-PI---Orange-PI-(Headless-OSPOS)>).
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@opensourcepos/opensourcepos",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.4-dev",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@opensourcepos/opensourcepos",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.4-dev",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bootstrap": "^3.4.1",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opensourcepos/opensourcepos",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.4-dev",
|
||||
"description": "Open Source Point of Sale is a web based point of sale system written in the PHP language. It uses MySQL as the data storage back-end and has a simple user interface.",
|
||||
"keywords": [
|
||||
"point-of-sale",
|
||||
|
||||
@@ -7,9 +7,9 @@ use App\Models\Employee;
|
||||
use CodeIgniter\Config\Factories;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\OSPOS;
|
||||
use Config\Services;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
/**
|
||||
* Regression tests for the login validation flow in OSPOSRules::login_check().
|
||||
@@ -19,6 +19,8 @@ use PHPUnit\Framework\MockObject\MockObject;
|
||||
*/
|
||||
class OSPOSRulesTest extends CIUnitTestCase
|
||||
{
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Factories::reset();
|
||||
@@ -138,9 +140,7 @@ class OSPOSRulesTest extends CIUnitTestCase
|
||||
|
||||
private function injectSettings(array $settings): void
|
||||
{
|
||||
$ospos = new OSPOS();
|
||||
$ospos->settings = $settings;
|
||||
Factories::injectMock('config', OSPOS::class, $ospos);
|
||||
$this->injectOsposSettings($settings);
|
||||
}
|
||||
|
||||
private function injectRequest(): void
|
||||
|
||||
@@ -3,22 +3,23 @@
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use App\Models\Cashup;
|
||||
use CodeIgniter\Config\Factories;
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use CodeIgniter\Test\FeatureTestTrait;
|
||||
use Config\OSPOS;
|
||||
use ReflectionProperty;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
class CashupControllerTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
use EmployeeFixtureTrait;
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
@@ -26,34 +27,24 @@ class CashupControllerTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$ospos = new OSPOS();
|
||||
$ospos->settings = [
|
||||
$this->injectOsposSettings([
|
||||
'company' => 'Test Co',
|
||||
'dateformat' => 'Y-m-d',
|
||||
'timeformat' => 'H:i:s',
|
||||
'number_locale' => 'en_US',
|
||||
'currency_decimals' => 2,
|
||||
'thousands_separator' => ',',
|
||||
];
|
||||
Factories::injectMock('config', OSPOS::class, $ospos);
|
||||
]);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Factories::reset();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use CodeIgniter\Test\FeatureTestTrait;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Employee;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
class CustomersCsvImportTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -22,19 +23,12 @@ class CustomersCsvImportTest extends CIUnitTestCase
|
||||
protected Customer $customer;
|
||||
protected Employee $employee;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Reset the test database to a clean schema on the first test in this
|
||||
// class so leftover customers with the same emails from prior runs
|
||||
// cannot be rejected as duplicates by the import (check_email_exists).
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
// Reset any stale transaction state left on the shared in-process DB
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
@@ -12,11 +11,13 @@ use CodeIgniter\Config\Services;
|
||||
use App\Models\Employee;
|
||||
use App\Models\Module;
|
||||
use ReflectionProperty;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
|
||||
class EmployeesControllerTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
use EmployeeFixtureTrait;
|
||||
|
||||
@@ -27,20 +28,13 @@ class EmployeesControllerTest extends CIUnitTestCase
|
||||
|
||||
protected $priorDisallowGrantChange;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Reset the test database to a known clean schema on the first test in
|
||||
// this class so stale employees from prior runs (whose usernames are
|
||||
// unique-key bound and whose grant sets leak into these assertions)
|
||||
// cannot contaminate the assertions below.
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
// Reset any stale transaction state left on the shared in-process DB
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use CodeIgniter\Test\FeatureTestTrait;
|
||||
use App\Models\Employee;
|
||||
use RuntimeException;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
/**
|
||||
* Test suite for Home controller password validation
|
||||
@@ -19,6 +19,7 @@ use RuntimeException;
|
||||
class HomeTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -26,16 +27,9 @@ class HomeTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use CodeIgniter\Config\Factories;
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
@@ -11,14 +9,17 @@ use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use CodeIgniter\Test\FeatureTestTrait;
|
||||
use App\Models\Item;
|
||||
use App\Models\Item_kit;
|
||||
use Config\OSPOS;
|
||||
use Exception;
|
||||
use ReflectionProperty;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
class ItemKitsControllerTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
@@ -26,24 +27,16 @@ class ItemKitsControllerTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected Item $item;
|
||||
protected Item_kit $itemKit;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$ospos = new OSPOS();
|
||||
$ospos->settings = [
|
||||
$this->injectOsposSettings([
|
||||
'company' => 'Test Co',
|
||||
'barcode_content' => 'id',
|
||||
'barcode_type' => 'C128',
|
||||
@@ -59,8 +52,7 @@ class ItemKitsControllerTest extends CIUnitTestCase
|
||||
'barcode_page_cellspacing' => 1,
|
||||
'barcode_generate_if_empty' => 0,
|
||||
'barcode_formats' => 'null',
|
||||
];
|
||||
Factories::injectMock('config', OSPOS::class, $ospos);
|
||||
]);
|
||||
|
||||
$this->item = model(Item::class);
|
||||
$this->itemKit = model(Item_kit::class);
|
||||
@@ -68,7 +60,6 @@ class ItemKitsControllerTest extends CIUnitTestCase
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Factories::reset();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use CodeIgniter\Test\FeatureTestTrait;
|
||||
use App\Database\Seeds\TestDatabaseBootstrapSeeder;
|
||||
use App\Models\Employee;
|
||||
use Config\OSPOS;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
/**
|
||||
* Regression tests for the reports permission bypass
|
||||
@@ -24,6 +24,7 @@ use Config\OSPOS;
|
||||
class ReportsControllerTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -31,18 +32,12 @@ class ReportsControllerTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
/**
|
||||
* Set up test environment
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
TestDatabaseBootstrapSeeder::reset();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
@@ -12,6 +11,7 @@ use CodeIgniter\Config\Services;
|
||||
use App\Models\Employee;
|
||||
use Config\Database;
|
||||
use ReflectionProperty;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\ItemFixtureTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
use Tests\Support\SaleFixtureTrait;
|
||||
@@ -31,6 +31,7 @@ use Tests\Support\SaleFixtureTrait;
|
||||
class SalesControllerTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
use ItemFixtureTrait;
|
||||
use EmployeeFixtureTrait;
|
||||
@@ -42,16 +43,9 @@ class SalesControllerTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Controllers;
|
||||
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\HTTP\DownloadResponse;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
@@ -10,11 +9,13 @@ use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use CodeIgniter\Test\FeatureTestTrait;
|
||||
use App\Models\Tax;
|
||||
use ReflectionProperty;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
|
||||
class TaxesControllerTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use FeatureTestTrait;
|
||||
use EmployeeFixtureTrait;
|
||||
|
||||
@@ -24,16 +25,9 @@ class TaxesControllerTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static $doneBootstrap = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
namespace Tests\Helpers;
|
||||
|
||||
use CodeIgniter\Config\Factories;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\OSPOS;
|
||||
use stdClass;
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
class GetItemDataRowTest extends CIUnitTestCase
|
||||
{
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
@@ -20,8 +21,7 @@ class GetItemDataRowTest extends CIUnitTestCase
|
||||
|
||||
protected function injectSettings(array $overrides = []): void
|
||||
{
|
||||
$config = new OSPOS();
|
||||
$config->settings = array_merge([
|
||||
$this->injectOsposSettings(array_merge([
|
||||
'multi_pack_enabled' => 0,
|
||||
'use_destination_based_tax' => 0,
|
||||
'number_locale' => 'en_US',
|
||||
@@ -29,9 +29,7 @@ class GetItemDataRowTest extends CIUnitTestCase
|
||||
'quantity_decimals' => 0,
|
||||
'thousands_separator' => 1,
|
||||
'currency_symbol' => '$',
|
||||
], $overrides);
|
||||
|
||||
Factories::injectMock('config', OSPOS::class, $config);
|
||||
], $overrides));
|
||||
}
|
||||
|
||||
protected function makeItem(array $overrides = []): stdClass
|
||||
@@ -1,19 +1,20 @@
|
||||
<?php
|
||||
|
||||
use CodeIgniter\Config\Factories;
|
||||
namespace Tests\Helpers;
|
||||
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\OSPOS;
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
class LocaleHelperTest extends CIUnitTestCase
|
||||
{
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
require_once __DIR__ . '/../../app/Helpers/locale_helper.php';
|
||||
|
||||
$config = new OSPOS();
|
||||
$config->settings = ['dateformat' => 'Y-m-d'];
|
||||
Factories::injectMock('config', OSPOS::class, $config);
|
||||
$this->injectOsposSettings(['dateformat' => 'Y-m-d']);
|
||||
}
|
||||
|
||||
public function testValidDateReturnsTrue(): void
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class UrlHelperTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Include the url_helper.php file
|
||||
require_once __DIR__ . '/../../app/Helpers/url_helper.php';
|
||||
}
|
||||
|
||||
public function testBase64urlEncode(): void
|
||||
{
|
||||
$data = 'Test data';
|
||||
$encoded = base64url_encode($data);
|
||||
|
||||
// Assert that the encoded string is URL-safe
|
||||
$this->assertMatchesRegularExpression('/^[A-Za-z0-9\-_]+$/', $encoded);
|
||||
|
||||
// Assert that decoding the encoded string returns the original data
|
||||
$decoded = base64url_decode($encoded);
|
||||
$this->assertEquals($data, $decoded);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\helpers;
|
||||
namespace Tests\Helpers;
|
||||
|
||||
use CodeIgniter\Database\Exceptions\DatabaseException;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
@@ -1,10 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Helpers;
|
||||
|
||||
use App\Libraries\CI3SecretConverter;
|
||||
use App\Models\Appconfig;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\Encryption as EncryptionConfig;
|
||||
use Config\Services;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* The filesystem-touching helpers read their target paths from the shared
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -14,10 +14,12 @@ use App\Models\Sale;
|
||||
use App\Models\Stock_location;
|
||||
use CodeIgniter\Config\Factories;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use Config\OSPOS;
|
||||
use Tests\Support\OsposConfigFixtureTrait;
|
||||
|
||||
class Sale_libPaymentTest extends CIUnitTestCase
|
||||
{
|
||||
use OsposConfigFixtureTrait;
|
||||
|
||||
private Sale_lib $saleLib;
|
||||
|
||||
protected int $priorBcscale;
|
||||
@@ -35,15 +37,13 @@ class Sale_libPaymentTest extends CIUnitTestCase
|
||||
bcscale(0);
|
||||
|
||||
// Inject mock OSPOS config so Sale_lib constructor and helpers don't need real settings
|
||||
$ospos = new OSPOS();
|
||||
$ospos->settings = [
|
||||
$this->injectOsposSettings([
|
||||
'cash_rounding_code' => '',
|
||||
'cash_decimals' => 2,
|
||||
'currency_decimals' => 2,
|
||||
'tax_decimals' => 2,
|
||||
'quantity_decimals' => 2,
|
||||
];
|
||||
Factories::injectMock('config', OSPOS::class, $ospos);
|
||||
]);
|
||||
|
||||
// Inject stub models so model() calls in Sale_lib::__construct() skip DB
|
||||
$stubMethods = ['__construct'];
|
||||
|
||||
@@ -5,12 +5,13 @@ namespace Tests\Models;
|
||||
use App\Models\Appconfig;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Config\Database;
|
||||
use Config\OSPOS;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
class AppconfigTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
@@ -19,10 +20,11 @@ class AppconfigTest extends CIUnitTestCase
|
||||
protected $refresh = true;
|
||||
protected $namespace = null;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
protected function setUp(): void
|
||||
{
|
||||
$seeder = Database::seeder('tests');
|
||||
$seeder->call('TestDatabaseBootstrapSeeder');
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
private function appconfig(): Appconfig
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace Tests\Models;
|
||||
use App\Models\Customer;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Config\Database;
|
||||
use Tests\Support\ConcurrentDbRaceTrait;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
/**
|
||||
* Regression tests: adjustRewardPoints() must apply
|
||||
@@ -17,6 +17,7 @@ use Tests\Support\ConcurrentDbRaceTrait;
|
||||
class CustomerRewardPointsTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use ConcurrentDbRaceTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -24,14 +25,10 @@ class CustomerRewardPointsTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$seeder = Database::seeder('tests');
|
||||
$seeder->call('TestDatabaseBootstrapSeeder');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,20 +5,25 @@ namespace Tests\Models;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use App\Models\Employee;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
|
||||
class EmployeeTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use EmployeeFixtureTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
protected $seedOnce = true;
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace Tests\Models;
|
||||
use App\Models\Giftcard;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Config\Database;
|
||||
use Tests\Support\ConcurrentDbRaceTrait;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
/**
|
||||
* Regression tests: decrementGiftcardValue() must
|
||||
@@ -17,6 +17,7 @@ use Tests\Support\ConcurrentDbRaceTrait;
|
||||
class GiftcardTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use ConcurrentDbRaceTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -24,14 +25,10 @@ class GiftcardTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$seeder = Database::seeder('tests');
|
||||
$seeder->call('TestDatabaseBootstrapSeeder');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Tests\Models;
|
||||
use App\Models\Item;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
/**
|
||||
* Regression coverage for mass assignment in bulk edit.
|
||||
@@ -15,15 +16,13 @@ use CodeIgniter\Test\DatabaseTestTrait;
|
||||
class ItemBulkUpdateTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
|
||||
/**
|
||||
* The schema is taken as it stands rather than migrated, so these tests run
|
||||
* against an existing test database without dropping it. Every row created
|
||||
* here is rolled back in tearDown().
|
||||
*/
|
||||
protected $migrate = false;
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
protected $seedOnce = true;
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
protected Item $item;
|
||||
|
||||
@@ -35,6 +34,8 @@ class ItemBulkUpdateTest extends CIUnitTestCase
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->item = model(Item::class);
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace Tests\Models;
|
||||
use App\Models\Item_quantity;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Config\Database;
|
||||
use Tests\Support\ConcurrentDbRaceTrait;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\ItemFixtureTrait;
|
||||
|
||||
/**
|
||||
@@ -20,6 +20,7 @@ use Tests\Support\ItemFixtureTrait;
|
||||
class ItemQuantityTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use ConcurrentDbRaceTrait;
|
||||
use ItemFixtureTrait;
|
||||
|
||||
@@ -30,14 +31,10 @@ class ItemQuantityTest extends CIUnitTestCase
|
||||
|
||||
private const LOCATION_ID = 1;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$seeder = Database::seeder('tests');
|
||||
$seeder->call('TestDatabaseBootstrapSeeder');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@ namespace Tests\Models;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use App\Models\Item;
|
||||
use Config\Database;
|
||||
use Config\OSPOS;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\ItemSearchFixtureTrait;
|
||||
|
||||
class ItemSearchTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use ItemSearchFixtureTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -23,14 +24,10 @@ class ItemSearchTest extends CIUnitTestCase
|
||||
|
||||
protected $item;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$seeder = Database::seeder('tests');
|
||||
$seeder->call('TestDatabaseBootstrapSeeder');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->item = model(Item::class);
|
||||
|
||||
@@ -5,12 +5,13 @@ namespace Tests\Models;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use App\Models\Item_taxes;
|
||||
use Config\Database;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\ItemSearchFixtureTrait;
|
||||
|
||||
class ItemTaxesMultipleTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use ItemSearchFixtureTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
@@ -22,14 +23,10 @@ class ItemTaxesMultipleTest extends CIUnitTestCase
|
||||
|
||||
protected $item_taxes;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$seeder = Database::seeder('tests');
|
||||
$seeder->call('TestDatabaseBootstrapSeeder');
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->item_taxes = model(Item_taxes::class);
|
||||
|
||||
@@ -7,13 +7,16 @@ namespace Tests\Models\Reports;
|
||||
use App\Models\Reports\Summary_taxes;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
|
||||
class Summary_taxes_test extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
protected $seedOnce = true;
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
@@ -22,6 +25,8 @@ class Summary_taxes_test extends CIUnitTestCase
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
$this->seedTestData();
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace Tests\Models;
|
||||
|
||||
use App\Models\Sale;
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Tests\Support\DatabaseBootstrapTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
use Tests\Support\FailedQueryConnectionTrait;
|
||||
use Tests\Support\ItemFixtureTrait;
|
||||
@@ -18,6 +18,7 @@ use Tests\Support\ItemFixtureTrait;
|
||||
class SaleTest extends CIUnitTestCase
|
||||
{
|
||||
use DatabaseTestTrait;
|
||||
use DatabaseBootstrapTrait;
|
||||
use EmployeeFixtureTrait;
|
||||
use FailedQueryConnectionTrait;
|
||||
use ItemFixtureTrait;
|
||||
@@ -28,18 +29,11 @@ class SaleTest extends CIUnitTestCase
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
private const LOCATION_ID = 1;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
$this->resetDatabaseOnce();
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Support;
|
||||
|
||||
use App\Database\Seeds\TestDatabaseBootstrapSeeder;
|
||||
use CodeIgniter\Database\Config;
|
||||
|
||||
/**
|
||||
* Standard one-time-per-class database reset for DatabaseTestTrait tests.
|
||||
*
|
||||
* Call {@see self::resetDatabaseOnce()} as the first line of setUp(), before
|
||||
* parent::setUp(). It drops and re-migrates the `tests` schema exactly once
|
||||
* per test class (guarded by a per-class static, since PHP trait statics are
|
||||
* independent per using-class) and closes the shared connection afterward so
|
||||
* the migration run that follows reconnects against the freshly reset schema
|
||||
* instead of reusing a connection whose state predates the reset.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* use Tests\Support\DatabaseBootstrapTrait;
|
||||
*
|
||||
* class FooTest extends CIUnitTestCase
|
||||
* {
|
||||
* use DatabaseTestTrait;
|
||||
* use DatabaseBootstrapTrait;
|
||||
*
|
||||
* protected function setUp(): void
|
||||
* {
|
||||
* $this->resetDatabaseOnce();
|
||||
*
|
||||
* parent::setUp();
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
trait DatabaseBootstrapTrait
|
||||
{
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
protected function resetDatabaseOnce(): void
|
||||
{
|
||||
if (self::$doneBootstrap === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
TestDatabaseBootstrapSeeder::reset();
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Support;
|
||||
|
||||
use CodeIgniter\Config\Factories;
|
||||
use Config\OSPOS;
|
||||
|
||||
/**
|
||||
* Shared helper for injecting a mocked OSPOS config into a test.
|
||||
*
|
||||
* Replaces the old per-file `$ospos = new OSPOS(); $ospos->settings = [...];
|
||||
* Factories::injectMock(...)` block that was duplicated with slightly
|
||||
* different settings arrays across many test files. Each test supplies the
|
||||
* exact settings it depends on - OSPOS::getDefaultSettings() is private and
|
||||
* only has a handful of keys, so it is not a usable base to merge onto.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* use Tests\Support\OsposConfigFixtureTrait;
|
||||
*
|
||||
* class FooTest extends CIUnitTestCase
|
||||
* {
|
||||
* use OsposConfigFixtureTrait;
|
||||
*
|
||||
* protected function setUp(): void
|
||||
* {
|
||||
* parent::setUp();
|
||||
*
|
||||
* $this->injectOsposSettings([
|
||||
* 'invoice_enable' => false,
|
||||
* 'number_locale' => 'en_US',
|
||||
* ]);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
trait OsposConfigFixtureTrait
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $settings
|
||||
*/
|
||||
protected function injectOsposSettings(array $settings): OSPOS
|
||||
{
|
||||
$ospos = new OSPOS();
|
||||
$ospos->settings = $settings;
|
||||
|
||||
Factories::injectMock('config', OSPOS::class, $ospos);
|
||||
|
||||
return $ospos;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class UrlHelperTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
// Include the url_helper.php file
|
||||
require_once __DIR__ . '/../../app/Helpers/url_helper.php';
|
||||
}
|
||||
|
||||
public function testBase64urlEncode(): void
|
||||
{
|
||||
$data = 'Test data';
|
||||
$encoded = base64url_encode($data);
|
||||
|
||||
// Assert that the encoded string is URL-safe
|
||||
$this->assertMatchesRegularExpression('/^[A-Za-z0-9\-_]+$/', $encoded);
|
||||
|
||||
// Assert that decoding the encoded string returns the original data
|
||||
$decoded = base64url_decode($encoded);
|
||||
$this->assertEquals($data, $decoded);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user