Skip to content

15B: Scenario suite — every conflict policy, end to end - #29

Open
nikolaystrikhar wants to merge 1 commit into
15A-scenario-loadfrom
15B-scenario-conflict
Open

15B: Scenario suite — every conflict policy, end to end#29
nikolaystrikhar wants to merge 1 commit into
15A-scenario-loadfrom
15B-scenario-conflict

Conversation

@nikolaystrikhar

Copy link
Copy Markdown
Contributor

What: seven scenarios that put a real basename into the real active_plugins option and drive the conflict step at plugins_loaded priority 5 through every branch it has — DEACTIVATE, NOTICE_ONLY, DEFER, the capability gate, the merge notice rendering and clearing on all_admin_notices, the request after a deactivation, and the re-activation screen through core's own wp_admin_notice_markup dispatch.

Usage: a policy scenario, asserting what WordPress holds afterwards rather than what a stub remembers.

update_option( 'active_plugins', [ self::STANDALONE ] );

$this->register( [ 'standalone_plugin_basename' => self::STANDALONE ] );

$this->boot();
$location = $this->run_halted_request();

$this->assertNotContains( self::STANDALONE, $this->active_plugins() );
$this->assertSame( admin_url( 'plugins.php' ), $location );

Why this way:

Core's own deactivate_plugins() does the deactivating. Nothing here doubles the plugin state, so what is asserted is the option WordPress really holds rather than a stub's recollection of having been called — which is the only way the network-aware branch and the silent-deactivation argument get exercised at all.

Two of them run a second request. That is the only way to cover what this library is for: a merge takes one request to resolve and the next one to load. The second request is also where a redirect loop would show, and it is asserted not to halt rather than described as not looping.

The capability gate gets a scenario from both sides. A subscriber resolves nothing and consumes nothing — the standalone is still there to detect on the next request, from someone who can act on it. Without that second half the test would pass just as well if the gate had quietly eaten the notice.

The destination is asserted, not merely the redirect. Conflict\Redirector reads the current request URI, so the scenario pins $_SERVER['REQUEST_URI'] in setUp and restores it in tearDown. Left to whatever the previous test wrote, the assertion that the user lands on plugins.php was right by accident.

The re-activation screen goes through core's filter dispatch, not through Conflict\Rewriter. The admin-only add_filter() is half of what has to work: a filter that never wired leaves core's "triggered a fatal error" — true, and useless — on the one screen least able to afford it.

Seven scenarios that put a real basename into the real active_plugins option and
let core's own deactivate_plugins() be what turns it off, so what is asserted is
the option WordPress actually holds rather than a stub's recollection of being
called. DEACTIVATE deactivates, queues the merge notice and redirects to an
asserted destination; NOTICE_ONLY talks without acting; DEFER stands aside with
the standalone's own guard constant already defined, which is the state
wp-settings.php really leaves the request in.

Two of them run a second request, because that is the only way to cover what
this library is for: the merge takes one request to resolve and the next one to
load. The second request is also where a redirect loop would show, and it is
asserted not to halt rather than described as not looping.

The capability gate gets a scenario of its own, from both sides. A subscriber
resolves nothing and consumes nothing -- the standalone is still there to detect
on the next request, from someone who can act on it, which is the half that
would pass just as well if the gate had eaten the notice.

The reactivation scenario drives the wp_admin_notice_markup filter through core's
own dispatch rather than calling the rewriter, because the admin-only add_filter()
is half of what has to work: a filter that never wired leaves core's useless
sentence on the one screen least able to afford it.

Each case is written up in tests/README with a mermaid diagram of its flow,
including the policy branch the conflict step takes and the order the two gates
are asked in.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant