Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(DIST-136): Increase resilience for visual tests in firefox #2

Merged
merged 1 commit into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 17 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ python:

addons:
chrome: stable
firefox: latest
firefox: "67.0"

branches:
only:
Expand Down Expand Up @@ -47,12 +47,25 @@ jobs:
if: branch = master OR branch = release
script:
- yarn test:unit
- name: "Visual Tests (Internal)"
- name: "Visual Tests Chrome (Internal)"
if: fork = false AND (branch = master OR branch = release)
script:
- yarn start --no-info & export EMBED_PID=$!
- yarn test:visual:install
- yarn test:visual:chrome
- kill $EMBED_PID
- name: "Visual Tests Mobile (Internal)"
if: fork = false AND (branch = master OR branch = release)
script:
- yarn start --no-info & export EMBED_PID=$!
- yarn test:visual:install
- yarn test:visual:mobile
- kill $EMBED_PID
- name: "Visual Tests Firefox (Internal)"
if: fork = false AND (branch = master OR branch = release)
script:
- yarn start --no-info & export EMBED_PID=$!
- yarn test:visual:install
Comment on lines +62 to +68
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runs firefox visual tests in parallel on travis (speed up tests)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can run tests in parallel for each browser 👍 I suggest you run yarn test:visual:mobile separately as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good I wasn't sure if creating many jobs in parallel would cause issues, thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think it would. Each job needs to clone the repo and install dependencies - if the task is short it usually should not have a separate job. If it takes longer than cloning and installing and has no dependencies it can be a separate job.

I think I would also split functional tests per browser to make it faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 give me 10 minutes and I'll push the changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One build failed because both tests were running in parallel, I wonder if makes more sense to run one job with both tests in parallel (as @Gotusso set it up) or separated? I am not sure about it. Thoughts @mathio ? (right now I split them and removed the parallel flag)

Copy link
Collaborator

@mathio mathio Apr 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe try without the --parallel flag for cypress? But I would check with Franco first. So for now feel free to keep this as is.

Edit: I re-run the tests and they passed 🤷‍♂️ When run in separate Travis jobs it saves ~30 seconds of total run time.

- yarn test:visual:firefox
- kill $EMBED_PID
- name: "Functional Tests (Internal)"
Expand All @@ -66,8 +79,8 @@ jobs:
if: fork = true AND (branch = master OR branch = release)
script:
- yarn start --no-info & export EMBED_PID=$!
- yarn test:functional:chrome
- yarn test:functional:firefox
- yarn test:functional:chrome --parallel
- yarn test:functional:firefox --parallel
- kill $EMBED_PID
- name: "Deploy"
# Deploy to preview preview URL for testing purposes. Only deploy pull requests to 'release' branch.
Expand Down
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@ This is the list of all the test commands, if you want to run them one by one:
- `yarn test:visual` --> Runs visual tests with CodeceptJs, WebDriver, and Applitools.
- `yarn test:visual:chrome` --> Runs visual tests using Chrome
- `yarn test:visual:firefox` --> Runs visual tests using Firefox (Gecko drivers)
- `yarn test:visual:safari` --> Runs tests with Safari. This requires some extra steps for our local environment, check the [official apple documentation](https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari).

***_Note: `yarn test:visual` will not run the Safari tests. You need to run them manually_**
antoniofull marked this conversation as resolved.
Show resolved Hide resolved

## Feedback

Expand Down
2 changes: 1 addition & 1 deletion codecept-visual.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ exports.config = {
WebDriver: {
smartWait: 5000,
url: process.env.URL || 'http://localhost:8080',
show: true,
browser: process.profile || 'chrome',
host: '127.0.0.1',
port: 4444,
path: '/wd/hub',
restart: false,
desiredCapabilities: capabilities[process.profile] || capabilities.chrome,
windowSize: '1200x825'
},
Expand Down
14 changes: 9 additions & 5 deletions demo/demo.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
window.messages = []
window.addEventListener('message', function (event) {
console.log(`${event.data.type} event has been triggered`)
// Changes the document title when the form is ready
if (event.data.type === 'form-ready') {
window.document.title = event.data.type
}
Comment on lines +4 to +7
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the form is loaded, the page will receive a postMessage with data form-ready we change the title of the document to match the event, like so we have a better idea that the form is ready without having to dig in to the form itself.

})

var queryString = window.location.search

var EMBED_DOM_CLASSES = [
{
selector: '.typeform-widget',
attribute: 'data-url',
attribute: 'data-url'
}, {
selector: '.typeform-share',
attribute: 'href',
attribute: 'href'
}, {
selector: '.typeform-full',
attribute: 'src',
},
attribute: 'src'
}
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
]

window.addEventListener('DOMContentLoaded', function () {
Expand Down
2 changes: 1 addition & 1 deletion demo/full.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
width="100%"
height="100%"
frameborder="0"
src="https://admin.typeform.com/to/pDgR2Z"
src="https://admin.typeform.com/to/mzy0hT?disable-tracking=true"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use a static form without initial animation, since this seems to be the main issue

></iframe>

<script type="text/javascript" src="embed.js"></script>
Expand Down
6 changes: 3 additions & 3 deletions demo/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<body>
<a
class="typeform-share"
href="//admin.typeform.com/to/mzy0hT"
href="//admin.typeform.com/to/mzy0hT?disable-tracking=true"
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
data-mode="1"
data-submit-close-delay="4"
target="_blank"
Expand All @@ -30,7 +30,7 @@

<a
class="typeform-share"
href="//admin.typeform.com/to/mzy0hT"
href="//admin.typeform.com/to/mzy0hT?disable-tracking=true"
data-mode="2"
data-submit-close-delay="4"
target="_blank"
Expand All @@ -40,7 +40,7 @@

<a
class="typeform-share"
href="//admin.typeform.com/to/mzy0hT"
href="//admin.typeform.com/to/mzy0hT?disable-tracking=true"
data-mode="3"
data-submit-close-delay="4"
target="_blank"
Expand Down
4 changes: 1 addition & 3 deletions demo/widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@
<body>
<div
class="typeform-widget"
data-url="//admin.typeform.com/to/McAQk1"
data-url="//admin.typeform.com/to/mzy0hT?disable-tracking=true"
style="width:100%; height:500px;"
></div>

<script type="text/javascript" src="demo.js"></script>
<script type="text/javascript" src="embed.js"></script>
<script type="text/javascript" src="embed.js"></script>
<script type="text/javascript" src="embed.js"></script>
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
</body>
</html>
4 changes: 2 additions & 2 deletions e2e/codeceptjs-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = {
opinionScale: '[data-qa*=blocktype-opinionScale]',
closeButton: '[data-qa="popup-close-button"]'
},
resizeWindow: (I) => {
I.resizeWindow(375, 600)
resizeWindow: async (I) => {
await I.resizeWindow(375, 600)
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
}
}
10 changes: 10 additions & 0 deletions e2e/custom-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ module.exports = function () {
// For Visual Tests requires more waiting time
waitForVisualElement (cssLocator) {
this.waitForVisible({ css: cssLocator }, 10)
},
async waitForIFrameMessage () {
this.executeAsyncScript(function (done) {
const interval = setInterval(function () {
if (window.document.title === 'form-ready') {
clearInterval(interval)
done()
}
}, 100)
})
Comment on lines +29 to +38
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot use directly window object with codeceptjs and webdriver, so we use executeAsyncScript to run a function that checks at intervals when the title of the document is changed. see previous comments

}
})
}
2 changes: 1 addition & 1 deletion e2e/cypress-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const setupIframeTesting = (iframe) => {
// We can only use it inside Chrome disabling web security --> see config
// Won't work in popups
if (Cypress.isBrowser('chrome')) {
getIframeBody(iframe).find('[data-qa="fixed-footer-progress"]').should('be.visible')
getIframeBody(iframe).find('[data-qa="start-button"]').should('be.visible')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Since we changed form, we still want to have some resilience to make sure the form is loaded internally, the new form has a start button so we check for it. This is for functional tests

} else {
cy.get(iframe).should('be.visible')
}
Expand Down
1 change: 0 additions & 1 deletion e2e/functional/drawer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ describe('Drawer Embed Widget', () => {
link
})
})

