diff --git a/tests/e2e/specs/graphiql.spec.js b/tests/e2e/specs/graphiql.spec.js index 8a9cf154b..82096445b 100644 --- a/tests/e2e/specs/graphiql.spec.js +++ b/tests/e2e/specs/graphiql.spec.js @@ -1,29 +1,96 @@ -import { - loginToWordPressAdmin, - openDrawer, - pasteVariables, - typeQuery, - typeVariables, - visitAdminFacingPage, - visitPublicFacingPage, - wpAdminUrl, - loadGraphiQL, -} from '../utils.js'; + import { test, expect } from '@playwright/test'; +export const wpAdminUrl = 'http://localhost:8888/wp-admin'; + const selectors = { graphiqlContainer: '.graphiql-container', graphiqlResponse: '.resultWrap', executeQueryButton: '.execute-button', queryInput: '[aria-label="Query Editor"] .CodeMirror', variablesInput: '[aria-label="Variables"] .CodeMirror', + loginUsername: '#user_login', + loginPassword: '#user_pass', + submitButton: '#wp-submit', }; -// Login to WordPress before each test -test.beforeEach( async ( { page } ) => { - // await loginToWordPressAdmin( page ); - // await page.evaluate(() => localStorage.clear()); -} ); +/** + * Types a GraphQL query into the CodeMirror editor. + * @param {import('@playwright/test').Page} page The Playwright page object. + * @param {string} query The GraphQL query to type. + */ +export async function typeQuery( page, query = '' ) { + + const selector = '.query-editor .cm-s-graphiql'; + + // Set the value + await page.evaluate( async ({ query, selector }) => { + const editor = document.querySelector(selector).CodeMirror; + await editor.setValue( query ); + }, { query, selector }); + + // Wait for the value to be set + await page.waitForTimeout( 500 ); +} + +export async function loadGraphiQL( page, queryParams = { query: null, variables: null, isQueryComposerOpen: null } ) { + + const { + query, + variables, + isQueryComposerOpen, + } = queryParams; + + let _queryParams = ''; + + if ( query ) { + _queryParams += `&query=${encodeURIComponent( query )}`; + } + + if ( variables ) { + _queryParams += `&variables=${encodeURIComponent( JSON.stringify( variables ) )}`; + } + + // _queryParams += `&isQueryComposerOpen=${isQueryComposerOpen ? "true" : "false" }` + + const url = wpAdminUrl + `/admin.php?page=graphiql-ide${_queryParams}`; + console.log( { url }) + await page.goto( + url, + { waitUntil: 'networkidle' } + ); + + const isLoggedIn = await page.locator( '#wpadminbar' ).isVisible(); + + if ( ! isLoggedIn ) { + console.log( `Logging in as admin` ) + await page.fill( selectors.loginUsername, 'admin' ); + await page.fill( selectors.loginPassword, 'password' ); + await page.click( selectors.submitButton ); + + } else { + console.log( `Already logged in as admin` ) + } + + await page.waitForLoadState( 'networkidle' ); + + const pageTitle = await page.title(); + + // if there's an error, go to the plugins page + if ( ! pageTitle.includes( 'GraphiQL' ) ) { + page.goto( wpAdminUrl + '/plugins.php' ) + } + + await page.waitForLoadState( 'networkidle' ); + + console.log( { + domContentLoaded: true, + title: await page.title(), + url: await page.url(), + }) + + +} test.describe('GraphiQL', () => { @@ -40,83 +107,83 @@ test.describe('GraphiQL', () => { }); - // test('it renders errors when errors are expected', async ({ page }) => { - // await loadGraphiQL( page ); - // await typeQuery( page, `{nonExistentFieldThatShouldError}` ); - // await page.click( selectors.executeQueryButton ); - // await page.waitForLoadState('networkidle'); - // const response = await page.locator( selectors.graphiqlResponse ); - // await expect( response ).toContainText( 'errors' ); - // }); - // - // test('it loads with custom query from url query params', async ({ page }) => { - // - // // Generate a unique alias to use in the query param - // // and test that it is present in the query editor - // // when it loads - // const alias = 'alias' + Math.random().toString(36).substring(7); - // - // await loadGraphiQL( page, { query: `query TestFromUri { posts { nodes { id ${alias}:title } } }`} ); - // await page.waitForLoadState('networkidle'); - // const editor = await page.locator( selectors.graphiqlContainer ); - // await expect( editor ).toContainText( 'TestFromUri' ); - // await expect( editor ).toContainText( 'posts' ); - // await expect( editor ).toContainText( 'nodes' ); - // await expect( editor ).toContainText( 'id' ); - // await expect( editor ).toContainText( alias ); - // }); - // - // test('it loads with the query composer hidden by default', async ({ page }) => { - // await loadGraphiQL( page, { query: `{posts{nodes{id}}}`} ); - // const queryComposer = await page.locator( '.query-composer-wrap' ); - // await expect( queryComposer ).not.toBeVisible(); - // }); - // - // test.skip('it loads with query composer open if queryParam says to', async ({ page }) => { - // await loadGraphiQL( page, { query: `{posts{nodes{id}}}`, isQueryComposerOpen: "true" } ); - // const queryComposer = await page.locator( '.query-composer-wrap' ); - // await expect( queryComposer ).toBeVisible(); - // }); - // - // test('opens query composer on click', async ({ page }) => { - // await loadGraphiQL( page ); - // const button = page.locator( "xpath=//button[contains(text(), 'Query Composer')]" ); - // const queryComposer = await page.locator( '.query-composer-wrap' ); - // - // // composer should be closed by default - // await expect( queryComposer ).not.toBeVisible(); - // - // // clicking the button should open it - // await button.click(); - // await page.waitForTimeout( 1000 ); - // await expect( queryComposer ).toBeVisible(); - // - // // clicking again should close it - // await button.click(); - // await page.waitForTimeout( 1000 ); - // await expect( queryComposer ).not.toBeVisible(); - // }); - // - // - // test('documentation explorer can be toggled open and closed', async ({ page }) => { - // await loadGraphiQL( page ); - // const openButton = page.locator( "button.docExplorerShow" ); - // const docExplorerWrap = await page.locator( '.doc-explorer' ); - // - // // docs should be closed by default - // await expect( docExplorerWrap ).not.toBeVisible(); - // - // // clicking the openButton should open it - // await openButton.click(); - // await page.waitForTimeout( 1000 ); - // await expect( docExplorerWrap ).toBeVisible(); - // - // // clicking the close button should close it - // const closeButton = page.locator( "button.docExplorerHide" ); - // await closeButton.click(); - // await page.waitForTimeout( 1000 ); - // await expect( docExplorerWrap ).not.toBeVisible(); - // }); + test('it renders errors when errors are expected', async ({ page }) => { + await loadGraphiQL( page ); + await typeQuery( page, `{nonExistentFieldThatShouldError}` ); + await page.click( selectors.executeQueryButton ); + await page.waitForLoadState('networkidle'); + const response = await page.locator( selectors.graphiqlResponse ); + await expect( response ).toContainText( 'errors' ); + }); + + test('it loads with custom query from url query params', async ({ page }) => { + + // Generate a unique alias to use in the query param + // and test that it is present in the query editor + // when it loads + const alias = 'alias' + Math.random().toString(36).substring(7); + + await loadGraphiQL( page, { query: `query TestFromUri { posts { nodes { id ${alias}:title } } }`} ); + await page.waitForLoadState('networkidle'); + const editor = await page.locator( selectors.graphiqlContainer ); + await expect( editor ).toContainText( 'TestFromUri' ); + await expect( editor ).toContainText( 'posts' ); + await expect( editor ).toContainText( 'nodes' ); + await expect( editor ).toContainText( 'id' ); + await expect( editor ).toContainText( alias ); + }); + + test('it loads with the query composer hidden by default', async ({ page }) => { + await loadGraphiQL( page, { query: `{posts{nodes{id}}}`} ); + const queryComposer = await page.locator( '.query-composer-wrap' ); + await expect( queryComposer ).not.toBeVisible(); + }); + + test.skip('it loads with query composer open if queryParam says to', async ({ page }) => { + await loadGraphiQL( page, { query: `{posts{nodes{id}}}`, isQueryComposerOpen: "true" } ); + const queryComposer = await page.locator( '.query-composer-wrap' ); + await expect( queryComposer ).toBeVisible(); + }); + + test('opens query composer on click', async ({ page }) => { + await loadGraphiQL( page ); + const button = page.locator( "xpath=//button[contains(text(), 'Query Composer')]" ); + const queryComposer = await page.locator( '.query-composer-wrap' ); + + // composer should be closed by default + await expect( queryComposer ).not.toBeVisible(); + + // clicking the button should open it + await button.click(); + await page.waitForTimeout( 1000 ); + await expect( queryComposer ).toBeVisible(); + + // clicking again should close it + await button.click(); + await page.waitForTimeout( 1000 ); + await expect( queryComposer ).not.toBeVisible(); + }); + + + test('documentation explorer can be toggled open and closed', async ({ page }) => { + await loadGraphiQL( page ); + const openButton = page.locator( "button.docExplorerShow" ); + const docExplorerWrap = await page.locator( '.doc-explorer' ); + + // docs should be closed by default + await expect( docExplorerWrap ).not.toBeVisible(); + + // clicking the openButton should open it + await openButton.click(); + await page.waitForTimeout( 1000 ); + await expect( docExplorerWrap ).toBeVisible(); + + // clicking the close button should close it + const closeButton = page.locator( "button.docExplorerHide" ); + await closeButton.click(); + await page.waitForTimeout( 1000 ); + await expect( docExplorerWrap ).not.toBeVisible(); + }); });