forked from cybrespace/pinafore
add test for threads
This commit is contained in:
parent
5b051558e1
commit
ea3f5a33fb
|
@ -57,3 +57,5 @@ export const quuxStatuses = [
|
||||||
{content: 'pinned toot 2'},
|
{content: 'pinned toot 2'},
|
||||||
{content: 'pinned toot 1'}
|
{content: 'pinned toot 1'}
|
||||||
].concat(times(25, i => ({content: `unlisted thread ${25 - i}`})))
|
].concat(times(25, i => ({content: `unlisted thread ${25 - i}`})))
|
||||||
|
|
||||||
|
export const quuxThread = times(25, i => ({content: `unlisted thread ${i + 1}`}))
|
|
@ -1,4 +1,4 @@
|
||||||
import { getNthVirtualArticle } from '../utils'
|
import { getNthStatus } from '../utils'
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
|
|
||||||
fixture`05-status-types.js`
|
fixture`05-status-types.js`
|
||||||
|
@ -6,39 +6,39 @@ fixture`05-status-types.js`
|
||||||
|
|
||||||
test('shows direct vs followers-only vs regular', async t => {
|
test('shows direct vs followers-only vs regular', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.expect(getNthVirtualArticle(1).getAttribute('aria-label')).eql('Status by admin')
|
.expect(getNthStatus(1).getAttribute('aria-label')).eql('Status by admin')
|
||||||
.expect(getNthVirtualArticle(1).find('.status-content').innerText).contains('notification of unlisted message')
|
.expect(getNthStatus(1).find('.status-content').innerText).contains('notification of unlisted message')
|
||||||
.expect(getNthVirtualArticle(1).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
.expect(getNthStatus(1).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
||||||
.eql('Boost')
|
.eql('Boost')
|
||||||
.expect(getNthVirtualArticle(1).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).notOk()
|
.expect(getNthStatus(1).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).notOk()
|
||||||
.expect(getNthVirtualArticle(2).getAttribute('aria-label')).eql('Status by admin')
|
.expect(getNthStatus(2).getAttribute('aria-label')).eql('Status by admin')
|
||||||
.expect(getNthVirtualArticle(2).find('.status-content').innerText).contains('notification of followers-only message')
|
.expect(getNthStatus(2).find('.status-content').innerText).contains('notification of followers-only message')
|
||||||
.expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
.expect(getNthStatus(2).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
||||||
.eql('Cannot be boosted because this is followers-only')
|
.eql('Cannot be boosted because this is followers-only')
|
||||||
.expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
.expect(getNthStatus(2).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
||||||
.expect(getNthVirtualArticle(3).getAttribute('aria-label')).eql('Direct message by admin')
|
.expect(getNthStatus(3).getAttribute('aria-label')).eql('Direct message by admin')
|
||||||
.expect(getNthVirtualArticle(3).find('.status-content').innerText).contains('notification of direct message')
|
.expect(getNthStatus(3).find('.status-content').innerText).contains('notification of direct message')
|
||||||
.expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
.expect(getNthStatus(3).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
||||||
.eql('Cannot be boosted because this is a direct message')
|
.eql('Cannot be boosted because this is a direct message')
|
||||||
.expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
.expect(getNthStatus(3).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('shows direct vs followers-only vs regular in notifications', async t => {
|
test('shows direct vs followers-only vs regular in notifications', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.navigateTo('/notifications')
|
.navigateTo('/notifications')
|
||||||
.expect(getNthVirtualArticle(2).getAttribute('aria-label')).eql('Status by admin')
|
.expect(getNthStatus(2).getAttribute('aria-label')).eql('Status by admin')
|
||||||
.expect(getNthVirtualArticle(2).find('.status-content').innerText).contains('notification of unlisted message')
|
.expect(getNthStatus(2).find('.status-content').innerText).contains('notification of unlisted message')
|
||||||
.expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
.expect(getNthStatus(2).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
||||||
.eql('Boost')
|
.eql('Boost')
|
||||||
.expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).notOk()
|
.expect(getNthStatus(2).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).notOk()
|
||||||
.expect(getNthVirtualArticle(3).getAttribute('aria-label')).eql('Status by admin')
|
.expect(getNthStatus(3).getAttribute('aria-label')).eql('Status by admin')
|
||||||
.expect(getNthVirtualArticle(3).find('.status-content').innerText).contains('notification of followers-only message')
|
.expect(getNthStatus(3).find('.status-content').innerText).contains('notification of followers-only message')
|
||||||
.expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
.expect(getNthStatus(3).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
||||||
.eql('Cannot be boosted because this is followers-only')
|
.eql('Cannot be boosted because this is followers-only')
|
||||||
.expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
.expect(getNthStatus(3).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
||||||
.expect(getNthVirtualArticle(4).getAttribute('aria-label')).eql('Direct message by admin')
|
.expect(getNthStatus(4).getAttribute('aria-label')).eql('Direct message by admin')
|
||||||
.expect(getNthVirtualArticle(4).find('.status-content').innerText).contains('notification of direct message')
|
.expect(getNthStatus(4).find('.status-content').innerText).contains('notification of direct message')
|
||||||
.expect(getNthVirtualArticle(4).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
.expect(getNthStatus(4).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
|
||||||
.eql('Cannot be boosted because this is a direct message')
|
.eql('Cannot be boosted because this is a direct message')
|
||||||
.expect(getNthVirtualArticle(4).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
.expect(getNthStatus(4).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Selector as $ } from 'testcafe'
|
import { Selector as $ } from 'testcafe'
|
||||||
import { getNthVirtualArticle } from '../utils'
|
import { getNthStatus } from '../utils'
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
|
|
||||||
fixture`06-tabindex.js`
|
fixture`06-tabindex.js`
|
||||||
|
@ -7,27 +7,27 @@ fixture`06-tabindex.js`
|
||||||
|
|
||||||
test('shows correct tabindex in home timeline', async t => {
|
test('shows correct tabindex in home timeline', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.expect(getNthVirtualArticle(0).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(0).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(1).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(1).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(2).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(2).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(3).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(3).getAttribute('tabindex')).eql('0')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('shows correct tabindex in notifications', async t => {
|
test('shows correct tabindex in notifications', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.navigateTo('/notifications')
|
.navigateTo('/notifications')
|
||||||
.expect(getNthVirtualArticle(0).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(0).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(1).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(1).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(2).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(2).getAttribute('tabindex')).eql('0')
|
||||||
.hover(getNthVirtualArticle(2))
|
.hover(getNthStatus(2))
|
||||||
.expect(getNthVirtualArticle(3).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(3).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(4).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(4).getAttribute('tabindex')).eql('0')
|
||||||
.hover(getNthVirtualArticle(4))
|
.hover(getNthStatus(4))
|
||||||
.expect(getNthVirtualArticle(5).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(5).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(6).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(6).getAttribute('tabindex')).eql('0')
|
||||||
.hover(getNthVirtualArticle(6))
|
.hover(getNthStatus(6))
|
||||||
.expect(getNthVirtualArticle(7).getAttribute('tabindex')).eql('0')
|
.expect(getNthStatus(7).getAttribute('tabindex')).eql('0')
|
||||||
.expect(getNthVirtualArticle(7).getAttribute('aria-setsize')).eql('8')
|
.expect(getNthStatus(7).getAttribute('aria-setsize')).eql('8')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('shows correct tabindex in pinned statuses', async t => {
|
test('shows correct tabindex in pinned statuses', async t => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Selector as $ } from 'testcafe'
|
import { Selector as $ } from 'testcafe'
|
||||||
import { getNthVirtualArticle } from '../utils'
|
import { getNthStatus } from '../utils'
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
|
|
||||||
const modalDialogContents = $('.modal-dialog-contents')
|
const modalDialogContents = $('.modal-dialog-contents')
|
||||||
|
@ -10,33 +10,33 @@ fixture`08-status-media.js`
|
||||||
|
|
||||||
test('shows sensitive images and videos', async t => {
|
test('shows sensitive images and videos', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.hover(getNthVirtualArticle(3))
|
.hover(getNthStatus(3))
|
||||||
.hover(getNthVirtualArticle(6))
|
.hover(getNthStatus(6))
|
||||||
.hover(getNthVirtualArticle(7))
|
.hover(getNthStatus(7))
|
||||||
.expect(getNthVirtualArticle(7).find('.status-media img').exists).notOk()
|
.expect(getNthStatus(7).find('.status-media img').exists).notOk()
|
||||||
.click(getNthVirtualArticle(7).find('.status-sensitive-media-button'))
|
.click(getNthStatus(7).find('.status-sensitive-media-button'))
|
||||||
.expect(getNthVirtualArticle(7).find('.status-media img').getAttribute('alt')).eql('kitten')
|
.expect(getNthStatus(7).find('.status-media img').getAttribute('alt')).eql('kitten')
|
||||||
.expect(getNthVirtualArticle(7).find('.status-media img').hasAttribute('src')).ok()
|
.expect(getNthStatus(7).find('.status-media img').hasAttribute('src')).ok()
|
||||||
.hover(getNthVirtualArticle(8))
|
.hover(getNthStatus(8))
|
||||||
.expect(getNthVirtualArticle(8).find('.status-media .play-video-button').exists).notOk()
|
.expect(getNthStatus(8).find('.status-media .play-video-button').exists).notOk()
|
||||||
.click(getNthVirtualArticle(8).find('.status-sensitive-media-button'))
|
.click(getNthStatus(8).find('.status-sensitive-media-button'))
|
||||||
.expect(getNthVirtualArticle(8).find('.status-media .play-video-button').exists).ok()
|
.expect(getNthStatus(8).find('.status-media .play-video-button').exists).ok()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('click and close image and video modals', async t => {
|
test('click and close image and video modals', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.hover(getNthVirtualArticle(3))
|
.hover(getNthStatus(3))
|
||||||
.hover(getNthVirtualArticle(6))
|
.hover(getNthStatus(6))
|
||||||
.hover(getNthVirtualArticle(7))
|
.hover(getNthStatus(7))
|
||||||
.hover(getNthVirtualArticle(9))
|
.hover(getNthStatus(9))
|
||||||
.expect(modalDialogContents.exists).notOk()
|
.expect(modalDialogContents.exists).notOk()
|
||||||
.click(getNthVirtualArticle(9).find('.play-video-button'))
|
.click(getNthStatus(9).find('.play-video-button'))
|
||||||
.expect(modalDialogContents.exists).ok()
|
.expect(modalDialogContents.exists).ok()
|
||||||
.click(closeDialogButton)
|
.click(closeDialogButton)
|
||||||
.expect(modalDialogContents.exists).notOk()
|
.expect(modalDialogContents.exists).notOk()
|
||||||
.hover(getNthVirtualArticle(11))
|
.hover(getNthStatus(11))
|
||||||
.hover(getNthVirtualArticle(12))
|
.hover(getNthStatus(12))
|
||||||
.click(getNthVirtualArticle(12).find('.show-image-button'))
|
.click(getNthStatus(12).find('.show-image-button'))
|
||||||
.expect(modalDialogContents.exists).ok()
|
.expect(modalDialogContents.exists).ok()
|
||||||
.click(closeDialogButton)
|
.click(closeDialogButton)
|
||||||
.expect(modalDialogContents.exists).notOk()
|
.expect(modalDialogContents.exists).notOk()
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { Selector as $ } from 'testcafe'
|
||||||
|
import { getNthStatus, getUrl, validateTimeline, scrollToBottomOfTimeline } from '../utils'
|
||||||
|
import { foobarRole } from '../roles'
|
||||||
|
import { quuxThread } from '../fixtures'
|
||||||
|
|
||||||
|
fixture`09-threads.js`
|
||||||
|
.page`http://localhost:4002`
|
||||||
|
|
||||||
|
test('Shows a thread', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.click($('a').withText('quux'))
|
||||||
|
|
||||||
|
await scrollToBottomOfTimeline(t)
|
||||||
|
await t
|
||||||
|
.click(getNthStatus(26))
|
||||||
|
.expect(getUrl()).contains('/statuses/99549257018049016')
|
||||||
|
|
||||||
|
await validateTimeline(t, quuxThread)
|
||||||
|
|
||||||
|
await t.expect(getNthStatus(24).getAttribute('aria-setsize')).eql('25')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Scrolls to proper point in thread', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.click($('a').withText('quux'))
|
||||||
|
.hover(getNthStatus(0))
|
||||||
|
.hover(getNthStatus(2))
|
||||||
|
.hover(getNthStatus(4))
|
||||||
|
.hover(getNthStatus(6))
|
||||||
|
.hover(getNthStatus(8))
|
||||||
|
.hover(getNthStatus(10))
|
||||||
|
.click(getNthStatus(10))
|
||||||
|
.expect(getUrl()).contains('/statuses/99549263341916700')
|
||||||
|
.expect(getNthStatus(16).innerText).contains('unlisted thread 17')
|
||||||
|
.expect(Math.round(getNthStatus(16).boundingClientRect.top))
|
||||||
|
.eql(Math.round($('.container').boundingClientRect.top))
|
||||||
|
})
|
|
@ -6,38 +6,55 @@ export const addInstanceButton = $('.add-new-instance button')
|
||||||
|
|
||||||
export const getUrl = exec(() => window.location.href)
|
export const getUrl = exec(() => window.location.href)
|
||||||
|
|
||||||
export function getNthVirtualArticle (n) {
|
export function getNthStatus (n) {
|
||||||
return $(`.virtual-list-item[aria-hidden="false"] article[aria-posinset="${n}"]`)
|
return $(`[aria-hidden="false"] > article[aria-posinset="${n}"]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLastVisibleStatus () {
|
||||||
|
return $(`[aria-hidden="false"] > article[aria-posinset]`).nth(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function validateTimeline (t, timeline) {
|
export async function validateTimeline (t, timeline) {
|
||||||
for (let i = 0; i < timeline.length; i++) {
|
for (let i = 0; i < timeline.length; i++) {
|
||||||
let status = timeline[i]
|
let status = timeline[i]
|
||||||
if (status.content) {
|
if (status.content) {
|
||||||
await t.expect(getNthVirtualArticle(i).find('.status-content p').innerText)
|
await t.expect(getNthStatus(i).find('.status-content p').innerText)
|
||||||
.contains(status.content)
|
.contains(status.content)
|
||||||
}
|
}
|
||||||
if (status.spoiler) {
|
if (status.spoiler) {
|
||||||
await t.expect(getNthVirtualArticle(i).find('.status-spoiler p').innerText)
|
await t.expect(getNthStatus(i).find('.status-spoiler p').innerText)
|
||||||
.contains(status.spoiler)
|
.contains(status.spoiler)
|
||||||
}
|
}
|
||||||
if (status.followedBy) {
|
if (status.followedBy) {
|
||||||
await t.expect(getNthVirtualArticle(i).find('.status-header span').innerText)
|
await t.expect(getNthStatus(i).find('.status-header span').innerText)
|
||||||
.contains(status.followedBy + ' followed you')
|
.contains(status.followedBy + ' followed you')
|
||||||
}
|
}
|
||||||
if (status.rebloggedBy) {
|
if (status.rebloggedBy) {
|
||||||
await t.expect(getNthVirtualArticle(i).find('.status-header span').innerText)
|
await t.expect(getNthStatus(i).find('.status-header span').innerText)
|
||||||
.contains(status.rebloggedBy + ' boosted your status')
|
.contains(status.rebloggedBy + ' boosted your status')
|
||||||
}
|
}
|
||||||
if (status.favoritedBy) {
|
if (status.favoritedBy) {
|
||||||
await t.expect(getNthVirtualArticle(i).find('.status-header span').innerText)
|
await t.expect(getNthStatus(i).find('.status-header span').innerText)
|
||||||
.contains(status.favoritedBy + ' favorited your status')
|
.contains(status.favoritedBy + ' favorited your status')
|
||||||
}
|
}
|
||||||
|
|
||||||
// hovering forces TestCafé to scroll to that element: https://git.io/vABV2
|
// hovering forces TestCafé to scroll to that element: https://git.io/vABV2
|
||||||
if (i % 3 === 2) { // only scroll every nth element
|
if (i % 3 === 2) { // only scroll every nth element
|
||||||
await t.hover(getNthVirtualArticle(i))
|
await t.hover(getNthStatus(i))
|
||||||
await t.expect($('.loading-footer').exist).notOk()
|
.expect($('.loading-footer').exist).notOk()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function scrollToBottomOfTimeline (t) {
|
||||||
|
let lastSize = null
|
||||||
|
while (true) {
|
||||||
|
await t.hover(getLastVisibleStatus())
|
||||||
|
.expect($('.loading-footer').exist).notOk()
|
||||||
|
let newSize = await getLastVisibleStatus().getAttribute('aria-setsize')
|
||||||
|
if (newSize === lastSize) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
lastSize = newSize
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue