Skip to content

Commit

Permalink
Merge pull request #139 from wp-graphql/ci/test-toolbar-buttons
Browse files Browse the repository at this point in the history
ci: add e2e ests for editor toolbar buttons
  • Loading branch information
josephfusco authored May 17, 2024
2 parents 1f85f70 + 2e15e53 commit a7d710d
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 85 deletions.
16 changes: 8 additions & 8 deletions ACTIONS_AND_FILTERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@

-> [Original documentation](https://www.wpgraphql.com/docs/customizing-wpgraphiql)

_legend_ 🎉 = new functionality

## PHP Actions

- `wpgraphqlide_enqueue_script` ([enqueue_graphiql_extension](https://www.wpgraphql.com/docs/customizing-wpgraphiql#enqueue_graphiql_extension))

## PHP Filters

- `wpgraphqlide_capability_required` 🎉
- `wpgraphqlide_context` 🎉
- `wpgraphqlide_capability_required`
- `wpgraphqlide_context`
- `wpgraphqlide_external_fragments` ([graphiql_external_fragments](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_external_fragments))
- `wpgraphqlide_drawer_button_label`
- `wpgraphqlide_drawer_button_loading_label`

## JavaScript Actions

- `wpgraphqlide_destroyed` 🎉
- `wpgraphqlide_destroyed`
- `wpgraphqlide_rendered` ([graphiql_rendered](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_rendered))

## JavaScript Filters

- `wpgraphqlide_toolbar_buttons` ([graphiql_toolbar_buttons](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_toolbar_buttons))
TBD

## Legacy Hooks

Not all actions/filters were ported over from the legacy WPGraphQL IDE.

- `graphiql_toolbar_before_buttons`
- `graphiql_toolbar_after_buttons`
- [`graphiql_toolbar_before_buttons`](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_toolbar_before_buttons)
- [`graphiql_toolbar_after_buttons`](https://www.wpgraphql.com/docs/customizing-wpgraphiql#graphiql_toolbar_before_buttons)
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

257 changes: 257 additions & 0 deletions tests/e2e/specs/editor-toolbar-buttons.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
import { describe, test, beforeEach } from '@playwright/test';
import {
getCodeMirrorValue,
getQueryFromLocalStorage,
loginToWordPressAdmin,
openDrawer,
setQueryInLocalStorage,
typeQuery
} from "../utils";
import { expect } from '@playwright/test';

export const selectors = {
graphiqlContainer: '.graphiql-container',
graphiqlResponse: '.graphiql-response',
editorDrawerButton: '.EditorDrawerButton',
editorDrawerCloseButton: '.EditorDrawerCloseButton',
executeQueryButton: '.graphiql-execute-button',
queryInput: '[aria-label="Query Editor"] .CodeMirror',
variablesInput: '[aria-label="Variables"] .CodeMirror',
prettifyButton: '.graphiql-prettify-button',
authButton: '.graphiql-toggle-auth-button',
};

// Login to WordPress before each test
beforeEach(async ({ page, context }) => {
await loginToWordPressAdmin(page);
await context.grantPermissions(['clipboard-read', 'clipboard-write']);
});

async function openGraphiQL(page) {
await expect(page.locator(selectors.graphiqlContainer)).toBeHidden();
await openDrawer(page);
}

describe('Toolbar Buttons', () => {

beforeEach(async ({ page }) => {
await openGraphiQL(page);
});

test('Clicking the Execute button executes a query', async ({ page }) => {
await typeQuery(page, 'query { posts { nodes { title } } }');
const response = page.locator(selectors.graphiqlResponse);
await expect(response).not.toContainText('posts');
await page.click(selectors.executeQueryButton);
await expect(response).toContainText('posts');
await expect(response).toContainText('nodes');
});

describe('Auth button', () => {

beforeEach(async ({ page }) => {
await typeQuery(page, 'query { viewer { name } }');
});

test('Default state is authenticated', async ({ page }) => {
// const authButton = page.locator(selectors.authButton);

// select the 2nd button in the .graphiql-toolbar
const authButton = await page.locator( `.graphiql-toolbar button:nth-child(2)` )
await expect(authButton).not.toHaveClass(/is-public/);
await expect(authButton).toHaveClass(/is-authenticated/);
});

test('Private data is returned when authenticated', async ({ page }) => {
const response = page.locator(selectors.graphiqlResponse);
await expect(response).not.toContainText('viewer');
await expect(response).not.toContainText('admin');
await page.click(selectors.executeQueryButton);
await expect(response).toContainText('viewer');
await expect(response).toContainText('admin');
});

test('Auth button is not grayscale when authenticated', async ({ page }) => {
// const authButton = page.locator(selectors.authButton);
const authButton = await page.locator( `.graphiql-toolbar button:nth-child(2)` );
const filterValue = await authButton.evaluate(node => window.getComputedStyle(node).filter);
expect(filterValue).not.toBe('grayscale(1)');
});

describe('Toggling auth state to public', () => {

beforeEach(async ({ page }) => {
// const authButton = page.locator(selectors.authButton);
const authButton = await page.locator( `.graphiql-toolbar button:nth-child(2)` );
await authButton.click();
});

test('Auth button is in public state', async ({ page }) => {
// const authButton = page.locator(selectors.authButton);
const authButton = await page.locator( `.graphiql-toolbar button:nth-child(2)` );
await expect(authButton).not.toHaveClass(/is-authenticated/);
await expect(authButton).toHaveClass(/is-public/);
});

test('Private data is not returned when public', async ({ page }) => {
const response = page.locator(selectors.graphiqlResponse);
await page.click(selectors.executeQueryButton);
await expect(response).toContainText('viewer');
await expect(response).not.toContainText('admin');
});

test('Auth button is grayscale when public', async ({ page }) => {
// const authButton = page.locator(selectors.authButton);
const authButton = await page.locator( `.graphiql-toolbar button:nth-child(2)` );
const filterValue = await authButton.evaluate(node => window.getComputedStyle(node).filter);
expect(filterValue).toBe('grayscale(1)');
});
});
});

describe('Prettify button', () => {

beforeEach(async ({ page }) => {
await typeQuery(page, 'query{viewer{name} }'); // poorly formatted query
});

test('Misformatted query is prettified when button is clicked', async ({ page }) => {
// const prettifyButton = page.locator(selectors.prettifyButton);
const prettifyButton = await page.locator( `.graphiql-toolbar button:nth-child(3)` );
const queryEditorLocator = page.locator(selectors.queryInput);

// Get the value from the CodeMirror instance
const codeMirrorValue = await getCodeMirrorValue(queryEditorLocator);

// Ensure the query is initially poorly formatted
await expect(codeMirrorValue).toBe('query{viewer{name} }');

// Make sure the prettify button is visible and interactable
await expect(prettifyButton).toBeVisible();
await expect(prettifyButton).toBeEnabled();

// Click the prettify button
await prettifyButton.click();

const codeMirrorValleAfterClick = await getCodeMirrorValue( queryEditorLocator );

await expect(codeMirrorValleAfterClick).toBe(`{
viewer {
name
}
}`
);

});
});

describe('Copy button', () => {

beforeEach(async ({ page }) => {
await typeQuery(page, '{ posts { nodes { id } } }' ); // poorly formatted query
});

test( 'Clicking the copy button copies the query to the clipboard', async ({ page }) => {

// clear the clipboard
await page.evaluate( () => navigator.clipboard.writeText('') );

// assert the clipboard is empty
const clipboardTextBefore = await page.evaluate( () => navigator.clipboard.readText() );
expect( clipboardTextBefore ).toBe( '' );

// Click the copy button
const copyButton = await page.locator( `.graphiql-toolbar button:nth-child(4)` );

await copyButton.click();
const clipboardText = await page.evaluate( () => navigator.clipboard.readText() );

expect( clipboardText ).not.toBe( '' );
});


});

describe('Merge Fragments button', () => {

const queryWithFragment = `{
...TestFragment
}
fragment TestFragment on RootQuery {
viewer {
name
}
}`;

beforeEach(async ({ page }) => {
await setQueryInLocalStorage(page, queryWithFragment);// query with fragment
await page.reload({ waitUntil: 'networkidle' }); // reload page to initialize with localStorage
await openDrawer(page);
});

test( 'Clicking the merge fragments button merges the fragment into the query', async ({ page }) => {
// Make sure the prettify button is visible and interactable
const mergeButton = page.locator( `.graphiql-toolbar button:nth-child(5)` );
await expect(mergeButton).toBeVisible();
await expect(mergeButton).toBeEnabled();

await mergeButton.click();

const queryEditorLocator = page.locator(selectors.queryInput);

// wait for the merge to complete
await page.waitForTimeout( 1000 );

// Get the value from the CodeMirror instance
const codeMirrorValue = await getCodeMirrorValue(queryEditorLocator);

// Log the output for debugging purposes
console.log('Merged Query:', codeMirrorValue);

// Verify that the query is now merged properly and formatted
const expectedMergedQuery = `{
viewer {
name
}
}`;
// const expectedMergedQueryFromTestsThatIsNotWhatWeGetInBrowserButItsTechnicallyStillValid = `{
// ... on RootQuery {
// viewer {
// name
// }
// }
// }`;
expect(codeMirrorValue).toBe(expectedMergedQuery);
});


})

describe('Share button', () => {

beforeEach(async ({ page }) => {
await typeQuery(page, '{ posts { nodes { id } } }' ); // poorly formatted query
});

test( 'Clicking the share button copies the query to the clipboard', async ({ page }) => {

// clear the clipboard
await page.evaluate( () => navigator.clipboard.writeText('') );

// assert the clipboard is empty
const clipboardTextBefore = await page.evaluate( () => navigator.clipboard.readText() );
expect( clipboardTextBefore ).toBe( '' );

// Click the copy button
const copyButton = await page.locator( `.graphiql-toolbar button:nth-child(4)` );

await copyButton.click();
const clipboardText = await page.evaluate( () => navigator.clipboard.readText() );

expect( clipboardText ).not.toBe( '' );
});


});

});
74 changes: 0 additions & 74 deletions tests/e2e/specs/toolbar-buttons.spec.js

This file was deleted.

Loading

0 comments on commit a7d710d

Please sign in to comment.