@@ -12,22 +12,112 @@ test.describe( 'Query Monitor plugin', () => {
1212 expect ( plugin . status ) . toBe ( 'inactive' ) ;
1313 }
1414
15- test . beforeEach ( async ( { requestUtils } ) => {
15+ test . beforeEach ( async ( { requestUtils } ) => {
1616 await deactivateQueryMonitor ( requestUtils ) ;
1717 } ) ;
1818
19- test . afterEach ( async ( { requestUtils } ) => {
19+ test . afterEach ( async ( { requestUtils } ) => {
2020 await deactivateQueryMonitor ( requestUtils ) ;
2121 } ) ;
2222
23- test ( 'should activate' , async ( { admin, page } ) => {
23+ test ( 'should activate and show SQLite queries (QM 4.0+) ' , async ( { admin, page } ) => {
2424 // Activate the Query Monitor plugin on the plugins page.
2525 await admin . visitAdminPage ( '/plugins.php' ) ;
2626 await page . getByLabel ( 'Activate Query Monitor' , { exact : true } ) . click ( ) ;
2727 await page . getByText ( 'Plugin activated.' , { exact : true } ) . waitFor ( ) ;
2828
29+ // Skip this test if QM 4.0+ is not active (no shadow DOM container).
30+ const hasContainer = await page . locator ( '#query-monitor-container' ) . count ( ) ;
31+ test . skip ( hasContainer === 0 , 'QM 4.0+ not detected' ) ;
32+
33+ // Click on the Query Monitor admin bar item.
34+ // QM 4.0 re-renders the admin bar with Preact — use the ab-item class.
35+ await page . locator ( '#wp-admin-bar-query-monitor > a.ab-item' ) . click ( ) ;
36+
37+ // Wait for the QM panel to render inside the shadow DOM.
38+ const container = page . locator ( '#query-monitor-container' ) ;
39+ await expect ( async ( ) => {
40+ const hasShadow = await container . evaluate (
41+ ( el ) => el . shadowRoot !== null
42+ ) ;
43+ expect ( hasShadow ) . toBe ( true ) ;
44+ } ) . toPass ( ) ;
45+
46+ // Click on the Database Queries tab inside the shadow DOM.
47+ // QM 4.0 renders nav items as <button role="tab">.
48+ await expect ( async ( ) => {
49+ await container . evaluate ( ( el ) => {
50+ const shadow = el . shadowRoot ;
51+ const tabs = shadow . querySelectorAll ( 'button[role="tab"]' ) ;
52+ for ( const tab of tabs ) {
53+ if ( tab . textContent . includes ( 'Database Queries' ) ) {
54+ tab . click ( ) ;
55+ return ;
56+ }
57+ }
58+ throw new Error ( 'Database Queries tab not found' ) ;
59+ } ) ;
60+ } ) . toPass ( ) ;
61+
62+ // Verify the first logged query is visible in the shadow DOM.
63+ await expect ( async ( ) => {
64+ const hasSqlQuery = await container . evaluate ( ( el ) => {
65+ const shadow = el . shadowRoot ;
66+ const codeCells = shadow . querySelectorAll ( 'td code' ) ;
67+ for ( const cell of codeCells ) {
68+ if ( cell . textContent . includes ( 'SELECT option_name, option_value' ) ) {
69+ return true ;
70+ }
71+ }
72+ return false ;
73+ } ) ;
74+ expect ( hasSqlQuery ) . toBe ( true ) ;
75+ } ) . toPass ( ) ;
76+
77+ // Click the SQLite <details> summary for the first query row.
78+ // The element is injected by a debounced MutationObserver, so retry.
79+ await expect ( async ( ) => {
80+ await container . evaluate ( ( el ) => {
81+ const shadow = el . shadowRoot ;
82+ const summary = shadow . querySelector ( 'details.qm-sqlite summary' ) ;
83+ if ( ! summary ) {
84+ throw new Error ( 'SQLite details summary not found' ) ;
85+ }
86+ summary . click ( ) ;
87+ } ) ;
88+ } ) . toPass ( ) ;
89+
90+ // Verify the SQLite query is displayed.
91+ await expect ( async ( ) => {
92+ const hasSqliteQuery = await container . evaluate ( ( el ) => {
93+ const shadow = el . shadowRoot ;
94+ const sqliteQueries = shadow . querySelectorAll ( '.qm-sqlite-query' ) ;
95+ for ( const query of sqliteQueries ) {
96+ if (
97+ query . textContent . includes ( 'SELECT' ) &&
98+ query . textContent . includes ( 'option_name' )
99+ ) {
100+ return true ;
101+ }
102+ }
103+ return false ;
104+ } ) ;
105+ expect ( hasSqliteQuery ) . toBe ( true ) ;
106+ } ) . toPass ( ) ;
107+ } ) ;
108+
109+ test ( 'should activate and show SQLite queries (QM 3.x)' , async ( { admin, page } ) => {
110+ // Activate the Query Monitor plugin on the plugins page.
111+ await admin . visitAdminPage ( '/plugins.php' ) ;
112+ await page . getByLabel ( 'Activate Query Monitor' , { exact : true } ) . click ( ) ;
113+ await page . getByText ( 'Plugin activated.' , { exact : true } ) . waitFor ( ) ;
114+
115+ // Skip this test if QM 3.x is not active (has shadow DOM container = QM 4.0+).
116+ const hasContainer = await page . locator ( '#query-monitor-container' ) . count ( ) ;
117+ test . skip ( hasContainer > 0 , 'QM 3.x not detected' ) ;
118+
29119 // Click on the Query Monitor menu item in the WordPress admin bar.
30- await page . locator ( 'a[role="menuitem"][href="#qm-overview"][aria-expanded="false"]' ) . click ( ) ;
120+ await page . locator ( '#wp-admin-bar-query-monitor > a' ) . click ( ) ;
31121
32122 // Wait for the Query Monitor panel to open.
33123 await page . locator ( '#query-monitor-main' ) . waitFor ( ) ;
@@ -42,6 +132,13 @@ test.describe( 'Query Monitor plugin', () => {
42132
43133 // Check that the query is logged with SQLite information.
44134 await sqlCell . getByLabel ( 'Toggle SQLite queries' ) . click ( ) ;
45- expect ( page . locator ( '.qm-sqlite-query' , { hasText : 'SELECT `option_name` , `option_value` FROM `wp_options`' } ) . first ( ) ) . toBeVisible ( ) ;
135+ await expect (
136+ page
137+ . locator ( '.qm-sqlite-query' , {
138+ hasText :
139+ 'SELECT `option_name` , `option_value` FROM `wp_options`' ,
140+ } )
141+ . first ( )
142+ ) . toBeVisible ( ) ;
46143 } ) ;
47144} ) ;
0 commit comments