mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
E2E docs: Add guide to debuging PhantomJS (#21606)
* Add guide to debuging PhanomJS * Update contribute/style-guides/e2e.md
This commit is contained in:
parent
152059fec9
commit
aba402f98e
@ -1,9 +1,9 @@
|
|||||||
# End to end test framework
|
# End to end test framework
|
||||||
Grafana Labs uses a minimal home grown solution built on top of Cypress for our end to end (e2e) tests.
|
Grafana Labs uses a minimal home grown solution built on top of Cypress for our end to end (e2e) tests.
|
||||||
|
|
||||||
## Basic concepts
|
## Basic concepts
|
||||||
Here is a good introduction to e2e best practices: https://martinfowler.com/bliki/PageObject.html.
|
Here is a good introduction to e2e best practices: https://martinfowler.com/bliki/PageObject.html.
|
||||||
- `Selector`: A unique identifier that is used from the e2e framework to retrieve an element from the Browser
|
- `Selector`: A unique identifier that is used from the e2e framework to retrieve an element from the Browser
|
||||||
- `Page`: An abstraction for an object that contains one or more `Selectors`
|
- `Page`: An abstraction for an object that contains one or more `Selectors`
|
||||||
- `Flow`: An abstraction that contains a sequence of actions on one or more `Pages` that can be reused and shared between tests
|
- `Flow`: An abstraction that contains a sequence of actions on one or more `Pages` that can be reused and shared between tests
|
||||||
|
|
||||||
@ -49,16 +49,16 @@ export const Pages = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
Now that we have a `Page` called `Login` in our `Pages` const we can use that to add a selector in our html like shown below and now this really signals to future developers that it is part of an e2e test.
|
Now that we have a `Page` called `Login` in our `Pages` const we can use that to add a selector in our html like shown below and now this really signals to future developers that it is part of an e2e test.
|
||||||
```jsx harmony
|
```jsx harmony
|
||||||
<div>
|
<div>
|
||||||
<input type="text" className="gf-form-input login-form-input" aria-label={e2e.pages.Login.selectors.username}/>
|
<input type="text" className="gf-form-input login-form-input" aria-label={e2e.pages.Login.selectors.username}/>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
The last step in our example is to use our `Login` page as part of a test. The `pageFactory` function we used before gives us two things:
|
The last step in our example is to use our `Login` page as part of a test. The `pageFactory` function we used before gives us two things:
|
||||||
- The `url` property is used whenever we call the `visit` function and is equivalent to the Cypress function [cy.visit()](https://docs.cypress.io/api/commands/visit.html#Syntax).
|
- The `url` property is used whenever we call the `visit` function and is equivalent to the Cypress function [cy.visit()](https://docs.cypress.io/api/commands/visit.html#Syntax).
|
||||||
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
|
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
|
||||||
- Any defined selector in the `selectors` property can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [cy.get(...)](https://docs.cypress.io/api/commands/get.html#Syntax).
|
- Any defined selector in the `selectors` property can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [cy.get(...)](https://docs.cypress.io/api/commands/get.html#Syntax).
|
||||||
```ecmascript 6
|
```ecmascript 6
|
||||||
describe('Login test', () => {
|
describe('Login test', () => {
|
||||||
@ -90,7 +90,7 @@ Let's take a look at an example that uses the same `selector` for multiple items
|
|||||||
```
|
```
|
||||||
```
|
```
|
||||||
|
|
||||||
Just as before in the basic example we'll start by creating a page abstraction using the `pageFactory` function:
|
Just as before in the basic example we'll start by creating a page abstraction using the `pageFactory` function:
|
||||||
```typescript
|
```typescript
|
||||||
export const DataSources = pageFactory({
|
export const DataSources = pageFactory({
|
||||||
url: '/datasources',
|
url: '/datasources',
|
||||||
@ -134,15 +134,27 @@ When this list is rendered with the data sources with names `A`, `B`, `C` the re
|
|||||||
```
|
```
|
||||||
|
|
||||||
Now we can write our test. The one thing that differs from the `Basic example` is that we pass in which data source we want to click on as an argument to the selector function:
|
Now we can write our test. The one thing that differs from the `Basic example` is that we pass in which data source we want to click on as an argument to the selector function:
|
||||||
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
|
> Best practice after calling `visit` is to always call `should` on a selector to prevent flaky tests when you try to access an element that isn't ready. For more information, refer to [Commands vs. assertions](https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions).
|
||||||
```ecmascript 6
|
```ecmascript 6
|
||||||
describe('List test', () => {
|
describe('List test', () => {
|
||||||
it('Clicking on data source named B', () => {
|
it('Clicking on data source named B', () => {
|
||||||
e2e.pages.DataSources.visit();
|
e2e.pages.DataSources.visit();
|
||||||
// To prevent flaky tests, always do a .should on any selector that you expect to be in the DOM.
|
// To prevent flaky tests, always do a .should on any selector that you expect to be in the DOM.
|
||||||
// Read more here: https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions
|
// Read more here: https://docs.cypress.io/guides/core-concepts/retry-ability.html#Commands-vs-assertions
|
||||||
e2e.pages.DataSources.dataSources('B').should('be.visible');
|
e2e.pages.DataSources.dataSources('B').should('be.visible');
|
||||||
e2e.pages.DataSources.dataSources('B').click();
|
e2e.pages.DataSources.dataSources('B').click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Debugging PhantomJS image rendering
|
||||||
|
|
||||||
|
There is no easy or comprehensive way to debug PhantomJS smoke test (image rendering) failures. However, PhantomJS exposes remote debugging interface which can give you a sense of what is going wrong in the smoke test. Before performing the steps described below make sure your local Grafana instance is running:
|
||||||
|
|
||||||
|
1. Go to `tools/phantomjs` directory
|
||||||
|
2. Execute `phantomjs` binary against `render.js` file: `./phantomjs --remote-debugger-port=9009 --remote-debugger-autorun=yes ./render.js url="http://localhost:3000"`
|
||||||
|
3. In your browser navigate to `http://localhost:9009/`
|
||||||
|
4. Select `http://localhost:3000/login` from the list. You will get access to Webkit's inspector to see the console's output from the smoke test.
|
||||||
|
|
||||||
|
The method described above is not perfect, but is helpful to evaluate smoke tests breaking due to bundle errors.
|
||||||
|
Loading…
Reference in New Issue
Block a user