test: make tests less flaky (#678)

This commit is contained in:
Nolan Lawson 2018-11-21 22:08:37 -08:00 committed by GitHub
parent 673e7b951c
commit bae367da7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 72 deletions

View File

@ -1,7 +1,7 @@
import { Selector as $ } from 'testcafe' import { Selector as $ } from 'testcafe'
import { import {
getNthStatus, getUrl, validateTimeline, scrollToBottomOfTimeline, getFirstVisibleStatus, getNthStatus, getUrl, validateTimeline, getFirstVisibleStatus,
goBack, forceOffline, forceOnline, searchNavButton, searchInput, getNthSearchResult goBack, forceOffline, forceOnline, searchNavButton, searchInput, getNthSearchResult, scrollToStatus
} from '../utils' } from '../utils'
import { loginAsFoobar } from '../roles' import { loginAsFoobar } from '../roles'
import { bazThreadRelativeTo2, bazThreadRelativeTo2b, bazThreadRelativeTo2B2, quuxThread } from '../fixtures' import { bazThreadRelativeTo2, bazThreadRelativeTo2b, bazThreadRelativeTo2B2, quuxThread } from '../fixtures'
@ -14,8 +14,9 @@ test('Shows a thread', async t => {
await t await t
.click($('a').withText('quux')) .click($('a').withText('quux'))
await scrollToBottomOfTimeline(t) await scrollToStatus(t, 26)
await t await t
.hover(getNthStatus(26))
.click(getNthStatus(26)) .click(getNthStatus(26))
.expect(getUrl()).contains('/statuses/') .expect(getUrl()).contains('/statuses/')

View File

@ -1,7 +1,7 @@
import { import {
getFavoritesCount, getFavoritesCount,
getNthFavoriteButton, getNthFavorited, getNthStatus, getUrl, homeNavButton, notificationsNavButton, getNthFavoriteButton, getNthFavorited, getNthStatus, getUrl, homeNavButton, notificationsNavButton,
scrollToBottomOfTimeline, scrollToTopOfTimeline scrollToBottom, scrollToTop, sleep
} from '../utils' } from '../utils'
import { loginAsFoobar } from '../roles' import { loginAsFoobar } from '../roles'
import { indexWhere } from '../../routes/_utils/arrays' import { indexWhere } from '../../routes/_utils/arrays'
@ -19,8 +19,9 @@ test('favorites a status', async t => {
.expect(getNthFavorited(4)).eql('true') .expect(getNthFavorited(4)).eql('true')
// scroll down and back up to force an unrender // scroll down and back up to force an unrender
await scrollToBottomOfTimeline(t) await scrollToBottom()
await scrollToTopOfTimeline(t) await sleep(1)
await scrollToTop()
await t await t
.hover(getNthStatus(4)) .hover(getNthStatus(4))
.expect(getNthFavorited(4)).eql('true') .expect(getNthFavorited(4)).eql('true')
@ -45,8 +46,9 @@ test('unfavorites a status', async t => {
.expect(getNthFavorited(1)).eql('false') .expect(getNthFavorited(1)).eql('false')
// scroll down and back up to force an unrender // scroll down and back up to force an unrender
await scrollToBottomOfTimeline(t) await scrollToBottom()
await scrollToTopOfTimeline(t) await sleep(1)
await scrollToTop()
await t await t
.expect(getNthFavorited(1)).eql('false') .expect(getNthFavorited(1)).eql('false')
.click(notificationsNavButton) .click(notificationsNavButton)

View File

@ -1,24 +1,27 @@
import { import {
getNthReblogButton, getNthReblogged, getNthStatus, getReblogsCount, getUrl, homeNavButton, getNthReblogButton, getNthReblogged, getNthStatus, getNthStatusContent, getReblogsCount, getUrl, homeNavButton,
notificationsNavButton, notificationsNavButton, scrollToBottom, scrollToTop, sleep
scrollToBottomOfTimeline, scrollToTopOfTimeline
} from '../utils' } from '../utils'
import { loginAsFoobar } from '../roles' import { loginAsFoobar } from '../roles'
import { postAs, reblogStatusAs } from '../serverActions'
fixture`101-reblog-unreblog.js` fixture`101-reblog-unreblog.js`
.page`http://localhost:4002` .page`http://localhost:4002`
test('reblogs a status', async t => { test('reblogs a status', async t => {
await postAs('foobar', 'hello this should be reblogged')
await loginAsFoobar(t) await loginAsFoobar(t)
await t await t
.hover(getNthStatus(0)) .hover(getNthStatus(0))
.expect(getNthStatusContent(0).innerText).contains('should be reblogged')
.expect(getNthReblogged(0)).eql('false') .expect(getNthReblogged(0)).eql('false')
.click(getNthReblogButton(0)) .click(getNthReblogButton(0))
.expect(getNthReblogged(0)).eql('true') .expect(getNthReblogged(0)).eql('true')
// scroll down and back up to force an unrender // scroll down and back up to force an unrender
await scrollToBottomOfTimeline(t) await scrollToBottom()
await scrollToTopOfTimeline(t) await sleep(1)
await scrollToTop()
await t await t
.hover(getNthStatus(0)) .hover(getNthStatus(0))
.expect(getNthReblogged(0)).eql('true') .expect(getNthReblogged(0)).eql('true')
@ -35,46 +38,53 @@ test('reblogs a status', async t => {
}) })
test('unreblogs a status', async t => { test('unreblogs a status', async t => {
await postAs('foobar', 'woot i wanna reblog this')
await loginAsFoobar(t) await loginAsFoobar(t)
await t await t
.hover(getNthStatus(3)) .hover(getNthStatus(0))
.expect(getNthReblogged(3)).eql('false') .expect(getNthStatusContent(0).innerText).contains('woot i wanna')
.click(getNthReblogButton(3)) .expect(getNthReblogged(0)).eql('false')
.expect(getNthReblogged(3)).eql('true') .click(getNthReblogButton(0))
.click(getNthReblogButton(3)) .expect(getNthReblogged(0)).eql('true')
.expect(getNthReblogged(3)).eql('false') .click(getNthReblogButton(0))
.expect(getNthReblogged(0)).eql('false')
// scroll down and back up to force an unrender // scroll down and back up to force an unrender
await scrollToBottomOfTimeline(t) await scrollToBottom()
await scrollToTopOfTimeline(t) await sleep(1)
await scrollToTop()
await t await t
.hover(getNthStatus(3)) .hover(getNthStatus(0))
.expect(getNthReblogged(3)).eql('false') .expect(getNthReblogged(0)).eql('false')
.click(notificationsNavButton) .click(notificationsNavButton)
.click(homeNavButton) .click(homeNavButton)
.expect(getNthReblogged(3)).eql('false') .expect(getNthReblogged(0)).eql('false')
.click(notificationsNavButton) .click(notificationsNavButton)
.navigateTo('/') .navigateTo('/')
.expect(getNthReblogged(3)).eql('false') .expect(getNthReblogged(0)).eql('false')
.click(getNthReblogButton(3)) .click(getNthReblogButton(0))
.expect(getNthReblogged(3)).eql('true') .expect(getNthReblogged(0)).eql('true')
}) })
test('Keeps the correct reblogs count', async t => { test('Keeps the correct reblogs count', async t => {
let { id } = await postAs('foobar', 'this will be reblogged')
await reblogStatusAs('foobar', id)
await reblogStatusAs('admin', id)
await loginAsFoobar(t) await loginAsFoobar(t)
await t await t
.hover(getNthStatus(3)) .hover(getNthStatus(0))
.expect(getNthReblogged(3)).eql('true') .expect(getNthStatusContent(0).innerText).contains('this will be reblogged')
.click(getNthStatus(3)) .expect(getNthReblogged(0)).eql('true')
.click(getNthStatus(0))
.expect(getUrl()).contains('/status') .expect(getUrl()).contains('/status')
.expect(getNthReblogged(0)).eql('true') .expect(getNthReblogged(0)).eql('true')
.expect(getReblogsCount()).eql(2) .expect(getReblogsCount()).eql(2)
.click(homeNavButton) .click(homeNavButton)
.expect(getUrl()).eql('http://localhost:4002/') .expect(getUrl()).eql('http://localhost:4002/')
.hover(getNthStatus(3)) .hover(getNthStatus(0))
.click(getNthReblogButton(3)) .click(getNthReblogButton(0))
.expect(getNthReblogged(3)).eql('false') .expect(getNthReblogged(0)).eql('false')
.click(getNthStatus(3)) .click(getNthStatus(0))
.expect(getUrl()).contains('/status') .expect(getUrl()).contains('/status')
.expect(getNthReblogged(0)).eql('false') .expect(getNthReblogged(0)).eql('false')
.expect(getReblogsCount()).eql(1) .expect(getReblogsCount()).eql(1)

View File

@ -1,6 +1,6 @@
import { loginAsFoobar } from '../roles' import { loginAsFoobar } from '../roles'
import { import {
getNthStatus, scrollContainerToTop, showMoreButton, sleep getNthStatus, scrollToTop, showMoreButton, sleep
} from '../utils' } from '../utils'
import { postAs } from '../serverActions' import { postAs } from '../serverActions'
@ -27,7 +27,7 @@ test('new incoming toots show a button if scrolled down', async t => {
await sleep(4000) await sleep(4000)
await t.hover(getNthStatus(2)) await t.hover(getNthStatus(2))
.hover(getNthStatus(0)) .hover(getNthStatus(0))
await scrollContainerToTop() await scrollToTop()
await sleep(1000) await sleep(1000)
await t await t
.expect(showMoreButton.innerText).contains('Show 2 more') .expect(showMoreButton.innerText).contains('Show 2 more')

View File

@ -3,8 +3,7 @@ import {
avatarInComposeBox, closeDialogButton, composeInput, getNthDialogOptionsOption, getNthPinnedStatus, avatarInComposeBox, closeDialogButton, composeInput, getNthDialogOptionsOption, getNthPinnedStatus,
getNthPinnedStatusFavoriteButton, getNthPinnedStatusFavoriteButton,
getNthStatus, getNthStatusContent, getNthStatus, getNthStatusContent,
getNthStatusOptionsButton, getUrl, homeNavButton, postStatusButton, scrollContainerToTop, scrollToBottomOfTimeline, getNthStatusOptionsButton, getUrl, homeNavButton, postStatusButton, scrollToTop, scrollToBottom,
scrollToTopOfTimeline,
settingsNavButton, sleep settingsNavButton, sleep
} from '../utils' } from '../utils'
import { users } from '../users' import { users } from '../users'
@ -70,9 +69,9 @@ test('Saved pinned/unpinned state of status', async t => {
.click(closeDialogButton) .click(closeDialogButton)
// scroll down and back up to force an unrender // scroll down and back up to force an unrender
await scrollToBottomOfTimeline(t) await scrollToBottom()
await scrollToTopOfTimeline(t) await sleep(1)
await scrollContainerToTop() // otherwise the ... button is obscured by the pen button await scrollToTop()
await t await t
.expect(getNthStatusContent(0).innerText).contains('hey I am going to pin and unpin this', { timeout }) .expect(getNthStatusContent(0).innerText).contains('hey I am going to pin and unpin this', { timeout })

View File

@ -64,10 +64,6 @@ export const getActiveElementInnerText = exec(() =>
(document.activeElement && document.activeElement.innerText) || '' (document.activeElement && document.activeElement.innerText) || ''
) )
export const getActiveElementAriaLabel = exec(() =>
(document.activeElement && document.activeElement.getAttribute('aria-label')) || ''
)
export const getActiveElementInsideNthStatus = exec(() => { export const getActiveElementInsideNthStatus = exec(() => {
let element = document.activeElement let element = document.activeElement
while (element) { while (element) {
@ -95,10 +91,6 @@ export const getBodyClassList = exec(() => (
Array.prototype.slice.apply(document.body.classList).filter(_ => _ !== 'the-body')) Array.prototype.slice.apply(document.body.classList).filter(_ => _ !== 'the-body'))
) )
export const scrollContainerToTop = exec(() => {
document.scrollingElement.scrollTop = 0
})
export const uploadKittenImage = i => (exec(() => { export const uploadKittenImage = i => (exec(() => {
let image = images[`kitten${i}`] let image = images[`kitten${i}`]
let blob = blobUtils.base64StringToBlob(image.data, 'image/png') let blob = blobUtils.base64StringToBlob(image.data, 'image/png')
@ -120,6 +112,14 @@ export const focus = (selector) => (exec(() => {
} }
})) }))
export const scrollToBottom = exec(() => {
document.scrollingElement.scrollTop = document.scrollingElement.scrollHeight
})
export const scrollToTop = exec(() => {
document.scrollingElement.scrollTop = 0
})
export function getNthMediaAltInput (n) { export function getNthMediaAltInput (n) {
return $(`.compose-box .compose-media:nth-child(${n}) .compose-media-alt input`) return $(`.compose-box .compose-media:nth-child(${n}) .compose-media-alt input`)
} }
@ -281,29 +281,6 @@ export async function validateTimeline (t, timeline) {
} }
} }
export async function scrollToTopOfTimeline (t) {
let i = await getFirstVisibleStatus().getAttribute('aria-posinset')
while (true) {
await t.hover(getNthStatus(i))
.expect($('.loading-footer').exist).notOk()
if (--i <= 0) {
break
}
}
}
export async function scrollToBottomOfTimeline (t) {
let i = 0
while (true) {
await t.hover(getNthStatus(i))
.expect($('.loading-footer').exist).notOk()
let size = await getNthStatus(i).getAttribute('aria-setsize')
if (++i >= size - 1) {
break
}
}
}
export async function scrollToStatus (t, n) { export async function scrollToStatus (t, n) {
let timeout = 20000 let timeout = 20000
for (let i = 0; i <= n; i++) { for (let i = 0; i <= n; i++) {