From efdb0bc534f85eb95f60f1842495f9bda3d4c80d Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Sat, 26 May 2018 13:51:41 -0700 Subject: [PATCH] Remove testcafe roles and run in parallel x4 (#334) * more attempts to fix test flakiness * remove testcafe roles entirely * really remove testcafe roles * run testcafe in parallel x2 * run testcafe in parallel x4 * fix online/offline forcing in tests * fix pin test --- package.json | 15 +++--- .../_components/compose/ComposeToolbar.html | 15 +++--- routes/_store/store.js | 5 ++ tests/roles.js | 22 ++++++--- tests/spec/003-basic-timeline-spec.js | 31 +++++++----- tests/spec/004-pinned-statuses.js | 11 +++-- tests/spec/005-status-types.js | 8 ++-- tests/spec/006-tabindex.js | 11 +++-- tests/spec/007-account-profile.js | 14 ++++-- tests/spec/008-status-media.js | 6 +-- tests/spec/009-threads.js | 11 +++-- tests/spec/010-focus.js | 18 ++++--- tests/spec/011-reblog-favorites-count.js | 8 ++-- tests/spec/012-compose.js | 20 +++++--- tests/spec/013-compose-media.js | 11 +++-- tests/spec/014-compose-post-privacy.js | 5 +- tests/spec/015-compose-content-warnings.js | 11 +++-- tests/spec/016-external-links.js | 8 ++-- tests/spec/017-compose-reply.js | 20 ++++---- tests/spec/018-compose-autosuggest.js | 26 ++++++---- tests/spec/019-mention.js | 5 +- tests/spec/020-themes.js | 5 +- tests/spec/021-followers-follows.js | 5 +- tests/spec/100-favorite-unfavorite.js | 11 +++-- tests/spec/101-reblog-unreblog.js | 11 +++-- tests/spec/102-notifications.js | 5 +- tests/spec/103-compose.js | 8 ++-- tests/spec/104-streaming.js | 8 ++-- tests/spec/105-deletes.js | 11 +++-- tests/spec/106-follow-requests.js | 5 +- tests/spec/107-streaming-gap.js | 5 +- tests/spec/108-compose-dialog.js | 6 +-- tests/spec/109-compose-media.js | 14 ++++-- tests/spec/110-compose-content-warnings.js | 14 ++++-- tests/spec/111-focus.js | 5 +- tests/spec/112-status-links.js | 5 +- tests/spec/113-block-unblock.js | 8 ++-- tests/spec/114-mute-unmute.js | 4 +- tests/spec/115-follow-unfollow.js | 5 +- tests/spec/116-follow-requests.js | 4 +- tests/spec/117-pin-unpin.js | 24 +++++----- tests/utils.js | 47 ++++++++++--------- 42 files changed, 300 insertions(+), 191 deletions(-) diff --git a/package.json b/package.json index 601d0469..2a6b0799 100644 --- a/package.json +++ b/package.json @@ -8,19 +8,22 @@ "dev": "run-s build-svg build-inline-script serve-dev", "serve-dev": "run-p --race build-sass-watch serve", "serve": "node server.js", - "build": "cross-env NODE_ENV=production run-s globalize-css build-sass build-svg build-inline-script sapper-build deglobalize-css", - "sapper-build": "cross-env NODE_ENV=production sapper build", - "start": "cross-env NODE_ENV=production node server.js", + "build": "cross-env NODE_ENV=production npm run build-steps", + "build-steps": "run-s globalize-css build-sass build-svg build-inline-script sapper-build deglobalize-css", + "sapper-build": "sapper build", + "start": "cross-env NODE_ENV=production npm run serve", "build-and-start": "run-s build start", "build-svg": "node ./bin/build-svg.js", "build-inline-script": "node ./bin/build-inline-script.js", "build-sass": "node ./bin/build-sass.js", "build-sass-watch": "node ./bin/build-sass.js --watch", "run-mastodon": "node -r esm ./bin/run-mastodon.js", - "run-testcafe": "cross-env-shell testcafe --hostname localhost --skip-js-errors $BROWSER tests/spec", + "testcafe": "run-s testcafe-p testcafe-s", + "testcafe-p": "cross-env-shell testcafe --hostname localhost --skip-js-errors -c 4 $BROWSER tests/spec/0*", + "testcafe-s": "cross-env-shell testcafe --hostname localhost --skip-js-errors $BROWSER tests/spec/1*", "test": "cross-env BROWSER=chrome:headless npm run test-browser", - "test-browser": "run-p --race run-mastodon dev test-mastodon", - "test-mastodon": "run-s wait-for-mastodon-to-start wait-for-mastodon-data run-testcafe", + "test-browser": "run-p --race run-mastodon build-and-start test-mastodon", + "test-mastodon": "run-s wait-for-mastodon-to-start wait-for-mastodon-data testcafe", "wait-for-mastodon-to-start": "node -r esm bin/wait-for-mastodon-to-start.js", "wait-for-mastodon-data": "node -r esm bin/wait-for-mastodon-data.js", "globalize-css": "node ./bin/globalize-css.js", diff --git a/routes/_components/compose/ComposeToolbar.html b/routes/_components/compose/ComposeToolbar.html index 1083e150..e86a18ca 100644 --- a/routes/_components/compose/ComposeToolbar.html +++ b/routes/_components/compose/ComposeToolbar.html @@ -53,14 +53,13 @@ export default { oncreate () { - if (process.env.NODE_ENV !== 'production') { - window.__fakeFileInput = (file) => { - this.onFileChange({ - target: { - files: [file] - } - }) - } + // for testing + window.__fakeFileInput = (file) => { + this.onFileChange({ + target: { + files: [file] + } + }) } }, components: { diff --git a/routes/_store/store.js b/routes/_store/store.js index 2842c2f4..bccc71bb 100644 --- a/routes/_store/store.js +++ b/routes/_store/store.js @@ -58,3 +58,8 @@ observers(store) if (process.browser && process.env.NODE_ENV !== 'production') { window.store = store // for debugging } + +// needed for tests +if (process.browser) { + window.__forceOnline = online => store.set({online}) +} diff --git a/tests/roles.js b/tests/roles.js index 35e8d3b3..497bb906 100644 --- a/tests/roles.js +++ b/tests/roles.js @@ -1,4 +1,3 @@ -import { Role } from 'testcafe' import { authorizeInput, emailInput, getUrl, instanceInput, mastodonLogInButton, passwordInput, @@ -21,10 +20,21 @@ async function login (t, username, password) { .expect(getUrl()).eql('http://localhost:4002/', {timeout: 30000}) } -export const foobarRole = Role('http://localhost:4002/settings/instances/add', async t => { - await login(t, users.foobar.email, users.foobar.password) -}) +// roles appear not to be working anymore :( +// export const foobarRole = Role('http://localhost:4002/settings/instances/add', async t => { +// await login(t, users.foobar.email, users.foobar.password) +// }) +// +// export const lockedAccountRole = Role('http://localhost:4002/settings/instances/add', async t => { +// await login(t, users.LockedAccount.email, users.LockedAccount.password) +// }) -export const lockedAccountRole = Role('http://localhost:4002/settings/instances/add', async t => { +export async function loginAsFoobar (t) { + await t.navigateTo('/settings/instances/add') + await login(t, users.foobar.email, users.foobar.password) +} + +export async function loginAsLockedAccount (t) { + await t.navigateTo('/settings/instances/add') await login(t, users.LockedAccount.email, users.LockedAccount.password) -}) +} diff --git a/tests/spec/003-basic-timeline-spec.js b/tests/spec/003-basic-timeline-spec.js index 02b6ab4b..c89d149f 100644 --- a/tests/spec/003-basic-timeline-spec.js +++ b/tests/spec/003-basic-timeline-spec.js @@ -1,13 +1,18 @@ import { Selector as $ } from 'testcafe' -import { getFirstVisibleStatus, getNthStatus, getUrl, validateTimeline } from '../utils' +import { + communityNavButton, + getFirstVisibleStatus, getNthStatus, getUrl, localTimelineNavButton, notificationsNavButton, + validateTimeline +} from '../utils' import { homeTimeline, notifications, localTimeline, favorites } from '../fixtures' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`003-basic-timeline-spec.js` .page`http://localhost:4002` test('Shows the home timeline', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .expect(getFirstVisibleStatus().exists).ok() .expect(getFirstVisibleStatus().hasAttribute('aria-setsize')).ok() @@ -19,24 +24,27 @@ test('Shows the home timeline', async t => { }) test('Shows notifications', async t => { - await t.useRole(foobarRole) - .click($('nav a[aria-label=Notifications]')) + await loginAsFoobar(t) + await t + .click(notificationsNavButton) .expect(getUrl()).contains('/notifications') await validateTimeline(t, notifications) }) test('Shows the local timeline', async t => { - await t.useRole(foobarRole) - .click($('nav a[aria-label=Local]')) + await loginAsFoobar(t) + await t + .click(localTimelineNavButton) .expect(getUrl()).contains('/local') await validateTimeline(t, localTimeline) }) test('Shows the federated timeline', async t => { - await t.useRole(foobarRole) - .click($('nav a[aria-label=Community]')) + await loginAsFoobar(t) + await t + .click(communityNavButton) .expect(getUrl()).contains('/community') .click($('a').withText('Federated')) .expect(getUrl()).contains('/federated') @@ -45,8 +53,9 @@ test('Shows the federated timeline', async t => { }) test('Shows favorites', async t => { - await t.useRole(foobarRole) - .click($('nav a[aria-label=Community]')) + await loginAsFoobar(t) + await t + .click(communityNavButton) .expect(getUrl()).contains('/community') .click($('a').withText('Favorites')) .expect(getUrl()).contains('/favorites') diff --git a/tests/spec/004-pinned-statuses.js b/tests/spec/004-pinned-statuses.js index 583409f0..97c30683 100644 --- a/tests/spec/004-pinned-statuses.js +++ b/tests/spec/004-pinned-statuses.js @@ -1,12 +1,13 @@ import { Selector as $ } from 'testcafe' import { communityNavButton, getNthPinnedStatus, getUrl } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`004-pinned-statuses.js` .page`http://localhost:4002` test("shows a user's pinned statuses", async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(communityNavButton) .expect(getUrl()).contains('/community') .click($('a[href="/pinned"]')) @@ -17,7 +18,8 @@ test("shows a user's pinned statuses", async t => { }) test("shows pinned statuses on a user's account page", async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/2') .expect(getNthPinnedStatus(0).getAttribute('aria-posinset')).eql('0') .expect(getNthPinnedStatus(0).getAttribute('aria-setsize')).eql('1') @@ -25,7 +27,8 @@ test("shows pinned statuses on a user's account page", async t => { }) test("shows pinned statuses on a user's account page 2", async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/3') .expect(getNthPinnedStatus(0).getAttribute('aria-posinset')).eql('0') .expect(getNthPinnedStatus(0).getAttribute('aria-setsize')).eql('2') diff --git a/tests/spec/005-status-types.js b/tests/spec/005-status-types.js index 6ea4350d..58081c67 100644 --- a/tests/spec/005-status-types.js +++ b/tests/spec/005-status-types.js @@ -1,11 +1,12 @@ import { getNthStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`005-status-types.js` .page`http://localhost:4002` test('shows direct vs followers-only vs regular', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(getNthStatus(1).getAttribute('aria-label')).eql('Status by admin') .expect(getNthStatus(1).find('.status-content').innerText).contains('notification of unlisted message') .expect(getNthStatus(1).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label')) @@ -24,7 +25,8 @@ test('shows direct vs followers-only vs regular', async t => { }) test('shows direct vs followers-only vs regular in notifications', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/notifications') .expect(getNthStatus(2).getAttribute('aria-label')).eql('Status by admin') .expect(getNthStatus(2).find('.status-content').innerText).contains('notification of unlisted message') diff --git a/tests/spec/006-tabindex.js b/tests/spec/006-tabindex.js index 9e77248a..1d0e0a68 100644 --- a/tests/spec/006-tabindex.js +++ b/tests/spec/006-tabindex.js @@ -1,12 +1,13 @@ import { Selector as $ } from 'testcafe' import { getNthStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`006-tabindex.js` .page`http://localhost:4002` test('shows correct tabindex in home timeline', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(getNthStatus(0).getAttribute('tabindex')).eql('0') .expect(getNthStatus(1).getAttribute('tabindex')).eql('0') .expect(getNthStatus(2).getAttribute('tabindex')).eql('0') @@ -14,7 +15,8 @@ test('shows correct tabindex in home timeline', async t => { }) test('shows correct tabindex in notifications', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/notifications') .expect(getNthStatus(0).getAttribute('tabindex')).eql('0') .expect(getNthStatus(1).getAttribute('tabindex')).eql('0') @@ -31,7 +33,8 @@ test('shows correct tabindex in notifications', async t => { }) test('shows correct tabindex in pinned statuses', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/pinned') .expect($('.status-article').getAttribute('tabindex')).eql('0') .expect($('.status-article').getAttribute('aria-posinset')).eql('0') diff --git a/tests/spec/007-account-profile.js b/tests/spec/007-account-profile.js index 745e63c8..da9a4e53 100644 --- a/tests/spec/007-account-profile.js +++ b/tests/spec/007-account-profile.js @@ -4,14 +4,15 @@ import { accountProfileFollowedBy, accountProfileName, accountProfileUsername, getUrl, validateTimeline } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { quuxStatuses } from '../fixtures' fixture`007-account-profile.js` .page`http://localhost:4002` test('shows account profile', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click($('.status-author-name').withText(('quux'))) .expect(getUrl()).contains('/accounts/3') .expect(accountProfileName.innerText).contains('quux') @@ -22,7 +23,8 @@ test('shows account profile', async t => { }) test('shows account profile 2', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click($('.status-author-name').withText(('admin'))) .expect(getUrl()).contains('/accounts/1') .expect(accountProfileName.innerText).contains('admin') @@ -33,7 +35,8 @@ test('shows account profile 2', async t => { }) test('shows account profile 3', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click($('.mention').withText(('foobar'))) .expect(getUrl()).contains('/accounts/2') .expect(accountProfileName.innerText).contains('foobar') @@ -44,7 +47,8 @@ test('shows account profile 3', async t => { }) test('shows account profile statuses', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click($('.status-author-name').withText(('quux'))) .expect(getUrl()).contains('/accounts/3') .expect($('.pinned-statuses .status-article').getAttribute('aria-setsize')).eql('2') diff --git a/tests/spec/008-status-media.js b/tests/spec/008-status-media.js index f7cdfde2..3b5e4582 100644 --- a/tests/spec/008-status-media.js +++ b/tests/spec/008-status-media.js @@ -1,11 +1,11 @@ import { closeDialogButton, getNthStatus, modalDialogContents, scrollToStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`008-status-media.js` .page`http://localhost:4002` test('shows sensitive images and videos', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 7) await t.expect(getNthStatus(7).find('.status-media img').exists).notOk() .click(getNthStatus(7).find('.status-sensitive-media-button')) @@ -18,7 +18,7 @@ test('shows sensitive images and videos', async t => { }) test('click and close image and video modals', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 9) await t.expect(modalDialogContents.exists).notOk() .click(getNthStatus(9).find('.play-video-button')) diff --git a/tests/spec/009-threads.js b/tests/spec/009-threads.js index 87171ae2..626652cf 100644 --- a/tests/spec/009-threads.js +++ b/tests/spec/009-threads.js @@ -3,14 +3,15 @@ import { getNthStatus, getUrl, validateTimeline, scrollToBottomOfTimeline, getFirstVisibleStatus, goBack, forceOffline, forceOnline, searchNavButton, searchInput, getNthSearchResult } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { bazThreadRelativeTo2, bazThreadRelativeTo2b, bazThreadRelativeTo2B2, quuxThread } from '../fixtures' fixture`009-threads.js` .page`http://localhost:4002` test('Shows a thread', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click($('a').withText('quux')) await scrollToBottomOfTimeline(t) @@ -24,7 +25,8 @@ test('Shows a thread', async t => { }) test('Scrolls to proper point in thread', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click($('a').withText('quux')) .hover(getNthStatus(0)) .hover(getNthStatus(2)) @@ -69,7 +71,8 @@ async function validateForkedThread (t) { } test('Forked threads look correct online and offline', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getFirstVisibleStatus()) await navigateToBazAccount(t) await validateForkedThread(t) diff --git a/tests/spec/010-focus.js b/tests/spec/010-focus.js index e8e09afd..4bf11835 100644 --- a/tests/spec/010-focus.js +++ b/tests/spec/010-focus.js @@ -3,13 +3,13 @@ import { goBackButton, getActiveElementInnerText, getNthReplyButton, getActiveElementInsideNthStatus, focus, getNthStatusSelector } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`010-focus.js` .page`http://localhost:4002` test('modal preserves focus', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 9) // explicitly hover-focus-click await t.hover(getNthStatus(9).find('.play-video-button')) @@ -22,7 +22,7 @@ test('modal preserves focus', async t => { }) test('timeline preserves focus', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) // explicitly hover-focus-click await t.hover(getNthStatus(0)) await focus(getNthStatusSelector(0))() @@ -36,7 +36,8 @@ test('timeline preserves focus', async t => { }) test('timeline link preserves focus', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(getNthStatus(0).exists).ok({timeout: 20000}) .click(getNthStatus(0).find('.status-header a')) .expect(getUrl()).contains('/accounts/') @@ -53,7 +54,8 @@ test('timeline link preserves focus', async t => { }) test('notification timeline preserves focus', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/notifications') await scrollToStatus(t, 5) await t.click(getNthStatus(5).find('.status-header a')) @@ -66,7 +68,8 @@ test('notification timeline preserves focus', async t => { }) test('thread preserves focus', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/3') await scrollToStatus(t, 2) await t.click(getNthStatus(2)) @@ -87,7 +90,8 @@ test('thread preserves focus', async t => { }) test('reply preserves focus and moves focus to the text input', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(getNthStatus(1).exists).ok({timeout: 20000}) .click(getNthReplyButton(1)) .expect(getActiveElementClass()).contains('compose-box-input') diff --git a/tests/spec/011-reblog-favorites-count.js b/tests/spec/011-reblog-favorites-count.js index a6468409..f91b9ca7 100644 --- a/tests/spec/011-reblog-favorites-count.js +++ b/tests/spec/011-reblog-favorites-count.js @@ -3,13 +3,14 @@ import { favoritesCountElement, getFavoritesCount, getNthStatus, getReblogsCount, getUrl, reblogsCountElement } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`011-reblog-favorites-count.js` .page`http://localhost:4002` test('shows favorites', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(getNthStatus(0)) .expect(getUrl()).contains('/statuses/') .expect(getFavoritesCount()).eql(2) @@ -24,7 +25,8 @@ test('shows favorites', async t => { }) test('shows boosts', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(getNthStatus(0)) .expect(getUrl()).contains('/statuses/') .expect(getReblogsCount()).eql(1) diff --git a/tests/spec/012-compose.js b/tests/spec/012-compose.js index b760b061..a06516c0 100644 --- a/tests/spec/012-compose.js +++ b/tests/spec/012-compose.js @@ -5,13 +5,14 @@ import { notificationsNavButton, times } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`012-compose.js` .page`http://localhost:4002` test('shows compose limits', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .expect(composeLengthIndicator.innerText).eql('500') .expect(composeButton.hasAttribute('disabled')).notOk() @@ -37,7 +38,8 @@ test('shows compose limits', async t => { }) test('shows compose limits for URLs/handles', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(composeLengthIndicator.innerText).eql('500') .expect(composeButton.hasAttribute('disabled')).notOk() .typeText(composeInput, 'hello world ' + @@ -48,14 +50,16 @@ test('shows compose limits for URLs/handles', async t => { }) test('shows compose limits for emoji', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'hello world \ud83c\ude01 \ud83d\udc6a') .expect(composeLengthIndicator.innerText).eql('485') .expect(composeButton.hasAttribute('disabled')).notOk() }) test('shows compose limits for custom emoji', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'hello world ') .click(emojiButton) .click($('button img[title=":blobnom:"]')) @@ -64,7 +68,8 @@ test('shows compose limits for custom emoji', async t => { }) test('inserts custom emoji correctly', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'hello world') .selectText(composeInput, 6, 6) .expect(getComposeSelectionStart()).eql(6) @@ -83,7 +88,8 @@ test('inserts custom emoji correctly', async t => { }) test('inserts emoji without typing anything', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(emojiButton) .click($('button img[title=":blobpats:"]')) .expect(composeInput.value).eql(':blobpats: ') diff --git a/tests/spec/013-compose-media.js b/tests/spec/013-compose-media.js index 8d5d282e..9f53fde4 100644 --- a/tests/spec/013-compose-media.js +++ b/tests/spec/013-compose-media.js @@ -2,13 +2,14 @@ import { composeInput, getNthDeleteMediaButton, getNthMedia, mediaButton, uploadKittenImage } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`013-compose-media.js` .page`http://localhost:4002` test('inserts media', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.hasAttribute('disabled')).notOk() await (uploadKittenImage(1)()) await t.expect(getNthMedia(1).getAttribute('alt')).eql('kitten1.jpg') @@ -35,7 +36,8 @@ test('inserts media', async t => { }) test('removes media', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.exists).ok() await (uploadKittenImage(1)()) await t.expect(getNthMedia(1).getAttribute('alt')).eql('kitten1.jpg') @@ -50,7 +52,8 @@ test('removes media', async t => { }) test('changes URLs as media is added/removed', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.exists).ok() await (uploadKittenImage(1)()) await t.expect(composeInput.value).match(/^ http:\/\/localhost:3000\/media\/\S+$/) diff --git a/tests/spec/014-compose-post-privacy.js b/tests/spec/014-compose-post-privacy.js index f02222d7..bbc8568b 100644 --- a/tests/spec/014-compose-post-privacy.js +++ b/tests/spec/014-compose-post-privacy.js @@ -1,11 +1,12 @@ import { getNthPostPrivacyOptionInDialog, postPrivacyButton } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`014-compose-post-privacy.js` .page`http://localhost:4002` test('Changes post privacy', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(postPrivacyButton.getAttribute('aria-label')).eql('Adjust privacy (currently Public)') .click(postPrivacyButton) .click(getNthPostPrivacyOptionInDialog(2)) diff --git a/tests/spec/015-compose-content-warnings.js b/tests/spec/015-compose-content-warnings.js index 3a56912a..f6569e06 100644 --- a/tests/spec/015-compose-content-warnings.js +++ b/tests/spec/015-compose-content-warnings.js @@ -2,13 +2,14 @@ import { composeContentWarning, composeInput, composeLengthIndicator, contentWarningButton, homeNavButton, notificationsNavButton } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`015-compose-content-warnings.js` .page`http://localhost:4002` test('Changes content warnings', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(composeContentWarning.exists).notOk() .expect(contentWarningButton.getAttribute('aria-label')).eql('Add content warning') .expect(contentWarningButton.getAttribute('aria-pressed')).eql('false') @@ -37,7 +38,8 @@ test('Changes content warnings', async t => { }) test('Considers content warnings for length limits', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(composeLengthIndicator.innerText).eql('500') .click(contentWarningButton) .typeText(composeContentWarning, 'my content warning', {paste: true}) @@ -53,7 +55,8 @@ test('Considers content warnings for length limits', async t => { }) test('Content warning goes away if you hide it', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(contentWarningButton) .expect(composeContentWarning.value).eql('') .typeText(composeContentWarning, 'yo', {paste: true}) diff --git a/tests/spec/016-external-links.js b/tests/spec/016-external-links.js index 1146622b..b4252627 100644 --- a/tests/spec/016-external-links.js +++ b/tests/spec/016-external-links.js @@ -1,5 +1,5 @@ import { getNthStatus, getUrl } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { Selector as $ } from 'testcafe' fixture`016-external-links.js` @@ -14,7 +14,8 @@ function getAnchorInProfile (n) { } test('converts external links in statuses', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .navigateTo('/accounts/4') .expect(getUrl()).contains('/accounts/4') @@ -31,7 +32,8 @@ test('converts external links in statuses', async t => { }) test('converts external links in profiles', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .navigateTo('/accounts/4') .expect(getUrl()).contains('/accounts/4') diff --git a/tests/spec/017-compose-reply.js b/tests/spec/017-compose-reply.js index 91fc7991..7b4f9702 100644 --- a/tests/spec/017-compose-reply.js +++ b/tests/spec/017-compose-reply.js @@ -5,13 +5,14 @@ import { getNthReplyContentWarningInput, getNthReplyPostPrivacyButton, getNthStatus, getUrl, homeNavButton, notificationsNavButton, scrollToStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`017-compose-reply.js` .page`http://localhost:4002` test('account handle populated correctly for replies', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(getNthReplyButton(0)) .expect(getNthComposeReplyInput(0).value).eql('@quux ') .typeText(getNthComposeReplyInput(0), 'hello quux', {paste: true}) @@ -29,7 +30,8 @@ test('account handle populated correctly for replies', async t => { }) test('replying to posts with mentions', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(getNthReplyButton(1)) .expect(getNthComposeReplyInput(1).value).eql('@admin ') .navigateTo('/accounts/4') @@ -38,7 +40,8 @@ test('replying to posts with mentions', async t => { }) test('replies have same privacy as replied-to status by default', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .hover(getNthStatus(1)) .click(getNthReplyButton(1)) @@ -62,7 +65,7 @@ test('replies have same privacy as replied-to status by default', async t => { }) test('replies have same CW as replied-to status', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 7) await t.click(getNthReplyButton(7)) .expect(getNthReplyContentWarningInput(7).value).eql('kitten CW') @@ -72,7 +75,7 @@ test('replies have same CW as replied-to status', async t => { }) test('replies save deletions of CW', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 7) await t.click(getNthReplyButton(7)) .expect(getNthReplyContentWarningInput(7).value).eql('kitten CW') @@ -84,7 +87,7 @@ test('replies save deletions of CW', async t => { }) test('replies save changes to CW', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 7) await t.click(getNthReplyButton(7)) .expect(getNthReplyContentWarningInput(7).value).eql('kitten CW') @@ -96,7 +99,8 @@ test('replies save changes to CW', async t => { }) test('replies save changes to post privacy', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .hover(getNthStatus(1)) .click(getNthReplyButton(1)) diff --git a/tests/spec/018-compose-autosuggest.js b/tests/spec/018-compose-autosuggest.js index f1c3df2d..324d2491 100644 --- a/tests/spec/018-compose-autosuggest.js +++ b/tests/spec/018-compose-autosuggest.js @@ -2,7 +2,7 @@ import { composeInput, getNthAutosuggestionResult, getNthComposeReplyInput, getNthReplyButton, getNthStatus, sleep } from '../utils' import { Selector as $ } from 'testcafe' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`018-compose-autosuggest.js` .page`http://localhost:4002` @@ -10,7 +10,8 @@ fixture`018-compose-autosuggest.js` const timeout = 30000 test('autosuggests user handles', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) await sleep(1000) await t @@ -31,7 +32,8 @@ test('autosuggests user handles', async t => { }) test('autosuggests custom emoji', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, ':blob') .click(getNthAutosuggestionResult(1)) @@ -51,7 +53,8 @@ test('autosuggests custom emoji', async t => { }) test('autosuggest custom emoji works with regular emoji - keyboard', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, '\ud83c\udf4d :blobno') .expect(getNthAutosuggestionResult(1).innerText).contains(':blobnom:', {timeout}) @@ -60,7 +63,8 @@ test('autosuggest custom emoji works with regular emoji - keyboard', async t => }) test('autosuggest custom emoji works with regular emoji - clicking', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, '\ud83c\udf4d :blobno') .expect(getNthAutosuggestionResult(1).innerText).contains(':blobnom:', {timeout}) @@ -69,7 +73,8 @@ test('autosuggest custom emoji works with regular emoji - clicking', async t => }) test('autosuggest handles works with regular emoji - keyboard', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, '\ud83c\udf4d @quu') .expect(getNthAutosuggestionResult(1).innerText).contains('@quux', {timeout}) @@ -78,7 +83,8 @@ test('autosuggest handles works with regular emoji - keyboard', async t => { }) test('autosuggest handles works with regular emoji - clicking', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, '\ud83c\udf4d @quu') .expect(getNthAutosuggestionResult(1).innerText).contains('@quux', {timeout}) @@ -87,7 +93,8 @@ test('autosuggest handles works with regular emoji - clicking', async t => { }) test('autosuggest only shows for one input', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, '@quu') .hover(getNthStatus(0)) @@ -99,7 +106,8 @@ test('autosuggest only shows for one input', async t => { }) test('autosuggest only shows for one input part 2', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(composeInput) .typeText(composeInput, '@adm') .expect($('.compose-autosuggest.shown').exists).ok({timeout}) diff --git a/tests/spec/019-mention.js b/tests/spec/019-mention.js index 07b7903b..cd5a94c2 100644 --- a/tests/spec/019-mention.js +++ b/tests/spec/019-mention.js @@ -2,13 +2,14 @@ import { accountProfileMoreOptionsButton, closeDialogButton, getNthDialogOptionsOption, modalDialog } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`019-mention.js` .page`http://localhost:4002` test('can mention from account profile', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/5') .click(accountProfileMoreOptionsButton) .expect(getNthDialogOptionsOption(1).innerText).contains('Mention @baz') diff --git a/tests/spec/020-themes.js b/tests/spec/020-themes.js index d9f579f9..46bca071 100644 --- a/tests/spec/020-themes.js +++ b/tests/spec/020-themes.js @@ -1,14 +1,15 @@ import { settingsNavButton } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { Selector as $ } from 'testcafe' fixture`020-themes.js` .page`http://localhost:4002` test('can set a theme', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(settingsNavButton) .click($('a[href="/settings/instances"]')) .click($('a[href="/settings/instances/localhost:3000"]')) diff --git a/tests/spec/021-followers-follows.js b/tests/spec/021-followers-follows.js index 53368c15..cc2f0bef 100644 --- a/tests/spec/021-followers-follows.js +++ b/tests/spec/021-followers-follows.js @@ -3,13 +3,14 @@ import { followsButton, getNthSearchResult, getNthStatus, getUrl, goBack } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`021-followers-follows.js` .page`http://localhost:4002` test('shows followers and follows', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(getNthStatus(0).find('.status-author-name')) .expect(getUrl()).match(/\/accounts\/3$/) .expect(followsButton.getAttribute('aria-label')).eql('Follows 2') diff --git a/tests/spec/100-favorite-unfavorite.js b/tests/spec/100-favorite-unfavorite.js index 1ed7cc87..6c1aad9f 100644 --- a/tests/spec/100-favorite-unfavorite.js +++ b/tests/spec/100-favorite-unfavorite.js @@ -3,13 +3,14 @@ import { getNthFavoriteButton, getNthFavorited, getNthStatus, getUrl, homeNavButton, notificationsNavButton, scrollToBottomOfTimeline, scrollToTopOfTimeline } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`100-favorite-unfavorite.js` .page`http://localhost:4002` test('favorites a status', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(4)) .expect(getNthFavorited(4)).eql('false') .click(getNthFavoriteButton(4)) @@ -35,7 +36,8 @@ test('favorites a status', async t => { }) test('unfavorites a status', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(getNthFavorited(1)).eql('true') .click(getNthFavoriteButton(1)) .expect(getNthFavorited(1)).eql('false') @@ -56,7 +58,8 @@ test('unfavorites a status', async t => { }) test('Keeps the correct favorites count', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(4)) .click(getNthFavoriteButton(4)) .expect(getNthFavorited(4)).eql('true') diff --git a/tests/spec/101-reblog-unreblog.js b/tests/spec/101-reblog-unreblog.js index fb06d068..008ac50b 100644 --- a/tests/spec/101-reblog-unreblog.js +++ b/tests/spec/101-reblog-unreblog.js @@ -3,13 +3,14 @@ import { notificationsNavButton, scrollToBottomOfTimeline, scrollToTopOfTimeline } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`101-reblog-unreblog.js` .page`http://localhost:4002` test('reblogs a status', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .expect(getNthReblogged(0)).eql('false') .click(getNthReblogButton(0)) @@ -34,7 +35,8 @@ test('reblogs a status', async t => { }) test('unreblogs a status', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(4)) .expect(getNthReblogged(4)).eql('false') .click(getNthReblogButton(4)) @@ -59,7 +61,8 @@ test('unreblogs a status', async t => { }) test('Keeps the correct reblogs count', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(4)) .expect(getNthReblogged(4)).eql('true') .click(getNthStatus(4)) diff --git a/tests/spec/102-notifications.js b/tests/spec/102-notifications.js index a7551dd2..08ba0566 100644 --- a/tests/spec/102-notifications.js +++ b/tests/spec/102-notifications.js @@ -1,4 +1,4 @@ -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { getNthStatus, getUrl, homeNavButton, notificationsNavButton, validateTimeline } from '../utils' import { favoriteStatusAs } from '../serverActions' import { notifications } from '../fixtures' @@ -7,7 +7,8 @@ fixture`102-notifications.js` .page`http://localhost:4002` test('shows unread notifications', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .hover(getNthStatus(2)) .hover(getNthStatus(4)) diff --git a/tests/spec/103-compose.js b/tests/spec/103-compose.js index 7a492462..11afa42a 100644 --- a/tests/spec/103-compose.js +++ b/tests/spec/103-compose.js @@ -1,4 +1,4 @@ -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { composeInput, getNthComposeReplyButton, getNthComposeReplyInput, getNthReplyButton, getNthStatus, getUrl, homeNavButton, notificationsNavButton, @@ -9,7 +9,8 @@ fixture`103-compose.js` .page`http://localhost:4002` test('statuses show up in home timeline', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'hello world', {paste: true}) .click(postStatusButton) .expect(getNthStatus(0).innerText).contains('hello world') @@ -23,7 +24,8 @@ test('statuses show up in home timeline', async t => { }) test('statuses in threads show up in right order', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/5') .click(getNthStatus(2)) .expect(getUrl()).contains('/statuses') diff --git a/tests/spec/104-streaming.js b/tests/spec/104-streaming.js index 80377460..f1b25945 100644 --- a/tests/spec/104-streaming.js +++ b/tests/spec/104-streaming.js @@ -1,4 +1,4 @@ -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { getNthStatus, scrollContainerToTop, showMoreButton, sleep } from '../utils' @@ -8,14 +8,16 @@ fixture`104-streaming.js` .page`http://localhost:4002` test('new incoming statuses show up immediately', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) await postAs('admin', 'hello my baby hello my honey') await t.expect(getNthStatus(0).innerText).contains('hello my baby hello my honey') }) test('new incoming toots show a button if scrolled down', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .hover(getNthStatus(2)) .hover(getNthStatus(4)) diff --git a/tests/spec/105-deletes.js b/tests/spec/105-deletes.js index 04bc801d..359c6ba7 100644 --- a/tests/spec/105-deletes.js +++ b/tests/spec/105-deletes.js @@ -1,4 +1,4 @@ -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { clickToNotificationsAndBackHome, forceOffline, forceOnline, getNthStatus, getUrl, homeNavButton, notificationsNavButton @@ -10,7 +10,8 @@ fixture`105-deletes.js` test('deleted statuses are removed from the timeline', async t => { let timeout = 20000 - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) let status = await postAs('admin', "I'm gonna delete this") await t.expect(getNthStatus(0).innerText).contains("I'm gonna delete this", {timeout}) @@ -30,7 +31,8 @@ test('deleted statuses are removed from the timeline', async t => { test('deleted statuses are removed from threads', async t => { let timeout = 20000 - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) let status = await postAs('admin', "I won't delete this") let reply = await postReplyAs('admin', 'But I will delete this', status.id) @@ -54,7 +56,8 @@ test('deleted statuses are removed from threads', async t => { test('deleted statuses result in deleted notifications', async t => { let timeout = 20000 - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .hover(getNthStatus(0)) .expect(notificationsNavButton.getAttribute('aria-label')).eql('Notifications') let status = await postAs('admin', "@foobar yo yo foobar what's up") diff --git a/tests/spec/106-follow-requests.js b/tests/spec/106-follow-requests.js index c166ac1f..1e4a574b 100644 --- a/tests/spec/106-follow-requests.js +++ b/tests/spec/106-follow-requests.js @@ -1,4 +1,4 @@ -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { accountProfileFollowButton, getNthStatus, @@ -12,7 +12,8 @@ fixture`106-follow-requests.js` .page`http://localhost:4002` test('can request to follow an account', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/6') .expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow') .click(accountProfileFollowButton) diff --git a/tests/spec/107-streaming-gap.js b/tests/spec/107-streaming-gap.js index 720b7fcc..63705495 100644 --- a/tests/spec/107-streaming-gap.js +++ b/tests/spec/107-streaming-gap.js @@ -1,4 +1,4 @@ -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { getNthStatus, homeNavButton, localTimelineNavButton, sleep } from '../utils' @@ -12,7 +12,8 @@ fixture`107-streaming-gap.js` test('fills in a status posted while away from timeline', async t => { let timeout = 30000 - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(localTimelineNavButton) .expect(getNthStatus(0).exists).ok({timeout}) .hover(getNthStatus(0)) diff --git a/tests/spec/108-compose-dialog.js b/tests/spec/108-compose-dialog.js index b47ea51f..c7a06961 100644 --- a/tests/spec/108-compose-dialog.js +++ b/tests/spec/108-compose-dialog.js @@ -2,14 +2,14 @@ import { composeButton, getNthStatus, scrollToStatus, modalDialog, sleep, notificationsNavButton, getUrl } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { Selector as $ } from 'testcafe' fixture`108-compose-dialog.js` .page`http://localhost:4002` test('can compose using a dialog', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 15) await t.expect(modalDialog.exists).notOk() .expect(composeButton.getAttribute('aria-label')).eql('Compose') @@ -27,7 +27,7 @@ test('can compose using a dialog', async t => { }) test('can use emoji dialog within compose dialog', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) await scrollToStatus(t, 15) await t.expect(composeButton.getAttribute('aria-label')).eql('Compose') await sleep(2000) diff --git a/tests/spec/109-compose-media.js b/tests/spec/109-compose-media.js index 3b152237..86fe5846 100644 --- a/tests/spec/109-compose-media.js +++ b/tests/spec/109-compose-media.js @@ -4,7 +4,7 @@ import { mediaButton, notificationsNavButton, uploadKittenImage } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`109-compose-media.js` .page`http://localhost:4002` @@ -18,7 +18,8 @@ async function uploadTwoKittens (t) { } test('uploads alts for media', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.hasAttribute('disabled')).notOk() await uploadTwoKittens(t) await t.typeText(getNthMediaAltInput(2), 'kitten 2') @@ -31,7 +32,8 @@ test('uploads alts for media', async t => { }) test('uploads alts when deleting and re-uploading media', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.hasAttribute('disabled')).notOk() await (uploadKittenImage(1)()) await t.typeText(getNthMediaAltInput(1), 'this will be deleted') @@ -46,7 +48,8 @@ test('uploads alts when deleting and re-uploading media', async t => { }) test('uploads alts mixed with no-alts', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.hasAttribute('disabled')).notOk() await uploadTwoKittens(t) await t.typeText(getNthMediaAltInput(2), 'kitten numero dos') @@ -56,7 +59,8 @@ test('uploads alts mixed with no-alts', async t => { }) test('saves alts to local storage', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(mediaButton.hasAttribute('disabled')).notOk() await uploadTwoKittens(t) await t.typeText(getNthMediaAltInput(1), 'kitten numero uno') diff --git a/tests/spec/110-compose-content-warnings.js b/tests/spec/110-compose-content-warnings.js index aad177a2..7e9b145e 100644 --- a/tests/spec/110-compose-content-warnings.js +++ b/tests/spec/110-compose-content-warnings.js @@ -2,13 +2,14 @@ import { composeButton, composeContentWarning, composeInput, contentWarningButton, getNthShowOrHideButton, getNthStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`110-compose-content-warnings.js` .page`http://localhost:4002` test('content warnings are posted', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'hello this is a toot', {paste: true}) .click(contentWarningButton) .typeText(composeContentWarning, 'CW', {paste: true}) @@ -21,7 +22,8 @@ test('content warnings are posted', async t => { }) test('content warnings are not posted if removed', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'hi this is another toot', {paste: true}) .click(contentWarningButton) .typeText(composeContentWarning, 'content warning!', {paste: true}) @@ -34,7 +36,8 @@ test('content warnings are not posted if removed', async t => { }) test('content warnings can have emoji', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'I can: :blobnom:') .click(contentWarningButton) .typeText(composeContentWarning, 'can you feel the :blobpats: tonight') @@ -48,7 +51,8 @@ test('content warnings can have emoji', async t => { test('no XSS in content warnings or text', async t => { let pwned1 = `` let pwned2 = `` - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, pwned1) .click(contentWarningButton) .typeText(composeContentWarning, pwned2) diff --git a/tests/spec/111-focus.js b/tests/spec/111-focus.js index 5b73ce06..74e35ec6 100644 --- a/tests/spec/111-focus.js +++ b/tests/spec/111-focus.js @@ -4,13 +4,14 @@ import { getNthComposeReplyInput, getNthReplyButton, getNthStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`111-focus.js` .page`http://localhost:4002` test('replying to a toot returns focus to reply button', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, 'I would like, if I may, to take you on a strange journey', {paste: true}) .pressKey('ctrl+enter') .expect(getNthStatus(0).find('.status-content').innerText).contains('I would like, if I may, to take you on a strange journey') diff --git a/tests/spec/112-status-links.js b/tests/spec/112-status-links.js index ea17412b..f61999aa 100644 --- a/tests/spec/112-status-links.js +++ b/tests/spec/112-status-links.js @@ -3,7 +3,7 @@ import { composeInput, getNthStatus } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`112-status-links.js` .page`http://localhost:4002` @@ -16,7 +16,8 @@ test('External links, hashtags, and mentions have correct attributes', async t = const nthAnchor = n => getNthStatus(0).find('.status-content a').nth(n) - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .typeText(composeInput, text, {paste: true}) .click(composeButton) .expect(getNthStatus(0).innerText).contains('Why hello there', {timeout: 20000}) diff --git a/tests/spec/113-block-unblock.js b/tests/spec/113-block-unblock.js index 71cc3181..45aaf878 100644 --- a/tests/spec/113-block-unblock.js +++ b/tests/spec/113-block-unblock.js @@ -4,7 +4,7 @@ import { getNthStatus, getNthStatusOptionsButton, getNthDialogOptionsOption, getUrl, modalDialog } from '../utils' import { Selector as $ } from 'testcafe' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { postAs } from '../serverActions' fixture`113-block-unblock.js` @@ -13,7 +13,8 @@ fixture`113-block-unblock.js` test('Can block and unblock an account from a status', async t => { let post = 'a very silly statement that should probably get me blocked' await postAs('admin', post) - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .expect(getNthStatus(0).innerText).contains(post, {timeout: 30000}) .click(getNthStatusOptionsButton(0)) .expect(getNthDialogOptionsOption(1).innerText).contains('Unfollow @admin') @@ -35,7 +36,8 @@ test('Can block and unblock an account from a status', async t => { }) test('Can block and unblock an account from the account profile page', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/5') .expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow') .click(accountProfileMoreOptionsButton) diff --git a/tests/spec/114-mute-unmute.js b/tests/spec/114-mute-unmute.js index f5afabd3..8e640782 100644 --- a/tests/spec/114-mute-unmute.js +++ b/tests/spec/114-mute-unmute.js @@ -4,14 +4,14 @@ import { getNthStatus, getNthStatusOptionsButton, getNthDialogOptionsOption, getUrl, modalDialog, closeDialogButton } from '../utils' import { Selector as $ } from 'testcafe' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' import { postAs } from '../serverActions' fixture`114-mute-unmute.js` .page`http://localhost:4002` test('Can mute and unmute an account', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) let post = 'blah blah blah' await postAs('admin', post) diff --git a/tests/spec/115-follow-unfollow.js b/tests/spec/115-follow-unfollow.js index 0395dba9..170d462a 100644 --- a/tests/spec/115-follow-unfollow.js +++ b/tests/spec/115-follow-unfollow.js @@ -3,13 +3,14 @@ import { accountProfileMoreOptionsButton, closeDialogButton, getNthDialogOptionsOption } from '../utils' -import { foobarRole } from '../roles' +import { loginAsFoobar } from '../roles' fixture`115-follow-unfollow.js` .page`http://localhost:4002` test('Can follow and unfollow an account from the profile page', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .navigateTo('/accounts/5') .expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow') .click(accountProfileMoreOptionsButton) diff --git a/tests/spec/116-follow-requests.js b/tests/spec/116-follow-requests.js index 5287b7e5..16eb7226 100644 --- a/tests/spec/116-follow-requests.js +++ b/tests/spec/116-follow-requests.js @@ -1,4 +1,4 @@ -import { lockedAccountRole } from '../roles' +import { loginAsLockedAccount } from '../roles' import { followAs, unfollowAs } from '../serverActions' import { avatarInComposeBox, @@ -14,7 +14,7 @@ fixture`116-follow-requests.js` const timeout = 30000 test('Can approve and reject follow requests', async t => { - await t.useRole(lockedAccountRole) + await loginAsLockedAccount(t) // necessary for re-running this test in local testing await Promise.all([ diff --git a/tests/spec/117-pin-unpin.js b/tests/spec/117-pin-unpin.js index b4049ea0..35d35011 100644 --- a/tests/spec/117-pin-unpin.js +++ b/tests/spec/117-pin-unpin.js @@ -1,8 +1,8 @@ -import { foobarRole } from '../roles' -import { postAs } from '../serverActions' +import { loginAsFoobar } from '../roles' import { - avatarInComposeBox, getNthDialogOptionsOption, getNthPinnedStatus, getNthPinnedStatusFavoriteButton, getNthStatus, - getNthStatusOptionsButton, getUrl, sleep + avatarInComposeBox, composeInput, getNthDialogOptionsOption, getNthPinnedStatus, getNthPinnedStatusFavoriteButton, + getNthStatus, + getNthStatusOptionsButton, getUrl, postStatusButton } from '../utils' import { users } from '../users' @@ -10,13 +10,12 @@ fixture`117-pin-unpin.js` .page`http://localhost:4002` test('Can pin statuses', async t => { - await t.useRole(foobarRole) - - await postAs('foobar', 'I am going to pin this') - - await sleep(2000) - - await t.click(avatarInComposeBox) + await loginAsFoobar(t) + await t + .typeText(composeInput, 'I am going to pin this', {paste: true}) + .click(postStatusButton) + .expect(getNthStatus(0).innerText).contains('I am going to pin this') + .click(avatarInComposeBox) .expect(getUrl()).contains(`/accounts/${users.foobar.id}`) .expect(getNthPinnedStatus(0).getAttribute('aria-setsize')).eql('1') .expect(getNthPinnedStatus(0).innerText).contains('this is unlisted') @@ -40,7 +39,8 @@ test('Can pin statuses', async t => { }) test('Can favorite a pinned status', async t => { - await t.useRole(foobarRole) + await loginAsFoobar(t) + await t .click(avatarInComposeBox) .expect(getNthPinnedStatus(0).getAttribute('aria-setsize')).eql('1') .expect(getNthPinnedStatusFavoriteButton(0).getAttribute('aria-pressed')).eql('false') diff --git a/tests/utils.js b/tests/utils.js index ebc464da..e8e86294 100644 --- a/tests/utils.js +++ b/tests/utils.js @@ -2,8 +2,6 @@ import { ClientFunction as exec, Selector as $ } from 'testcafe' import * as images from './images' import * as blobUtils from './blobUtils' -const SCROLL_INTERVAL = 1 - export const settingsButton = $('nav a[aria-label=Settings]') export const instanceInput = $('#instanceInput') export const modalDialog = $('.modal-dialog') @@ -80,9 +78,9 @@ export const getActiveElementInsideNthStatus = exec(() => { export const goBack = exec(() => window.history.back()) -export const forceOffline = exec(() => window.store.set({online: false})) +export const forceOffline = exec(() => window.__forceOnline(false)) -export const forceOnline = exec(() => window.store.set({online: true})) +export const forceOnline = exec(() => window.__forceOnline(true)) export const getComposeSelectionStart = exec(() => composeInput().selectionStart, { dependencies: { composeInput } @@ -157,6 +155,18 @@ export function getNthStatusSelector (n) { return `div[aria-hidden="false"] > article[aria-posinset="${n}"]` } +export function getNthStatusContent (n) { + return $(`${getNthStatusSelector(n)} .status-content`) +} + +export function getNthStatusSpoiler (n) { + return $(`${getNthStatusSelector(n)} .status-spoiler`) +} + +export function getNthStatusHeader (n) { + return $(`${getNthStatusSelector(n)} .status-header`) +} + export function getNthStatusAndImage (nStatus, nImage) { return getNthStatus(nStatus).find(`.status-media .show-image-button:nth-child(${nImage + 1}) img`) } @@ -234,36 +244,31 @@ export function getNthPinnedStatusFavoriteButton (n) { } export async function validateTimeline (t, timeline) { - const timeout = 20000 + const timeout = 30000 for (let i = 0; i < timeline.length; i++) { let status = timeline[i] - await t.expect(getNthStatus(i).exists).ok({ timeout }) + // hovering forces TestCafé to scroll to that element: https://git.io/vABV2 + await t.hover(getNthStatus(i)) if (status.content) { - await t.expect(getNthStatus(i).find('.status-content p').innerText) + await t.expect(getNthStatusContent(i).innerText) .contains(status.content, { timeout }) } if (status.spoiler) { - await t.expect(getNthStatus(i).find('.status-spoiler p').innerText) + await t.expect(getNthStatusSpoiler(i).innerText) .contains(status.spoiler, { timeout }) } if (status.followedBy) { - await t.expect(getNthStatus(i).find('.status-header span').innerText) + await t.expect(getNthStatusHeader(i).innerText) .contains(status.followedBy + ' followed you', { timeout }) } if (status.rebloggedBy) { - await t.expect(getNthStatus(i).find('.status-header span').innerText) + await t.expect(getNthStatusHeader(i).innerText) .contains(status.rebloggedBy + ' boosted your status', { timeout }) } if (status.favoritedBy) { - await t.expect(getNthStatus(i).find('.status-header span').innerText) + await t.expect(getNthStatusHeader(i).innerText) .contains(status.favoritedBy + ' favorited your status', { timeout }) } - - // hovering forces TestCafé to scroll to that element: https://git.io/vABV2 - if (i % SCROLL_INTERVAL === (SCROLL_INTERVAL - 1)) { // only scroll every nth element - await t.hover(getNthStatus(i)) - .expect($('.loading-footer').exist).notOk() - } } } @@ -272,8 +277,7 @@ export async function scrollToTopOfTimeline (t) { while (true) { await t.hover(getNthStatus(i)) .expect($('.loading-footer').exist).notOk() - i -= SCROLL_INTERVAL - if (i <= 0) { + if (--i <= 0) { break } } @@ -285,8 +289,7 @@ export async function scrollToBottomOfTimeline (t) { await t.hover(getNthStatus(i)) .expect($('.loading-footer').exist).notOk() let size = await getNthStatus(i).getAttribute('aria-setsize') - i += SCROLL_INTERVAL - if (i >= size - 1) { + if (++i >= size - 1) { break } } @@ -294,7 +297,7 @@ export async function scrollToBottomOfTimeline (t) { export async function scrollToStatus (t, n) { let timeout = 20000 - for (let i = 0; i <= n; i += SCROLL_INTERVAL) { + for (let i = 0; i <= n; i++) { await t.expect(getNthStatus(i).exists).ok({timeout}) .hover(getNthStatus(i)) .expect($('.loading-footer').exist).notOk()