diff --git a/.maestro/config.yml b/__e2e__/config.yml similarity index 100% rename from .maestro/config.yml rename to __e2e__/config.yml diff --git a/__e2e__/flows/composer-self-label.yml b/__e2e__/flows/composer-self-label.yml new file mode 100644 index 0000000000..cc38b1d995 --- /dev/null +++ b/__e2e__/flows/composer-self-label.yml @@ -0,0 +1,30 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: ?users +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eSignInAlice" + +# Post an image with the porn label +- tapOn: + id: "composeFAB" +- inputText: "Post with an image" +- tapOn: + id: "openGalleryBtn" +- tapOn: + id: "labelsBtn" +- tapOn: + label: "Tap on porn" + point: 78%,67% +- tapOn: + label: "Tap on confirm" + point: 51%,92% +- tapOn: + id: "composerPublishBtn" +- tapOn: + id: "e2eRefreshHome" +- assertVisible: "Adult Content" \ No newline at end of file diff --git a/.maestro/flows/composer.yml b/__e2e__/flows/composer.yml similarity index 100% rename from .maestro/flows/composer.yml rename to __e2e__/flows/composer.yml diff --git a/.maestro/flows/create-account.yml b/__e2e__/flows/create-account.yml similarity index 100% rename from .maestro/flows/create-account.yml rename to __e2e__/flows/create-account.yml diff --git a/.maestro/flows/curate-lists.yml b/__e2e__/flows/curate-lists.yml similarity index 100% rename from .maestro/flows/curate-lists.yml rename to __e2e__/flows/curate-lists.yml diff --git a/.maestro/flows/home-screen.yml b/__e2e__/flows/home-screen.yml similarity index 100% rename from .maestro/flows/home-screen.yml rename to __e2e__/flows/home-screen.yml diff --git a/__e2e__/flows/login.yml b/__e2e__/flows/login.yml new file mode 100644 index 0000000000..f1001f78da --- /dev/null +++ b/__e2e__/flows/login.yml @@ -0,0 +1,26 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users" +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eOpenLoggedOutView" +- tapOn: "Sign in" +- tapOn: + id: "selectServiceButton" +- tapOn: "Custom" +- tapOn: + id: "customServerTextInput" +- inputText: "http://localhost:3000" +- tapOn: "Done" +- tapOn: + id: "loginUsernameInput" +- inputText: "Alice" +- tapOn: + id: "loginPasswordInput" +- inputText: "hunter2" +- pressKey: Enter +- assertVisible: "Following" \ No newline at end of file diff --git a/__e2e__/flows/mod-lists.yml b/__e2e__/flows/mod-lists.yml new file mode 100644 index 0000000000..75ee100a83 --- /dev/null +++ b/__e2e__/flows/mod-lists.yml @@ -0,0 +1,45 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users&follows&labels" +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eSignInAlice" + +# create a modlist +- tapOn: + id: "e2eGotoModeration" +- tapOn: + id: "moderationlistsBtn" +- tapOn: "New" +- tapOn: + id: "editNameInput" +- inputText: "Muted Users" +- tapOn: + id: "editDescriptionInput" +- inputText: "Shhh" +- tapOn: "Save" +- tapOn: "Save" + +# view modlist +- assertVisible: "Muted Users" +- assertVisible: "Shhh" + +# toggle mute subscription +- tapOn: + point: "70%,9%" +- tapOn: "Mute accounts" +- tapOn: "Mute list" +- tapOn: "Unmute" + +# toggle block subscription +- tapOn: + point: "70%,9%" +- tapOn: "Block accounts" +- tapOn: "Block list" +- tapOn: "Unblock" + + # the rest of the behaviors are tested in curate-lists.yml \ No newline at end of file diff --git a/__e2e__/flows/profile-screen-edit.yml b/__e2e__/flows/profile-screen-edit.yml new file mode 100644 index 0000000000..602cc66887 --- /dev/null +++ b/__e2e__/flows/profile-screen-edit.yml @@ -0,0 +1,119 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users&posts&feeds" +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eSignInAlice" + + +# Navigate to my profile +- tapOn: + id: "bottomBarProfileBtn" + +# Can see feeds +- swipe: + from: + id: "profilePager-selector" + direction: LEFT +- tapOn: + id: "profilePager-selector-4" +- assertVisible: + id: "feed-alice-favs" +- swipe: + from: + id: "profilePager-selector" + direction: RIGHT +- tapOn: + id: "profilePager-selector-0" + +# Open and close edit profile modal +- tapOn: + id: "profileHeaderEditProfileButton" +- assertVisible: + id: "editProfileModal" +- tapOn: + id: "editProfileCancelBtn" +- assertNotVisible: + id: "editProfileModal" + +# Edit display name and description via the edit profile modal +- tapOn: + id: "profileHeaderEditProfileButton" +- assertVisible: + id: "editProfileModal" +- tapOn: + id: "editProfileDisplayNameInput" +- eraseText +- inputText: "Alicia" +- tapOn: + id: "editProfileDescriptionInput" +- eraseText +- inputText: "One cool hacker" +- tapOn: "Description" +- tapOn: + id: "editProfileSaveBtn" +- assertNotVisible: + id: "editProfileModal" +- assertVisible: "Alicia" +- assertVisible: "One cool hacker" + +# Remove display name and description via the edit profile modal +- tapOn: + id: "profileHeaderEditProfileButton" +- assertVisible: + id: "editProfileModal" +- tapOn: + id: "editProfileDisplayNameInput" +- eraseText +- tapOn: + id: "editProfileDescriptionInput" +- eraseText +- tapOn: "Description" +- tapOn: + id: "editProfileSaveBtn" +- assertNotVisible: + id: "editProfileModal" +- assertVisible: "alice.test" +- assertNotVisible: "One cool hacker" + +# Set avi and banner via the edit profile modal +- assertVisible: + id: "userBannerFallback" +- tapOn: + id: "profileHeaderEditProfileButton" +- assertVisible: + id: "editProfileModal" +- tapOn: + id: "changeBannerBtn" +- tapOn: "Upload from Library" +- tapOn: + id: "changeAvatarBtn" +- tapOn: "Upload from Library" +- tapOn: + id: "editProfileSaveBtn" +- assertNotVisible: + id: "editProfileModal" +- assertVisible: + id: "userBannerImage" + +# # Remove avi and banner via the edit profile modal +- tapOn: + id: "profileHeaderEditProfileButton" +- assertVisible: + id: "editProfileModal" +- tapOn: + id: "changeBannerBtn" +- tapOn: "Remove Banner" +- tapOn: + id: "changeAvatarBtn" +- tapOn: "Remove Avatar" +- tapOn: + id: "editProfileSaveBtn" +- assertNotVisible: + id: "editProfileModal" +- assertVisible: + id: "userBannerFallback" diff --git a/__e2e__/flows/profile-screen.yml b/__e2e__/flows/profile-screen.yml new file mode 100644 index 0000000000..7d2d43deea --- /dev/null +++ b/__e2e__/flows/profile-screen.yml @@ -0,0 +1,37 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users&posts&feeds" +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eSignInAlice" + +# Navigate to another user profile +- tapOn: + id: "bottomBarSearchBtn" +- tapOn: + id: "searchTextInput" +- inputText: "b" +- tapOn: + id: "searchAutoCompleteResult-bob.test" +- assertVisible: + id: "profileView" + +# Can follow/unfollow another user +- tapOn: + id: "followBtn" +- tapOn: + id: "unfollowBtn" + +# Can mute/unmute another user +- tapOn: + id: "profileHeaderDropdownBtn" +- tapOn: "Mute Account" +- assertVisible: "Account Muted" +- tapOn: + id: "profileHeaderDropdownBtn" +- tapOn: "Unmute Account" +- assertNotVisible: "Account Muted" \ No newline at end of file diff --git a/__e2e__/flows/search-screen.yml b/__e2e__/flows/search-screen.yml new file mode 100644 index 0000000000..0d31d03fb9 --- /dev/null +++ b/__e2e__/flows/search-screen.yml @@ -0,0 +1,22 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users" +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eSignInAlice" + +# Navigate to another user profile via autocomplete +- tapOn: + id: "bottomBarSearchBtn" +- tapOn: + id: "searchTextInput" +- inputText: "b" +- tapOn: + id: "searchAutoCompleteResult-bob.test" +- assertVisible: + id: "profileView" + diff --git a/__e2e__/flows/thread-muting.yml b/__e2e__/flows/thread-muting.yml new file mode 100644 index 0000000000..316389a79f --- /dev/null +++ b/__e2e__/flows/thread-muting.yml @@ -0,0 +1,82 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users&follows" +- runFlow: + file: ../setupApp.yml + + +# Login, create a thread, and log out +- tapOn: + id: "e2eSignInAlice" +- tapOn: + id: "composeFAB" +- inputText: "Test thread" +- tapOn: + id: "composerPublishBtn" + +# Login, reply to the thread, and log out +- tapOn: + id: "e2eSignInBob" +- tapOn: + id: "replyBtn" +- inputText: "Reply 1" +- tapOn: + id: "composerPublishBtn" + +# Login, confirm notification exists, mute thread, and log out +- tapOn: + id: "e2eSignInAlice" +- tapOn: + id: "bottomBarNotificationsBtn" +- assertVisible: + id: "feedItem-by-bob.test" +- tapOn: + id: "feedItem-by-bob.test" +- tapOn: + id: "postDropdownBtn" + childOf: + id: "postThreadItem-by-bob.test" +- tapOn: "Mute thread" + +# Login, reply to the thread twice, and log out +- tapOn: + id: "e2eSignInBob" +- tapOn: + id: "bottomBarProfileBtn" +- tapOn: + id: "profilePager-selector-1" +- tapOn: + id: "replyBtn" +- inputText: "Reply 2" +- tapOn: + id: "composerPublishBtn" +- tapOn: + id: "replyBtn" +- inputText: "Reply 3" +- tapOn: + id: "composerPublishBtn" + + +# Login, confirm notifications dont exist, unmute the thread, confirm notifications exist +- tapOn: + id: "e2eSignInAlice" +- tapOn: + id: "bottomBarNotificationsBtn" +- assertNotVisible: + id: "feedItem-by-bob.test" +- tapOn: + id: "bottomBarHomeBtn" +- tapOn: + id: "postDropdownBtn" +- tapOn: "Unmute thread" +- tapOn: + id: "bottomBarNotificationsBtn" +- swipe: + from: + id: "notifsFeed" + direction: DOWN +- assertVisible: + id: "feedItem-by-bob.test" diff --git a/__e2e__/flows/thread-screen.yml b/__e2e__/flows/thread-screen.yml new file mode 100644 index 0000000000..22f71345db --- /dev/null +++ b/__e2e__/flows/thread-screen.yml @@ -0,0 +1,84 @@ +appId: xyz.blueskyweb.app +--- +- runScript: + file: ../setupServer.js + env: + SERVER_PATH: "?users&follows&thread" +- runFlow: + file: ../setupApp.yml +- tapOn: + id: "e2eSignInAlice" + + +# Navigate to thread +- tapOn: "Thread root" +- assertVisible: "Thread reply" + +# Can like the root post +- tapOn: + id: "likeBtn" + childOf: + id: "postThreadItem-by-bob.test" +- assertVisible: + id: "likeCount-expanded" +- tapOn: + id: "likeBtn" + childOf: + id: "postThreadItem-by-bob.test" +- assertNotVisible: + id: "likeCount-expanded" + +# Can like a reply post +- tapOn: + id: "likeBtn" + childOf: + id: "postThreadItem-by-carla.test" +- assertVisible: + id: "likeCount" + childOf: + id: "postThreadItem-by-carla.test" +- tapOn: + id: "likeBtn" + childOf: + id: "postThreadItem-by-carla.test" +- assertNotVisible: + id: "likeCount" + childOf: + id: "postThreadItem-by-carla.test" + +# Can repost the root post +- tapOn: + id: "repostBtn" + childOf: + id: "postThreadItem-by-bob.test" +- tapOn: "Repost" +- assertVisible: + id: "repostCount-expanded" +- tapOn: + id: "repostBtn" + childOf: + id: "postThreadItem-by-bob.test" +- tapOn: "Undo repost" +- assertNotVisible: + id: "repostCount-expanded" + + +# Can repost a reply post +- tapOn: + id: "repostBtn" + childOf: + id: "postThreadItem-by-carla.test" +- tapOn: "Repost" +- assertVisible: + id: "repostCount" + childOf: + id: "postThreadItem-by-carla.test" +- tapOn: + id: "repostBtn" + childOf: + id: "postThreadItem-by-carla.test" +- tapOn: "Undo repost" +- assertNotVisible: + id: "repostCount" + childOf: + id: "postThreadItem-by-carla.test" diff --git a/__e2e__/jest.config.js b/__e2e__/jest.config.js deleted file mode 100644 index 80c2ad5b3a..0000000000 --- a/__e2e__/jest.config.js +++ /dev/null @@ -1,12 +0,0 @@ -/** @type {import('@jest/types').Config.InitialOptions} */ -module.exports = { - rootDir: '..', - testMatch: ['/__e2e__/**/*.test.ts'], - testTimeout: 120000, - maxWorkers: 1, - globalSetup: 'detox/runners/jest/globalSetup', - globalTeardown: 'detox/runners/jest/globalTeardown', - reporters: ['detox/runners/jest/reporter'], - testEnvironment: 'detox/runners/jest/testEnvironment', - verbose: true, -} diff --git a/__e2e__/maestro/scroll.yaml b/__e2e__/perf-test.yml similarity index 100% rename from __e2e__/maestro/scroll.yaml rename to __e2e__/perf-test.yml index 2d32793eb0..7a7b7a18c9 100644 --- a/__e2e__/maestro/scroll.yaml +++ b/__e2e__/perf-test.yml @@ -1,3 +1,4 @@ + # flow.yaml appId: xyz.blueskyweb.app @@ -74,4 +75,3 @@ appId: xyz.blueskyweb.app - "scroll" - "scroll" - "scroll" - diff --git a/.maestro/setupApp.yml b/__e2e__/setupApp.yml similarity index 100% rename from .maestro/setupApp.yml rename to __e2e__/setupApp.yml diff --git a/.maestro/setupServer.js b/__e2e__/setupServer.js similarity index 79% rename from .maestro/setupServer.js rename to __e2e__/setupServer.js index 78c82603c8..7b1fb95745 100644 --- a/.maestro/setupServer.js +++ b/__e2e__/setupServer.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line http.post('http://localhost:1986/' + SERVER_PATH, { headers: {'Content-Type': 'text/plain'}, body: '', diff --git a/__e2e__/tests/composer.test.ts b/__e2e__/tests/composer.test.ts deleted file mode 100644 index 06781410f6..0000000000 --- a/__e2e__/tests/composer.test.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* eslint-env detox/detox */ - -import {beforeAll, describe, it} from '@jest/globals' -import {expect} from 'detox' - -import {createServer, loginAsAlice, openApp, sleep} from '../util' - -describe('Composer', () => { - beforeAll(async () => { - await createServer('?users') - await openApp({ - permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'}, - }) - }) - - it('Login', async () => { - await loginAsAlice() - await element(by.id('homeScreenFeedTabs-Following')).tap() - }) - - it('Post text only', async () => { - await element(by.id('composeFAB')).tap() - await device.takeScreenshot('1- opened composer') - await element(by.id('composerTextInput')).typeText('Post text only') - await device.takeScreenshot('2- entered text') - await element(by.id('composerPublishBtn')).tap() - await device.takeScreenshot('3- opened general section') - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Post with an image', async () => { - await element(by.id('composeFAB')).tap() - await element(by.id('composerTextInput')).typeText('Post with an image') - await element(by.id('openGalleryBtn')).tap() - await sleep(1e3) - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Post with a link card', async () => { - await element(by.id('composeFAB')).tap() - await element(by.id('composerTextInput')).typeText( - 'Post with a https://example.com link card', - ) - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Reply text only', async () => { - await element(by.id('e2eRefreshHome')).tap() - - const post = by.id('feedItem-by-alice.test') - await element(by.id('replyBtn').withAncestor(post)).atIndex(0).tap() - await element(by.id('composerTextInput')).typeText('Reply text only') - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Reply with an image', async () => { - const post = by.id('feedItem-by-alice.test') - await element(by.id('replyBtn').withAncestor(post)).atIndex(0).tap() - await element(by.id('composerTextInput')).typeText('Reply with an image') - await element(by.id('openGalleryBtn')).tap() - await sleep(1e3) - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Reply with a link card', async () => { - const post = by.id('feedItem-by-alice.test') - await element(by.id('replyBtn').withAncestor(post)).atIndex(0).tap() - await element(by.id('composerTextInput')).typeText( - 'Reply with a https://example.com link card', - ) - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('QP text only', async () => { - const post = by.id('feedItem-by-alice.test') - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await element(by.id('quoteBtn').withAncestor(by.id('repostModal'))).tap() - await element(by.id('composerTextInput')).typeText('QP text only') - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('QP with an image', async () => { - const post = by.id('feedItem-by-alice.test') - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await element(by.id('quoteBtn').withAncestor(by.id('repostModal'))).tap() - await element(by.id('composerTextInput')).typeText('QP with an image') - await element(by.id('openGalleryBtn')).tap() - await sleep(1e3) - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('QP with a link card', async () => { - const post = by.id('feedItem-by-alice.test') - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await element(by.id('quoteBtn').withAncestor(by.id('repostModal'))).tap() - await element(by.id('composerTextInput')).typeText( - 'QP with a https://example.com link card', - ) - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) -}) diff --git a/__e2e__/tests/create-account.test.ts b/__e2e__/tests/create-account.test.ts deleted file mode 100644 index 9c56c914ea..0000000000 --- a/__e2e__/tests/create-account.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, createServer} from '../util' - -describe('Create account', () => { - let service: string - beforeAll(async () => { - service = await createServer('') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('I can create a new account', async () => { - await element(by.id('e2eOpenLoggedOutView')).tap() - - await element(by.id('createAccountButton')).tap() - await device.takeScreenshot('1- opened create account screen') - await element(by.id('selectServiceButton')).tap() - await device.takeScreenshot('2- selected other server') - await element(by.id('customSelectBtn')).tap() - await element(by.id('customServerTextInput')).typeText(service) - await element(by.id('customServerTextInput')).tapReturnKey() - await element(by.id('doneBtn')).tap() - await device.takeScreenshot('3- input test server URL') - await element(by.id('emailInput')).typeText('example@test.com') - await element(by.id('passwordInput')).typeText('hunter2') - await device.takeScreenshot('4- entered account details') - - await element(by.id('nextBtn')).tap() - - await element(by.id('handleInput')).typeText('e2e-test') - await device.takeScreenshot('5- entered handle') - - await element(by.id('nextBtn')).tap() - - await expect(element(by.id('onboardingInterests'))).toBeVisible() - }) -}) diff --git a/__e2e__/tests/curate-lists.test.ts b/__e2e__/tests/curate-lists.test.ts deleted file mode 100644 index 635357b8d2..0000000000 --- a/__e2e__/tests/curate-lists.test.ts +++ /dev/null @@ -1,213 +0,0 @@ -/* eslint-env detox/detox */ - -import {beforeAll, describe, it} from '@jest/globals' -import {expect} from 'detox' - -import {createServer, loginAsAlice, loginAsBob, openApp, sleep} from '../util' - -describe('Curate lists', () => { - beforeAll(async () => { - await createServer('?users&follows&posts') - await openApp({ - permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'}, - }) - }) - - it('Login and create a curatelists', async () => { - await loginAsAlice() - await element(by.id('e2eGotoLists')).tap() - await element(by.id('newUserListBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editNameInput')).typeText('Good Ppl') - await element(by.id('editDescriptionInput')).typeText('They good') - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await element(by.text('About')).tap() - await expect(element(by.id('headerTitle'))).toHaveText('Good Ppl') - await expect(element(by.id('listDescription'))).toHaveText('They good') - }) - - it('Edit display name and description via the edit curatelist modal', async () => { - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Edit list details')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editNameInput')).clearText() - await element(by.id('editNameInput')).typeText('Bad Ppl') - await element(by.id('editDescriptionInput')).clearText() - await element(by.id('editDescriptionInput')).typeText('They bad') - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('headerTitle'))).toHaveText('Bad Ppl') - await expect(element(by.id('listDescription'))).toHaveText('They bad') - // have to wait for the toast to clear - await waitFor(element(by.id('headerDropdownBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - it('Remove description via the edit curatelist modal', async () => { - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Edit list details')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editDescriptionInput')).clearText() - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('listDescription'))).not.toBeVisible() - // have to wait for the toast to clear - await waitFor(element(by.id('headerDropdownBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - it('Set avi via the edit curatelist modal', async () => { - await expect(element(by.id('userAvatarFallback'))).toExist() - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Edit list details')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('changeAvatarBtn')).tap() - await element(by.text('Upload from Library')).tap() - await sleep(3e3) - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('userAvatarImage'))).toExist() - // have to wait for the toast to clear - await waitFor(element(by.id('headerDropdownBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - it('Remove avi via the edit curatelist modal', async () => { - await expect(element(by.id('userAvatarImage'))).toExist() - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Edit list details')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('changeAvatarBtn')).tap() - await element(by.text('Remove Avatar')).tap() - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('userAvatarFallback'))).toExist() - // have to wait for the toast to clear - await waitFor(element(by.id('headerDropdownBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - it('Delete the curatelist', async () => { - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Delete List')).tap() - await element(by.id('confirmBtn')).tap() - await expect(element(by.id('listsEmpty'))).toBeVisible() - }) - - it('Create a new curatelist', async () => { - await element(by.id('e2eGotoLists')).tap() - await element(by.id('newUserListBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editNameInput')).typeText('Good Ppl') - await element(by.id('editDescriptionInput')).typeText('They good') - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await element(by.text('About')).tap() - await expect(element(by.id('headerTitle'))).toHaveText('Good Ppl') - await expect(element(by.id('listDescription'))).toHaveText('They good') - }) - - it('Adds users on curatelists from the list', async () => { - await element(by.text('About')).tap() - await element(by.id('addUserBtn')).tap() - await expect(element(by.id('listAddUserModal'))).toBeVisible() - await element(by.id('searchInput')).typeText('b') - await waitFor(element(by.id('user-bob.test-addBtn'))) - .toBeVisible() - .withTimeout(5000) - await element(by.id('user-bob.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('listAddUserModal'))).not.toBeVisible() - await expect(element(by.id('user-bob.test'))).toBeVisible() - }) - - it('Shows posts by the users in the list', async () => { - await element(by.text('Posts')).tap() - await expect(element(by.id('feedItem-by-bob.test'))).toBeVisible() - }) - - it('Pins the list', async () => { - await expect(element(by.id('pinBtn'))).toBeVisible() - await element(by.id('pinBtn')).tap() - await element(by.id('e2eGotoHome')).tap() - await element(by.id('homeScreenFeedTabs-Good Ppl')).tap() - await expect(element(by.id('feedItem-by-bob.test'))).toBeVisible() - - await element(by.id('bottomBarFeedsBtn')).tap() - await element(by.id('saved-feed-Good Ppl')).tap() - await expect(element(by.id('feedItem-by-bob.test'))).toBeVisible() - - await element(by.id('unpinBtn')).tap() - await element(by.id('bottomBarHomeBtn')).tap() - await expect( - element(by.id('homeScreenFeedTabs-Good Ppl')), - ).not.toBeVisible() - - await element(by.id('e2eGotoLists')).tap() - await element(by.id('list-Good Ppl')).tap() - }) - - it('Removes users on curatelists from the list', async () => { - await element(by.text('About')).tap() - await expect(element(by.id('user-bob.test'))).toBeVisible() - await element(by.id('user-bob.test-editBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible() - await element(by.id('user-bob.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible() - }) - - it('Shows the curatelist on my profile', async () => { - await element(by.id('bottomBarProfileBtn')).tap() - await element(by.id('profilePager-selector')).swipe('left') - await element(by.id('profilePager-selector-5')).tap() - await element(by.id('list-Good Ppl')).tap() - }) - - it('Adds and removes users on curatelists from the profile', async () => { - await element(by.id('bottomBarSearchBtn')).tap() - await element(by.id('searchTextInput')).typeText('bob') - await element(by.id('searchAutoCompleteResult-bob.test')).tap() - await expect(element(by.id('profileView'))).toBeVisible() - - await element(by.id('profileHeaderDropdownBtn')).tap() - await element(by.text('Add to Lists')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible() - await element(by.id('user-bob.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible() - - await element(by.id('profileHeaderDropdownBtn')).tap() - await element(by.text('Add to Lists')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible() - await element(by.id('user-bob.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible() - }) - - it('Can report a user list', async () => { - await element(by.id('e2eGotoSettings')).tap() - await element(by.id('signOutBtn')).tap() - await loginAsBob() - await element(by.id('bottomBarSearchBtn')).tap() - await element(by.id('searchTextInput')).typeText('alice') - await element(by.id('searchAutoCompleteResult-alice.test')).tap() - await element(by.id('profilePager-selector')).swipe('left') - await element(by.id('profilePager-selector-3')).tap() - await element(by.id('list-Good Ppl')).tap() - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Report List')).tap() - await expect(element(by.id('reportModal'))).toBeVisible() - await expect(element(by.text('Report List'))).toBeVisible() - await element( - by.id('reportReasonRadios-com.atproto.moderation.defs#reasonRude'), - ).tap() - await element(by.id('sendReportBtn')).tap() - await expect(element(by.id('reportModal'))).not.toBeVisible() - }) -}) diff --git a/__e2e__/tests/home-screen.test.ts b/__e2e__/tests/home-screen.test.ts deleted file mode 100644 index b594c46978..0000000000 --- a/__e2e__/tests/home-screen.test.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* eslint-env detox/detox */ - -import {beforeAll, describe, it} from '@jest/globals' -import {expect} from 'detox' - -import {createServer, loginAsAlice, openApp} from '../util' - -describe('Home screen', () => { - beforeAll(async () => { - await createServer('?users&follows&posts&feeds') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('Login', async () => { - await loginAsAlice() - await element(by.id('homeScreenFeedTabs-Following')).tap() - }) - - it('Can go to feeds page using feeds button in tab bar', async () => { - await element(by.id('homeScreenFeedTabs-Feeds ✨')).tap() - await expect(element(by.text('Discover New Feeds'))).toBeVisible() - }) - - it('Feeds button disappears after pinning a feed', async () => { - await element(by.id('bottomBarProfileBtn')).tap() - await element(by.id('profilePager-selector')).swipe('left') - await element(by.id('profilePager-selector-4')).tap() - await element(by.id('feed-alice-favs')).tap() - await element(by.id('pinBtn')).tap() - await element(by.id('bottomBarHomeBtn')).tap() - await expect( - element(by.id('homeScreenFeedTabs-Feeds ✨')), - ).not.toBeVisible() - }) - - it('Can like posts', async () => { - const carlaPosts = by.id('feedItem-by-carla.test') - await expect( - element(by.id('likeCount').withAncestor(carlaPosts)).atIndex(0), - ).not.toExist() - await element(by.id('likeBtn').withAncestor(carlaPosts)).atIndex(0).tap() - await expect( - element(by.id('likeCount').withAncestor(carlaPosts)).atIndex(0), - ).toHaveText('1') - await element(by.id('likeBtn').withAncestor(carlaPosts)).atIndex(0).tap() - await expect( - element(by.id('likeCount').withAncestor(carlaPosts)).atIndex(0), - ).not.toExist() - }) - - it('Can repost posts', async () => { - const carlaPosts = by.id('feedItem-by-carla.test') - await expect( - element(by.id('repostCount').withAncestor(carlaPosts)).atIndex(0), - ).not.toExist() - await element(by.id('repostBtn').withAncestor(carlaPosts)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount').withAncestor(carlaPosts)).atIndex(0), - ).toHaveText('1') - await element(by.id('repostBtn').withAncestor(carlaPosts)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount').withAncestor(carlaPosts)).atIndex(0), - ).not.toExist() - }) - - // TODO skipping because the test env PDS isnt setup correctly to handle the report -prf - // it('Can report posts', async () => { - // const carlaPosts = by.id('feedItem-by-carla.test') - // await element(by.id('postDropdownBtn').withAncestor(carlaPosts)) - // .atIndex(0) - // .tap() - // await element(by.text('Report post')).tap() - // await element(by.id('com.atproto.moderation.defs#reasonSpam')).tap() - // await element(by.id('sendReportBtn')).tap() - // }) - - it('Can swipe between feeds', async () => { - await element(by.id('homeScreen')).swipe('left', 'fast', 0.75) - await expect(element(by.id('customFeedPage'))).toBeVisible() - await element(by.id('homeScreen')).swipe('right', 'fast', 0.75) - await expect(element(by.id('followingFeedPage'))).toBeVisible() - }) - - it('Can tap between feeds', async () => { - await element(by.id('homeScreenFeedTabs-alice-favs')).tap() - await expect(element(by.id('customFeedPage'))).toBeVisible() - await element(by.id('homeScreenFeedTabs-Following')).tap() - await expect(element(by.id('followingFeedPage'))).toBeVisible() - }) - - it('Can delete posts', async () => { - const alicePosts = by.id('feedItem-by-alice.test') - await expect(element(alicePosts.withDescendant(by.text('Post')))).toExist() - await element(by.id('postDropdownBtn').withAncestor(alicePosts)) - .atIndex(0) - .tap() - await element(by.text('Delete post')).tap() - await expect(element(by.id('confirmModal'))).toBeVisible() - await element(by.id('confirmBtn')).tap() - await expect( - element(alicePosts.withDescendant(by.text('Post'))), - ).not.toExist() - }) -}) diff --git a/__e2e__/tests/invite-codes.test.skip.ts b/__e2e__/tests/invite-codes.test.skip.ts deleted file mode 100644 index 9f00f05255..0000000000 --- a/__e2e__/tests/invite-codes.test.skip.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-env detox/detox */ - -import {beforeAll, describe, it} from '@jest/globals' -import {expect} from 'detox' - -import {createServer, loginAsAlice, openApp} from '../util' - -describe('invite-codes', () => { - let service: string - let inviteCode = '' - beforeAll(async () => { - service = await createServer('?users&invite') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('I can fetch invite codes', async () => { - await loginAsAlice() - await element(by.id('e2eOpenInviteCodesModal')).tap() - await expect(element(by.id('inviteCodesModal'))).toBeVisible() - const attrs = await element(by.id('inviteCode-0-code')).getAttributes() - inviteCode = attrs.text - await element(by.id('closeBtn')).tap() - await element(by.id('e2eSignOut')).tap() - }) - - it('I can create a new account with the invite code', async () => { - await element(by.id('e2eOpenLoggedOutView')).tap() - await element(by.id('createAccountButton')).tap() - await device.takeScreenshot('1- opened create account screen') - await element(by.id('selectServiceButton')).tap() - await device.takeScreenshot('2- selected other server') - await element(by.id('customSelectBtn')).tap() - await element(by.id('customServerTextInput')).typeText(service) - await element(by.id('customServerTextInput')).tapReturnKey() - await element(by.id('doneBtn')).tap() - await device.takeScreenshot('3- input test server URL') - await element(by.id('inviteCodeInput')).typeText(inviteCode) - await element(by.id('emailInput')).typeText('example@test.com') - await element(by.id('passwordInput')).typeText('hunter2') - await device.takeScreenshot('4- entered account details') - await element(by.id('nextBtn')).tap() - await element(by.id('handleInput')).typeText('e2e-test') - await device.takeScreenshot('4- entered handle') - await element(by.id('nextBtn')).tap() - await expect(element(by.id('onboardingInterests'))).toBeVisible() - }) -}) diff --git a/__e2e__/tests/login.test.ts b/__e2e__/tests/login.test.ts deleted file mode 100644 index b4cedef6c4..0000000000 --- a/__e2e__/tests/login.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, login, createServer} from '../util' - -describe('Login', () => { - let service: string - beforeAll(async () => { - service = await createServer('?users') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('As Alice, I can login', async () => { - await element(by.id('e2eOpenLoggedOutView')).tap() - - await expect(element(by.id('signInButton'))).toBeVisible() - await login(service, 'alice', 'hunter2', { - takeScreenshots: true, - }) - await device.takeScreenshot('5- opened home screen') - }) -}) diff --git a/__e2e__/tests/merge-feed.test.skip.ts b/__e2e__/tests/merge-feed.test.skip.ts deleted file mode 100644 index 4a8b3cbcef..0000000000 --- a/__e2e__/tests/merge-feed.test.skip.ts +++ /dev/null @@ -1,163 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, loginAsAlice, createServer} from '../util' - -describe('Mergefeed', () => { - beforeAll(async () => { - await createServer('?mergefeed') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('Login', async () => { - await element(by.id('e2eOpenLoggedOutView')).tap() - await loginAsAlice() - await element(by.id('e2eToggleMergefeed')).tap() - await element(by.id('bottomBarFeedsBtn')).tap() - await element(by.id('feed-alice-favs-toggleSave')).tap() - await element(by.id('e2eGotoHome')).tap() - }) - - it('Sees the expected mix of posts with default filters', async () => { - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'slow', - 1, - 0.5, - 0.5, - ) - // followed users - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-carla.test')), - ).atIndex(0), - ).toHaveText('Post 9') - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-bob.test')), - ).atIndex(0), - ).toHaveText('Post 9') - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'up', - 'fast', - 1, - 0.5, - 0.5, - ) - // feed users - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-dan.test')), - ).atIndex(0), - ).toHaveText('Post 0') - }) - - it('Sees the expected mix of posts with replies disabled', async () => { - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'fast', - 1, - 0.5, - 0.5, - ) - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'fast', - 1, - 0.5, - 0.5, - ) - await element(by.id('viewHeaderHomeFeedPrefsBtn')).tap() - await element(by.id('toggleRepliesBtn')).tap() - await element(by.id('confirmBtn')).tap() - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'slow', - 1, - 0.5, - 0.5, - ) - - // followed users - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-carla.test')), - ).atIndex(0), - ).toHaveText('Post 9') - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-bob.test')), - ).atIndex(0), - ).toHaveText('Post 9') - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'up', - 'fast', - 1, - 0.5, - 0.5, - ) - - // feed users - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-dan.test')), - ).atIndex(0), - ).toHaveText('Post 0') - }) - - it('Sees the expected mix of posts with no follows', async () => { - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'fast', - 1, - 0.5, - 0.5, - ) - - await element(by.id('bottomBarSearchBtn')).tap() - await element(by.id('searchTextInput')).typeText('bob') - await element(by.id('searchAutoCompleteResult-bob.test')).tap() - await expect(element(by.id('profileView'))).toBeVisible() - await element(by.id('unfollowBtn')).tap() - await element(by.id('profileHeaderBackBtn')).tap() - - // have to wait for the toast to clear - await waitFor(element(by.id('searchTextInputClearBtn'))) - .toBeVisible() - .withTimeout(5000) - await element(by.id('searchTextInputClearBtn')).tap() - await element(by.id('searchTextInput')).typeText('carla') - await element(by.id('searchAutoCompleteResult-carla.test')).tap() - await expect(element(by.id('profileView'))).toBeVisible() - await element(by.id('unfollowBtn')).tap() - await element(by.id('profileHeaderBackBtn')).tap() - - await element(by.id('bottomBarHomeBtn')).tap() - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'slow', - 1, - 0.5, - 0.5, - ) - await element(by.id('followingFeedPage-feed-flatlist')).swipe( - 'down', - 'slow', - 1, - 0.5, - 0.5, - ) - - // followed users NOT present - await expect(element(by.id('feedItem-by-carla.test'))).not.toExist() - await expect(element(by.id('feedItem-by-bob.test'))).not.toExist() - - // feed users - await expect( - element( - by.id('postText').withAncestor(by.id('feedItem-by-dan.test')), - ).atIndex(0), - ).toHaveText('Post 0') - }) -}) diff --git a/__e2e__/tests/mod-lists.test.ts b/__e2e__/tests/mod-lists.test.ts deleted file mode 100644 index c3d4149e09..0000000000 --- a/__e2e__/tests/mod-lists.test.ts +++ /dev/null @@ -1,189 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, loginAsAlice, loginAsBob, createServer} from '../util' - -describe('Mod lists', () => { - beforeAll(async () => { - await createServer('?users&follows&labels') - await openApp({ - permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'}, - }) - }) - - it('Login and view my modlists', async () => { - await loginAsAlice() - await element(by.id('e2eGotoModeration')).tap() - await element(by.id('moderationlistsBtn')).tap() - await expect(element(by.id('list-Muted Users'))).toBeVisible() - await element(by.id('list-Muted Users')).tap() - await expect( - element(by.id('user-muted-by-list-account.test')), - ).toBeVisible() - }) - - it('Toggle mute subscription', async () => { - await element(by.id('unmuteBtn')).tap() - await element(by.id('subscribeBtn')).tap() - await element(by.text('Mute accounts')).tap() - await element(by.id('confirmBtn')).tap() - }) - - it('Edit display name and description via the edit modlist modal', async () => { - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Edit list details')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editNameInput')).clearText() - await element(by.id('editNameInput')).typeText('Bad Ppl') - await element(by.id('editDescriptionInput')).clearText() - await element(by.id('editDescriptionInput')).typeText('They bad') - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('headerTitle'))).toHaveText('Bad Ppl') - await expect(element(by.id('listDescription'))).toHaveText('They bad') - // have to wait for the toast to clear - await waitFor(element(by.id('headerDropdownBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - it('Remove description via the edit modlist modal', async () => { - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Edit list details')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editDescriptionInput')).clearText() - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('listDescription'))).not.toBeVisible() - // have to wait for the toast to clear - await waitFor(element(by.id('headerDropdownBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - // DISABLED e2e environment is real finicky about avatar uploads -prf - // it('Set avi via the edit modlist modal', async () => { - // await expect(element(by.id('userAvatarFallback'))).toExist() - // await element(by.id('headerDropdownBtn')).tap() - // await element(by.text('Edit list details')).tap() - // await expect(element(by.id('createOrEditListModal'))).toBeVisible() - // await element(by.id('changeAvatarBtn')).tap() - // await element(by.text('Library')).tap() - // await sleep(3e3) - // await element(by.id('saveBtn')).tap() - // await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - // await expect(element(by.id('userAvatarImage'))).toExist() - // // have to wait for the toast to clear - // await waitFor(element(by.id('headerDropdownBtn'))) - // .toBeVisible() - // .withTimeout(5000) - // }) - - // it('Remove avi via the edit modlist modal', async () => { - // await expect(element(by.id('userAvatarImage'))).toExist() - // await element(by.id('headerDropdownBtn')).tap() - // await element(by.text('Edit list details')).tap() - // await expect(element(by.id('createOrEditListModal'))).toBeVisible() - // await element(by.id('changeAvatarBtn')).tap() - // await element(by.text('Remove')).tap() - // await element(by.id('saveBtn')).tap() - // await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - // await expect(element(by.id('userAvatarFallback'))).toExist() - // // have to wait for the toast to clear - // await waitFor(element(by.id('headerDropdownBtn'))) - // .toBeVisible() - // .withTimeout(5000) - // }) - - it('Delete the modlist', async () => { - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Delete List')).tap() - await element(by.id('confirmBtn')).tap() - await expect(element(by.id('listsEmpty'))).toBeVisible() - }) - - it('Create a new modlist', async () => { - await element(by.id('newModListBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).toBeVisible() - await element(by.id('editNameInput')).typeText('Bad Ppl') - await element(by.id('editDescriptionInput')).typeText('They bad') - await element(by.id('saveBtn')).tap() - await expect(element(by.id('createOrEditListModal'))).not.toBeVisible() - await expect(element(by.id('headerTitle'))).toHaveText('Bad Ppl') - await expect(element(by.id('listDescription'))).toHaveText('They bad') - }) - - it('Adds and removes users on modlists from the list', async () => { - await element(by.id('addUserBtn')).tap() - await expect(element(by.id('listAddUserModal'))).toBeVisible() - await waitFor(element(by.id('user-warn-posts.test-addBtn'))) - .toBeVisible() - .withTimeout(5000) - await element(by.id('user-warn-posts.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('listAddUserModal'))).not.toBeVisible() - await element(by.id('listItems-flatlist')).swipe( - 'down', - 'slow', - 1, - 0.5, - 0.5, - ) - await expect(element(by.id('user-warn-posts.test'))).toBeVisible() - await element(by.id('user-warn-posts.test-editBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible() - await element(by.id('user-warn-posts.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible() - }) - - it('Shows the modlist on my profile', async () => { - await element(by.id('bottomBarProfileBtn')).tap() - await element(by.id('profilePager-selector')).swipe('left') - await element(by.id('profilePager-selector-5')).tap() - await element(by.id('list-Bad Ppl')).tap() - }) - - it('Adds and removes users on modlists from the profile', async () => { - await element(by.id('bottomBarSearchBtn')).tap() - await element(by.id('searchTextInput')).typeText('bob') - await element(by.id('searchAutoCompleteResult-bob.test')).tap() - await expect(element(by.id('profileView'))).toBeVisible() - - await element(by.id('profileHeaderDropdownBtn')).tap() - await element(by.text('Add to Lists')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible() - await element(by.id('user-bob.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible() - - await element(by.id('profileHeaderDropdownBtn')).tap() - await element(by.text('Add to Lists')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible() - await element(by.id('user-bob.test-addBtn')).tap() - await element(by.id('doneBtn')).tap() - await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible() - }) - - it('Can report a mute list', async () => { - await element(by.id('e2eGotoSettings')).tap() - await element(by.id('signOutBtn')).tap() - await loginAsBob() - await element(by.id('bottomBarSearchBtn')).tap() - await element(by.id('searchTextInput')).typeText('alice') - await element(by.id('searchAutoCompleteResult-alice.test')).tap() - await element(by.id('profilePager-selector')).swipe('left') - await element(by.id('profilePager-selector-3')).tap() - await element(by.id('list-Bad Ppl')).tap() - await element(by.id('headerDropdownBtn')).tap() - await element(by.text('Report List')).tap() - await expect(element(by.id('reportModal'))).toBeVisible() - await expect(element(by.text('Report List'))).toBeVisible() - await element( - by.id('reportReasonRadios-com.atproto.moderation.defs#reasonRude'), - ).tap() - await element(by.id('sendReportBtn')).tap() - await expect(element(by.id('reportModal'))).not.toBeVisible() - }) -}) diff --git a/__e2e__/tests/profile-screen.test.ts b/__e2e__/tests/profile-screen.test.ts deleted file mode 100644 index 7c3207ec83..0000000000 --- a/__e2e__/tests/profile-screen.test.ts +++ /dev/null @@ -1,196 +0,0 @@ -/* eslint-env detox/detox */ - -import {beforeAll, describe, it} from '@jest/globals' -import {expect} from 'detox' - -import {createServer, loginAsAlice, openApp, sleep} from '../util' - -describe('Profile screen', () => { - beforeAll(async () => { - await createServer('?users&posts&feeds') - await openApp({ - permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'}, - }) - }) - - it('Login and navigate to my profile', async () => { - await loginAsAlice() - await element(by.id('bottomBarProfileBtn')).tap() - }) - - it('Can see feeds', async () => { - await element(by.id('profilePager-selector')).swipe('left') - await element(by.id('profilePager-selector-4')).tap() - await expect(element(by.id('feed-alice-favs'))).toBeVisible() - await element(by.id('profilePager-selector')).swipe('right') - await element(by.id('profilePager-selector-0')).tap() - }) - - it('Open and close edit profile modal', async () => { - await element(by.id('profileHeaderEditProfileButton')).tap() - await expect(element(by.id('editProfileModal'))).toBeVisible() - await element(by.id('editProfileCancelBtn')).tap() - await expect(element(by.id('editProfileModal'))).not.toBeVisible() - }) - - it('Edit display name and description via the edit profile modal', async () => { - await element(by.id('profileHeaderEditProfileButton')).tap() - await expect(element(by.id('editProfileModal'))).toBeVisible() - await element(by.id('editProfileDisplayNameInput')).clearText() - await element(by.id('editProfileDisplayNameInput')).typeText('Alicia') - await element(by.id('editProfileDescriptionInput')).clearText() - await element(by.id('editProfileDescriptionInput')).typeText( - 'One cool hacker', - ) - await element(by.id('editProfileSaveBtn')).tap() - await expect(element(by.id('editProfileModal'))).not.toBeVisible() - await expect(element(by.id('profileHeaderDisplayName'))).toHaveText( - 'Alicia', - ) - await expect(element(by.id('profileHeaderDescription'))).toHaveText( - 'One cool hacker', - ) - }) - - it('Remove display name and description via the edit profile modal', async () => { - await element(by.id('profileHeaderEditProfileButton')).tap() - await expect(element(by.id('editProfileModal'))).toBeVisible() - await element(by.id('editProfileDisplayNameInput')).clearText() - await element(by.id('editProfileDescriptionInput')).clearText() - await element(by.id('editProfileSaveBtn')).tap() - await expect(element(by.id('editProfileModal'))).not.toBeVisible() - await expect(element(by.id('profileHeaderDisplayName'))).toHaveText( - 'alice.test', - ) - await expect(element(by.id('profileHeaderDescription'))).not.toExist() - }) - - it('Set avi and banner via the edit profile modal', async () => { - await expect(element(by.id('userBannerFallback'))).toExist() - await expect(element(by.id('userAvatarFallback'))).toExist() - await element(by.id('profileHeaderEditProfileButton')).tap() - await expect(element(by.id('editProfileModal'))).toBeVisible() - await element(by.id('changeBannerBtn')).tap() - await element(by.text('Upload from Library')).tap() - await sleep(3e3) - await element(by.id('changeAvatarBtn')).tap() - await element(by.text('Upload from Library')).tap() - await sleep(3e3) - await element(by.id('editProfileSaveBtn')).tap() - await expect(element(by.id('editProfileModal'))).not.toBeVisible() - await expect(element(by.id('userBannerImage'))).toExist() - await expect(element(by.id('userAvatarImage'))).toExist() - }) - - it('Remove avi and banner via the edit profile modal', async () => { - await expect(element(by.id('userBannerImage'))).toExist() - await expect(element(by.id('userAvatarImage'))).toExist() - await element(by.id('profileHeaderEditProfileButton')).tap() - await expect(element(by.id('editProfileModal'))).toBeVisible() - await element(by.id('changeBannerBtn')).tap() - await element(by.text('Remove Banner')).tap() - await element(by.id('changeAvatarBtn')).tap() - await element(by.text('Remove Avatar')).tap() - await element(by.id('editProfileSaveBtn')).tap() - await expect(element(by.id('editProfileModal'))).not.toBeVisible() - await expect(element(by.id('userBannerFallback'))).toExist() - await expect(element(by.id('userAvatarFallback'))).toExist() - }) - - it('Navigate to another user profile', async () => { - await element(by.id('bottomBarSearchBtn')).tap() - // have to wait for the toast to clear - await waitFor(element(by.id('searchTextInput'))) - .toBeVisible() - .withTimeout(5000) - await element(by.id('searchTextInput')).typeText('bob') - await element(by.id('searchAutoCompleteResult-bob.test')).tap() - await expect(element(by.id('profileView'))).toBeVisible() - }) - - it('Can follow/unfollow another user', async () => { - await element(by.id('followBtn')).tap() - await expect(element(by.id('unfollowBtn'))).toBeVisible() - await element(by.id('unfollowBtn')).tap() - await expect(element(by.id('followBtn'))).toBeVisible() - }) - - it('Can mute/unmute another user', async () => { - await expect(element(by.id('profileHeaderAlert'))).not.toExist() - await element(by.id('profileHeaderDropdownBtn')).tap() - await element(by.text('Mute Account')).tap() - await expect(element(by.id('profileHeaderAlert'))).toBeVisible() - await element(by.id('profileHeaderDropdownBtn')).tap() - await element(by.text('Unmute Account')).tap() - await expect(element(by.id('profileHeaderAlert'))).not.toExist() - }) - - // TODO skipping because the test env PDS isnt setup correctly to handle the report -prf - // it('Can report another user', async () => { - // await element(by.id('profileHeaderDropdownBtn')).tap() - // await element(by.text('Report Account')).tap() - // await expect(element(by.id('reportModal'))).toBeVisible() - // await element( - // by.id('reportReasonRadios-com.atproto.moderation.defs#reasonSpam'), - // ).tap() - // await element(by.id('sendReportBtn')).tap() - // await expect(element(by.id('reportModal'))).not.toBeVisible() - // }) - - it('Can like posts', async () => { - await element(by.id('postsFeed-flatlist')).swipe( - 'down', - 'slow', - 1, - 0.5, - 0.5, - ) - - const posts = by.id('feedItem-by-bob.test') - await expect( - element(by.id('likeCount').withAncestor(posts)).atIndex(0), - ).not.toExist() - await element(by.id('likeBtn').withAncestor(posts)).atIndex(0).tap() - await expect( - element(by.id('likeCount').withAncestor(posts)).atIndex(0), - ).toHaveText('1') - await element(by.id('likeBtn').withAncestor(posts)).atIndex(0).tap() - await expect( - element(by.id('likeCount').withAncestor(posts)).atIndex(0), - ).not.toExist() - }) - - it('Can repost posts', async () => { - const posts = by.id('feedItem-by-bob.test') - await expect( - element(by.id('repostCount').withAncestor(posts)).atIndex(0), - ).not.toExist() - await element(by.id('repostBtn').withAncestor(posts)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount').withAncestor(posts)).atIndex(0), - ).toHaveText('1') - await element(by.id('repostBtn').withAncestor(posts)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount').withAncestor(posts)).atIndex(0), - ).not.toExist() - }) - - // TODO skipping because the test env PDS isnt setup correctly to handle the report -prf - // it('Can report posts', async () => { - // const posts = by.id('feedItem-by-bob.test') - // await element(by.id('postDropdownBtn').withAncestor(posts)).atIndex(0).tap() - // await element(by.text('Report post')).tap() - // await expect(element(by.id('reportModal'))).toBeVisible() - // await element( - // by.id('reportReasonRadios-com.atproto.moderation.defs#reasonSpam'), - // ).tap() - // await element(by.id('sendReportBtn')).tap() - // await expect(element(by.id('reportModal'))).not.toBeVisible() - // }) -}) diff --git a/__e2e__/tests/search-screen.test.ts b/__e2e__/tests/search-screen.test.ts deleted file mode 100644 index 1dbb3cbfaa..0000000000 --- a/__e2e__/tests/search-screen.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, loginAsAlice, createServer} from '../util' - -describe('Search screen', () => { - beforeAll(async () => { - await createServer('?users') - await openApp({ - permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'}, - }) - }) - - it('Login', async () => { - await loginAsAlice() - }) - - it('Navigate to another user profile via autocomplete', async () => { - await element(by.id('bottomBarSearchBtn')).tap() - await element(by.id('searchTextInput')).typeText('bob') - await element(by.id('searchAutoCompleteResult-bob.test')).tap() - await expect(element(by.id('profileView'))).toBeVisible() - }) -}) diff --git a/__e2e__/tests/self-labeling.test.ts b/__e2e__/tests/self-labeling.test.ts deleted file mode 100644 index bba8ed484c..0000000000 --- a/__e2e__/tests/self-labeling.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, loginAsAlice, createServer, sleep} from '../util' - -describe('Self-labeling', () => { - beforeAll(async () => { - await createServer('?users') - await openApp({ - permissions: {notifications: 'YES', medialibrary: 'YES', photos: 'YES'}, - }) - }) - - it('Login', async () => { - await loginAsAlice() - await element(by.id('homeScreenFeedTabs-Following')).tap() - }) - - it('Post an image with the porn label', async () => { - await element(by.id('composeFAB')).tap() - await element(by.id('composerTextInput')).typeText('Post with an image') - await element(by.id('openGalleryBtn')).tap() - await sleep(3e3) - await element(by.id('labelsBtn')).tap() - await element(by.id('pornLabelBtn')).tap() - await element(by.id('confirmBtn')).tap() - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - const posts = by.id('feedItem-by-alice.test') - await element(by.id('e2eRefreshHome')).tap() - await expect( - element(by.id('contentHider-embed').withAncestor(posts)).atIndex(0), - ).toExist() - }) -}) diff --git a/__e2e__/tests/shell.test.skip.ts b/__e2e__/tests/shell.test.skip.ts deleted file mode 100644 index 69619dd81b..0000000000 --- a/__e2e__/tests/shell.test.skip.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-env detox/detox */ - -import {openApp, loginAsAlice, createServer} from '../util' - -describe('Shell', () => { - beforeAll(async () => { - await createServer('?users') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('Login', async () => { - await loginAsAlice() - await element(by.id('homeScreenFeedTabs-Following')).tap() - }) - - it('Can swipe the shelf open', async () => { - await element(by.id('homeScreen')).swipe('right', 'fast', 0.75) - await expect(element(by.id('drawer'))).toBeVisible() - await element(by.id('drawer')).swipe('left', 'fast', 0.75) - await expect(element(by.id('drawer'))).not.toBeVisible() - }) - - it('Can open the shelf by pressing the header avi', async () => { - await element(by.id('viewHeaderDrawerBtn')).tap() - await expect(element(by.id('drawer'))).toBeVisible() - }) - - it('Can navigate using the shelf', async () => { - await element(by.id('menuItemButton-Notifications')).tap() - await expect(element(by.id('drawer'))).not.toBeVisible() - await expect(element(by.id('notificationsScreen'))).toBeVisible() - }) -}) diff --git a/__e2e__/tests/thread-muting.test.ts b/__e2e__/tests/thread-muting.test.ts deleted file mode 100644 index ae62f93dcf..0000000000 --- a/__e2e__/tests/thread-muting.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-env detox/detox */ - -import {describe, beforeAll, it} from '@jest/globals' -import {expect} from 'detox' -import {openApp, loginAsAlice, loginAsBob, createServer} from '../util' - -describe('Thread muting', () => { - beforeAll(async () => { - await createServer('?users&follows') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('Login, create a thread, and log out', async () => { - await loginAsAlice() - await element(by.id('homeScreenFeedTabs-Following')).tap() - await element(by.id('composeFAB')).tap() - await element(by.id('composerTextInput')).typeText('Test thread') - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Login, reply to the thread, and log out', async () => { - await loginAsBob() - await element(by.id('homeScreenFeedTabs-Following')).tap() - const alicePosts = by.id('feedItem-by-alice.test') - await element(by.id('replyBtn').withAncestor(alicePosts)).atIndex(0).tap() - await element(by.id('composerTextInput')).typeText('Reply 1') - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - }) - - it('Login, confirm notification exists, mute thread, and log out', async () => { - await loginAsAlice() - await element(by.id('bottomBarNotificationsBtn')).tap() - const bobNotifs = by.id('feedItem-by-bob.test') - await expect( - element(by.id('postText').withAncestor(bobNotifs)).atIndex(0), - ).toHaveText('Reply 1') - await element(by.id('postDropdownBtn').withAncestor(bobNotifs)) - .atIndex(0) - .tap() - await element(by.text('Mute thread')).tap() - // have to wait for the toast to clear - await waitFor(element(by.id('viewHeaderDrawerBtn'))) - .toBeVisible() - .withTimeout(5000) - }) - - it('Login, reply to the thread twice, and log out', async () => { - await loginAsBob() - - await element(by.id('bottomBarProfileBtn')).tap() - await element(by.id('profilePager-selector-1')).tap() - const bobPosts = by.id('feedItem-by-bob.test') - await element(by.id('replyBtn').withAncestor(bobPosts)).atIndex(0).tap() - await element(by.id('composerTextInput')).typeText('Reply 2') - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - - const alicePosts = by.id('feedItem-by-alice.test') - await element(by.id('replyBtn').withAncestor(alicePosts)).atIndex(0).tap() - await element(by.id('composerTextInput')).typeText('Reply 3') - await element(by.id('composerPublishBtn')).tap() - await expect(element(by.id('composeFAB'))).toBeVisible() - - await element(by.id('bottomBarHomeBtn')).tap() - }) - - it('Login, confirm notifications dont exist, unmute the thread, confirm notifications exist', async () => { - await loginAsAlice() - - await element(by.id('bottomBarNotificationsBtn')).tap() - const bobNotifs = by.id('feedItem-by-bob.test') - await expect( - element(by.id('postText').withAncestor(bobNotifs)).atIndex(0), - ).not.toExist() - - await element(by.id('bottomBarHomeBtn')).tap() - const alicePosts = by.id('feedItem-by-alice.test') - await element(by.id('postDropdownBtn').withAncestor(alicePosts)) - .atIndex(0) - .tap() - await element(by.text('Unmute thread')).tap() - - // TODO - // the swipe down to trigger PTR isnt working and I dont want to block on this - // -prf - // await element(by.id('bottomBarNotificationsBtn')).tap() - // await element(by.id('notifsFeed')).swipe('down', 'fast') - // await waitFor(element(by.id('postText').withAncestor(bobNotifs))) - // .toBeVisible() - // .withTimeout(5000) - // await expect( - // element(by.id('postText').withAncestor(bobNotifs)).atIndex(0), - // ).toHaveText('Reply 2') - // await expect( - // element(by.id('postText').withAncestor(bobNotifs)).atIndex(1), - // ).toHaveText('Reply 3') - // await expect( - // element(by.id('postText').withAncestor(bobNotifs)).atIndex(2), - // ).toHaveText('Reply 1') - }) -}) diff --git a/__e2e__/tests/thread-screen.test.ts b/__e2e__/tests/thread-screen.test.ts deleted file mode 100644 index b99da11a67..0000000000 --- a/__e2e__/tests/thread-screen.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-env detox/detox */ - -import {beforeAll, describe, it} from '@jest/globals' -import {expect} from 'detox' - -import {createServer, loginAsAlice, openApp} from '../util' - -describe('Thread screen', () => { - beforeAll(async () => { - await createServer('?users&follows&thread') - await openApp({permissions: {notifications: 'YES'}}) - }) - - it('Login & navigate to thread', async () => { - await loginAsAlice() - await element(by.id('homeScreenFeedTabs-Following')).tap() - await element(by.id('feedItem-by-bob.test')).atIndex(0).tap() - await expect( - element( - by - .id('postThreadItem-by-bob.test') - .withDescendant(by.text('Thread root')), - ), - ).toBeVisible() - await expect( - element( - by - .id('postThreadItem-by-carla.test') - .withDescendant(by.text('Thread reply')), - ), - ).toBeVisible() - }) - - it('Can like the root post', async () => { - const post = by.id('postThreadItem-by-bob.test') - await expect( - element(by.id('likeCount-expanded').withAncestor(post)).atIndex(0), - ).not.toExist() - await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap() - await expect( - element(by.id('likeCount-expanded').withAncestor(post)).atIndex(0), - ).toHaveText('1 like') - await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap() - await expect( - element(by.id('likeCount-expanded').withAncestor(post)).atIndex(0), - ).not.toExist() - }) - - it('Can like a reply post', async () => { - const post = by.id('postThreadItem-by-carla.test') - await expect( - element(by.id('likeCount').withAncestor(post)).atIndex(0), - ).not.toExist() - await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap() - await expect( - element(by.id('likeCount').withAncestor(post)).atIndex(0), - ).toHaveText('1') - await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap() - await expect( - element(by.id('likeCount').withAncestor(post)).atIndex(0), - ).not.toExist() - }) - - it('Can repost the root post', async () => { - const post = by.id('postThreadItem-by-bob.test') - await expect( - element(by.id('repostCount-expanded').withAncestor(post)).atIndex(0), - ).not.toExist() - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount-expanded').withAncestor(post)).atIndex(0), - ).toHaveText('1 repost') - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount-expanded').withAncestor(post)).atIndex(0), - ).not.toExist() - }) - - it('Can repost a reply post', async () => { - const post = by.id('postThreadItem-by-carla.test') - await expect( - element(by.id('repostCount').withAncestor(post)).atIndex(0), - ).not.toExist() - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount').withAncestor(post)).atIndex(0), - ).toHaveText('1') - await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap() - await expect(element(by.id('repostModal'))).toBeVisible() - await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap() - await expect(element(by.id('repostModal'))).not.toBeVisible() - await expect( - element(by.id('repostCount').withAncestor(post)).atIndex(0), - ).not.toExist() - }) - - // TODO skipping because the test env PDS isnt setup correctly to handle the report -prf - // it('Can report the root post', async () => { - // const post = by.id('postThreadItem-by-bob.test') - // await element(by.id('postDropdownBtn').withAncestor(post)).atIndex(0).tap() - // await element(by.text('Report post')).tap() - // await expect(element(by.id('reportModal'))).toBeVisible() - // await element( - // by.id('reportReasonRadios-com.atproto.moderation.defs#reasonSpam'), - // ).tap() - // await element(by.id('sendReportBtn')).tap() - // await expect(element(by.id('reportModal'))).not.toBeVisible() - // }) - - // TODO skipping because the test env PDS isnt setup correctly to handle the report -prf - // it('Can report a reply post', async () => { - // const post = by.id('postThreadItem-by-carla.test') - // await element(by.id('postDropdownBtn').withAncestor(post)).atIndex(0).tap() - // await element(by.text('Report post')).tap() - // await expect(element(by.id('reportModal'))).toBeVisible() - // await element( - // by.id('reportReasonRadios-com.atproto.moderation.defs#reasonSpam'), - // ).tap() - // await element(by.id('sendReportBtn')).tap() - // await expect(element(by.id('reportModal'))).not.toBeVisible() - // }) -}) diff --git a/__e2e__/util.ts b/__e2e__/util.ts deleted file mode 100644 index 70fbdb6010..0000000000 --- a/__e2e__/util.ts +++ /dev/null @@ -1,141 +0,0 @@ -import {execSync} from 'child_process' -import {resolveConfig} from 'detox/internals' -import http from 'http' - -const platform = device.getPlatform() - -export async function openApp(opts: any) { - opts = opts || {} - const config = await resolveConfig() - - if (device.getPlatform() === 'ios') { - // disable password autofill - execSync( - `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist`, - ) - execSync( - `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist`, - ) - execSync( - `plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist`, - ) - } - if (config.configurationName.split('.').includes('debug')) { - return await openAppForDebugBuild(platform, opts) - } else { - return await device.launchApp({ - ...opts, - newInstance: true, - }) - } -} - -export async function isVisible(id: string) { - try { - await expect(element(by.id(id))).toBeVisible() - return true - } catch (e) { - return false - } -} - -export async function login( - service: string, - username: string, - password: string, - {takeScreenshots} = {takeScreenshots: false}, -) { - await element(by.id('signInButton')).tap() - if (takeScreenshots) { - await device.takeScreenshot('1- opened sign-in screen') - } - if (await isVisible('chooseAccountForm')) { - await element(by.id('chooseNewAccountBtn')).tap() - } - await element(by.id('selectServiceButton')).tap() - if (takeScreenshots) { - await device.takeScreenshot('2- opened service selector') - } - await element(by.id('customSelectBtn')).tap() - await element(by.id('customServerTextInput')).typeText(service) - await element(by.id('customServerTextInput')).tapReturnKey() - await element(by.id('doneBtn')).tap() - if (takeScreenshots) { - await device.takeScreenshot('3- input custom service') - } - await element(by.id('loginUsernameInput')).typeText(username) - await element(by.id('loginPasswordInput')).typeText(password) - if (takeScreenshots) { - await device.takeScreenshot('4- entered username and password') - } - await element(by.id('loginNextButton')).tap() -} - -export async function loginAsAlice() { - await element(by.id('e2eSignInAlice')).tap() -} - -export async function loginAsBob() { - await element(by.id('e2eSignInBob')).tap() -} - -async function openAppForDebugBuild(platform: string, opts: any) { - const deepLinkUrl = // Local testing with packager - /*process.env.EXPO_USE_UPDATES - ? // Testing latest published EAS update for the test_debug channel - getDeepLinkUrl(getLatestUpdateUrl()) - : */ getDeepLinkUrl(getDevLauncherPackagerUrl(platform)) - - if (platform === 'ios') { - await device.launchApp({ - ...opts, - newInstance: true, - }) - sleep(3000) - await device.openURL({ - url: deepLinkUrl, - }) - } else { - await device.launchApp({ - ...opts, - newInstance: true, - url: deepLinkUrl, - }) - } - - await sleep(3000) -} - -export async function createServer(path = ''): Promise { - return new Promise(function (resolve, reject) { - var req = http.request( - { - method: 'POST', - host: 'localhost', - port: 1986, - path: `/${path}`, - }, - function (res) { - const body: Buffer[] = [] - res.on('data', chunk => body.push(chunk)) - res.on('end', function () { - try { - resolve(Buffer.concat(body).toString()) - } catch (e) { - reject(e) - } - }) - }, - ) - req.on('error', reject) - req.end() - }) -} - -const getDeepLinkUrl = (url: string) => - `expo+bluesky://expo-development-client/?url=${encodeURIComponent(url)}` - -const getDevLauncherPackagerUrl = (platform: string) => - `http://localhost:8081/index.bundle?platform=${platform}&dev=true&minify=false&disableOnboarding=1` - -export const sleep = (t: number) => new Promise(res => setTimeout(res, t)) diff --git a/package.json b/package.json index 92bbad6d53..13ffc35c83 100644 --- a/package.json +++ b/package.json @@ -32,9 +32,9 @@ "typecheck": "tsc --project ./tsconfig.check.json", "e2e:mock-server": "./jest/dev-infra/with-test-redis-and-db.sh ts-node --project tsconfig.e2e.json __e2e__/mock-server.ts", "e2e:metro": "EXPO_PUBLIC_ENV=e2e NODE_ENV=test RN_SRC_EXT=e2e.ts,e2e.tsx expo run:ios", - "e2e:run": "maestro test .maestro", + "e2e:run": "maestro test __e2e__", "perf:test": "NODE_ENV=test maestro test", - "perf:test:run": "NODE_ENV=test maestro test __e2e__/maestro/scroll.yaml", + "perf:test:run": "NODE_ENV=test maestro test __e2e__/perf-test.yml", "perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand \"yarn perf:test\" --duration 150000 --resultsFilePath .perf/results.json", "perf:test:results": "NODE_ENV=test flashlight report .perf/results.json", "perf:measure": "NODE_ENV=test flashlight measure",