phpunit.xml
Rama main · réplica de lectura del repositorio original.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="tests/bootstrap.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory>tests/Feature</directory>
</testsuite>
</testsuites>
<extensions>
<!-- N+1 queries: the end-of-run report, the baseline's ratchet and its writer.
See tests/Support/QueryGuard.php. -->
<bootstrap class="Tests\Support\QueryGuardExtension"/>
</extensions>
<source>
<include>
<directory>app</directory>
</include>
</source>
<php>
<ini name="memory_limit" value="1G"/>
<!--
CI runs a stock php.ini, where pcre.jit is PHP's default of 1 and the JIT stack is 32KB.
A developer machine may ship 0, which tolerates a scan span roughly three times larger
before preg_match() gives up - and it does not give up by returning 0, it returns FALSE,
which `if (! preg_match(...))` reads as "no match". So an unsound pattern over a rendered
page reports the PAGE as wrong, only on CI, for every value the caller was checking.
FederationSettingsCardTest lost two rounds of debugging to exactly that gap. Pinning the
setting is what makes such a pattern fail on the machine that wrote it.
Deliberately pinned to CI's value and not to 0: 0 would turn the build green by hiding
the pattern instead of failing it, and would leave the same cliff for the next page that
grows. See tests/TestCase.php::pregMatchOrFail().
-->
<ini name="pcre.jit" value="1"/>
<env name="APP_ENV" value="testing"/>
<!--
.env.example ships APP_URL empty and CI copies it verbatim, so config('app.url') was ''
there while a developer's .env carries a real one. That one difference decides the host
every $this->get('/path') reaches: SetRequestForConsole synthesizes the request from
APP_URL at bootstrap, and MakesHttpRequests::prepareUrlForRequest() is trim(url($uri), '/').
A test that then pins config(['app.url' => ...]) moves _base_domain() WITHOUT moving that
host, and with IS_HOSTED=true ResolveCustomDomain reads the mismatch as an unknown custom
domain and aborts 404 before the session middleware runs - which is how 18 tests passed
locally and failed on CI. Pinning it here makes the two agree on every machine.
Forced, and mirrored into $_SERVER by tests/bootstrap.php, so neither .env nor an exported
shell variable can reintroduce the split. tests/TestCase.php::pinAppUrl() is how a test
moves it deliberately.
-->
<env name="APP_URL" value="https://eventschedule.test" force="true"/>
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_STORE" value="array"/>
<!-- The backups disk must resolve to its local default under test; a developer .env
that points it at object storage would otherwise fail BackupStorageTest. -->
<env name="BACKUP_DISK_DRIVER" value="local" force="true"/>
<env name="DB_CONNECTION" value="mysql"/>
<env name="DB_DATABASE" value="eventschedule_test" force="true"/>
<env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<!--
Pinned because ArraySessionHandler::read() expires entries against session.lifetime
using Carbon::now(), so travel() can expire the session ITSELF. A test that travels
past this would pass because the session vanished rather than because the thing it
asserts fired. Left at the old 120 so the window stays generous relative to the
seconds-scale travel in AdminReauthTimeoutTest, and so the test env does not inherit
whatever a developer's .env says.
-->
<env name="SESSION_LIFETIME" value="120" force="true"/>
<!--
Placeholder keys, never real ones. .env.example ships STRIPE_PLATFORM_SECRET blank and
omits STRIPE_KEY entirely, so on CI they resolve to '' and null - and the Stripe SDK
validates the key in its constructor, so every `new StripeClient(config(...))` in the
app throws before the test reaches an assertion. Pinning here keeps CI and local
identical, and stops a developer's real key from ever backing a test client.
Forced so an exported shell var cannot reintroduce either failure.
Keep the two values distinct: InstallmentChargeSettlementTest tells the Connect rail
from the platform rail by comparing them.
-->
<env name="STRIPE_KEY" value="sk_test_fake_connect" force="true"/>
<env name="STRIPE_PLATFORM_SECRET" value="sk_test_fake_platform" force="true"/>
<!--
The platform's publishable key is cashier.key, which the event form reads to offer
"Save and start free trial" in place of the plain upgrade link. .env.example ships it
empty, so CI never drew that button while a developer with a key set always did, and
EventTicketPanelAccessTest passed on one and failed on the other. A test that wants the
button sets config(['cashier.key' => ...]) itself.
-->
<env name="STRIPE_PLATFORM_KEY" value="" force="true"/>
<!--
Same reasoning as the Stripe keys above, for the installation-wide Payfast account and the
default payment method. These are documented for operators to set, so a developer who
follows our own selfhost guide would otherwise have their .env silently change what the
suite tests: with them populated, Payfast becomes a connected gateway for every user and
seven tests fail, several of which have nothing to do with Payfast.
force="true" covers getenv() and $_ENV but NOT $_SERVER, which Laravel's Env reads first -
see tests/bootstrap.php, which mirrors these across so an exported shell variable cannot
outrank a pin here. The same caveat applies to the Stripe keys above.
-->
<env name="PAYFAST_MERCHANT_ID" value="" force="true"/>
<env name="PAYFAST_MERCHANT_KEY" value="" force="true"/>
<env name="PAYFAST_PASSPHRASE" value="" force="true"/>
<!--
And the same again for PayPal, which matters more than Payfast's did: PayPal settles USD,
so an operator's populated keys would make it a connected gateway for EVERY user in the
suite's default currency. PaymentMethodEventFormTest nulls Stripe out by hand and then
asserts an exact list of what is left, and one of its cases asserts that a USD event with
no usable gateway warns the owner - a live PayPal would silently delete the warning that
test exists to pin.
-->
<env name="PAYPAL_CLIENT_ID" value="" force="true"/>
<env name="PAYPAL_CLIENT_SECRET" value="" force="true"/>
<env name="PAYPAL_WEBHOOK_ID" value="" force="true"/>
<env name="RAZORPAY_KEY_ID" value="" force="true"/>
<env name="RAZORPAY_KEY_SECRET" value="" force="true"/>
<env name="RAZORPAY_WEBHOOK_SECRET" value="" force="true"/>
<env name="DEFAULT_PAYMENT_METHOD" value="" force="true"/>
<!-- The homepage poster wall renders straight from the database under test. The `array`
cache store survives RefreshDatabase within a process, so a cached wall would
otherwise render against the next test's wiped database. ImageVariantsTest turns the
TTL back on for the two tests that exercise the cache itself. -->
<env name="MARKETING_WALL_CACHE_SECONDS" value="0" force="true"/>
<!-- The operator's real growth-data token lives in their .env (app:pull-growth reads it
there), and tests load .env. Pinned empty so it can never back a test request: the
endpoint tests set their own. -->
<env name="GROWTH_DATA_TOKEN" value="" force="true"/>
<!-- The venue map's address search and tile server (config services.map). The operator's
own may be set in their .env, and with the search live every test that draws a map
would send a venue fixture's address to a real, rate-limited service. Empty is also
what switches the venue map off, so a test that wants one sets
config(['services.map.geocoder_url' => ...]) together with Http::fake(). -->
<env name="MAP_GEOCODER_URL" value="" force="true"/>
<env name="MAP_TILE_URL" value="" force="true"/>
<!-- The operator's real Google backend key lives in their .env, and Role's saving hook
geocodes any schedule that has an address whenever one is configured. With it live,
every fixture that sets a city or a street made a real, BILLED request to the
Geocoding API - a few hundred per run of the suite, on a machine that runs it all
day. CI never had a key, so this only makes a local run match it. A test that needs
the geocode branch sets its own key AND Http::fake(). -->
<env name="BACKEND_GOOGLE_KEY" value="" force="true"/>
<!-- The suite loads the developer's .env, and on the machine that deploys the hosted
install that file holds the real DigitalOcean token and app id. With them set,
DigitalOceanService::isConfigured() is true in every test: the admin Domains page
read the PRODUCTION app from their API on each run of its test, and a test that
saves a direct-mode custom domain is one fake short of rewriting that app's spec.
CI never had them. A test that needs the service sets its own token together with
Http::fake(), as CustomDomainProvisioningTest does. -->
<env name="DO_API_TOKEN" value="" force="true"/>
<env name="DO_APP_ID" value="" force="true"/>
<!-- The same for Meta. The deploying machine's .env holds the platform's real Meta token, ad
account and Page: unpinned, a boost test that missed the fake would have created a
real campaign on the platform's card, and a boost partner's partner share runs with
that same token. A test that needs the real service sets its own values together
with Http::fake(); MetaAdsService falls back to MetaAdsServiceFake without a token. -->
<env name="META_ACCESS_TOKEN" value="" force="true"/>
<env name="META_AD_ACCOUNT_ID" value="" force="true"/>
<env name="META_PAGE_ID" value="" force="true"/>
<env name="META_BUSINESS_ID" value="" force="true"/>
<env name="META_SYSTEM_USER_ID" value="" force="true"/>
<env name="META_LOGIN_CONFIG_ID" value="" force="true"/>
<!-- The same for the AI key. With a developer's real GEMINI_API_KEY in .env, every page
that offers AI import drew its form here and not on CI, so a test could pass on one
and fail on the other for that alone (CustomFieldEventPageTest did), and a test one
Http::fake() short of the parser would spend real, billed requests on fixtures. CI
never had a key. A test that needs the AI branch sets
config('services.google.gemini_key') itself, with Http::fake() where anything is
asked. -->
<env name="GEMINI_API_KEY" value="" force="true"/>
<!-- The same for Search Console: a developer's .env holds a service account that reads the
real site's search data. A test that needs the client sets its own key with
Http::fake(), as SearchConsoleTest does. -->
<env name="SEARCH_CONSOLE_CREDENTIALS" value="" force="true"/>
<!-- And for Apple Wallet: a developer's .env may hold the real Pass Type ID certificate, and
with it every ticket page here would draw the badge it does not draw on CI. A test that
needs the pass sets its own certificate (AppleWalletPassTest makes one). -->
<env name="APPLE_WALLET_PASS_TYPE_ID" value="" force="true"/>
<env name="APPLE_WALLET_TEAM_ID" value="" force="true"/>
<env name="APPLE_WALLET_CERTIFICATE" value="" force="true"/>
<!-- Hosted admins must use two-factor authentication (auth.admin_requires_two_factor).
Off here so admin tests need no 2FA fixture; AdminTwoFactorRequiredTest turns it on. -->
<env name="ADMIN_REQUIRE_2FA" value="false" force="true"/>
<env name="TELESCOPE_ENABLED" value="false"/>
<env name="APP_TESTING" value="true"/>
<env name="IS_NEXUS" value="true"/>
<env name="LANG_OVERRIDES_PATH" value="storage/framework/testing/lang"/>
</php>
</phpunit>