it('Closes Embed Drawer using Keyboard', () => {
setupPopupTesting({
link,
Expand Down
2 changes: 1 addition & 1 deletion e2e/functional/right-drawer.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { setupPopupTesting } = require('../cypress-utils')

const link = 3
describe('Right Drawer Embed Widget', () => {
describe('Right Drawer Embed Widget handled with close button', () => {
it('Closes Embed Drawer clicking on the close button', () => {
setupPopupTesting({
link
Expand Down
34 changes: 27 additions & 7 deletions e2e/visual-helper.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
const { Eyes, Target, BatchInfo } = require('@applitools/eyes-webdriverio')
const { helper: Helper } = require('codeceptjs')
const { helper: Helper, event } = require('codeceptjs')
// const { ConsoleLogHandler } = require('@applitools/eyes-sdk-core')

const eyes = new Eyes()

class ApplitoolsHelper extends Helper {
constructor (config) {
super(config)
this.eyes = new Eyes()
this.eyes.setApiKey(process.env.EYES_API_KEY)
eyes.setApiKey(process.env.EYES_API_KEY)
this.appName = 'Embed Widget'
const batchInfo = new BatchInfo(this.appName)
this.eyes.setBatch(batchInfo)
eyes.setBatch(batchInfo)
}

async _before (test) {
const windowSize = this.setWindowSize(this.helpers['WebDriver'].config)
const browser = this.helpers['WebDriver'].browser
await this.eyes.open(browser, this.appName, test.title, windowSize)
// TODO Is this useful or makes tests more noisy?
// Print logs to console
// but makes the build noisy with a lot of logging events might makes it hard to read in Travis

// eyes.setLogHandler(new ConsoleLogHandler(true))

await eyes.open(browser, this.appName, test.title, windowSize)
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
}

setWindowSize (webDriverConfig) {
Expand All @@ -33,8 +41,20 @@ class ApplitoolsHelper extends Helper {
}

async eyesCheck (pageName) {
await this.eyes.check(pageName, Target.window())
await this.eyes.close()
await eyes.check(pageName, Target.window())
await eyes.close()
await eyes.abortIfNotClosed()
}

// Once visual tests have finished it takes Applitools more than
// 3 minutes to sent the exit code. So below the exit is forced
// as soon as Codecept tests results are printed.
// Forcing exit code to 0 because Applitools github integration will make
// the github status check fail if visuals fail
_afterSuite () {
event.dispatcher.on(event.all.result, () => {
process.exit(0)
})
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
87 changes: 49 additions & 38 deletions e2e/visual/embed.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,85 @@
const { resizeWindow } = require('../codeceptjs-utils')

const clickOnLink = (I, n = 1) => {
const clickOnLink = async (I, n = 1) => {
const cssLinkSelector = `[data-mode="${n}"]`
I.click({ css: cssLinkSelector })
await I.click({ css: cssLinkSelector })
}

const waitForIFrame = async (I) => {
await I.waitForVisible({ css: 'iframe' }, WAITING_TIME)
await I.waitForIFrameMessage()
}
const WAITING_TIME = 5

antoniofull marked this conversation as resolved.
Show resolved Hide resolved
Feature('Embed Widget')

Scenario('Basic Widget', async (I) => {
I.amOnPage('widget.html')
I.waitForVisible({ css: 'iframe' }, 5)
Scenario('Basic Widget @desktop', async (I) => {
await I.amOnPage('widget.html')
await waitForIFrame(I)
antoniofull marked this conversation as resolved.
Show resolved Hide resolved
await I.eyesCheck('Embed Basic Widget')
})

Scenario('Full Page Widget', async (I) => {
I.amOnPage('full.html')
I.waitForVisible({ css: 'iframe' }, 5)
Scenario('Full Page Widget @desktop', async (I) => {
await I.amOnPage('full.html')
await waitForIFrame(I)
await I.eyesCheck('Embed Full Page Widget')
})

Scenario('Basic Widget on Mobile', async (I) => {
resizeWindow(I)
I.amOnPage('widget.html')
Scenario('Basic Widget @mobile', async (I) => {
await resizeWindow(I)
await I.amOnPage('widget.html')
await waitForIFrame(I)
await I.eyesCheck('Embed Basic Widget - Mobile')
})

Scenario('Full Page Widget on Mobile', async (I) => {
resizeWindow(I)
I.amOnPage('full.html')
Scenario('Full Page Widget @mobile', async (I) => {
await resizeWindow(I)
await I.amOnPage('full.html')
await waitForIFrame(I)
await I.eyesCheck('Embed Full Page Widget - Mobile')
})

Scenario('Popup Widget', async (I) => {
I.amOnPage('popup.html')
clickOnLink(I, 1)
I.waitForVisible({ css: 'iframe' }, 10)
Scenario('Popup Widget @desktop', async (I) => {
await I.amOnPage('popup.html')
await clickOnLink(I, 1)
await waitForIFrame(I)
await I.eyesCheck('Popup Widget')
})

Scenario('Popup Widget on Mobile', async (I) => {
resizeWindow(I)
I.amOnPage('popup.html')
clickOnLink(I, 1)
Scenario('Popup Widget @mobile', async (I) => {
await resizeWindow(I)
await I.amOnPage('popup.html')
await clickOnLink(I, 1)
await waitForIFrame(I)
await I.eyesCheck('Popup Widget')
})

Scenario('Drawer Widget', async (I) => {
I.amOnPage('popup.html')
clickOnLink(I, 2)
I.waitForVisible({ css: 'iframe' }, 10)
Scenario('Drawer Widget @desktop', async (I) => {
await I.amOnPage('popup.html')
await clickOnLink(I, 2)
await waitForIFrame(I)
await I.eyesCheck('Drawer Widget')
})

Scenario('Drawer Widget on Mobile', async (I) => {
resizeWindow(I)
I.amOnPage('popup.html')
clickOnLink(I, 2)
Scenario('Drawer Widget @mobile', async (I) => {
await resizeWindow(I)
await I.amOnPage('popup.html')
await clickOnLink(I, 2)
await waitForIFrame(I)
await I.eyesCheck('Drawer Widget - Mobile')
})

Scenario('Right Drawer Widget', async (I) => {
I.amOnPage('popup.html')
clickOnLink(I, 3)
I.waitForVisible({ css: 'iframe' }, 10)
Scenario('Right Drawer Widget @desktop', async (I) => {
await I.amOnPage('popup.html')
await clickOnLink(I, 3)
await waitForIFrame(I)
await I.eyesCheck('Popup Widget')
})

Scenario('Right Drawer Widget on Mobile', async (I) => {
resizeWindow(I)
I.amOnPage('popup.html')
clickOnLink(I, 3)
Scenario('Right Drawer Widget @mobile', async (I) => {
await resizeWindow(I)
await I.amOnPage('popup.html')
await clickOnLink(I, 3)
await waitForIFrame(I)
await I.eyesCheck('Right Drawer Widget - Mobile')
})