E2E 🟢 (#2092)
* Add logged out e2e ctrl, fix login test * Fix log handling via env vars in expo * Fix create account test * Upgrade dev-env * Fix home screen tests * Fix composer tests * Fix curate-lists tests, split in two * Fix invite codes test * Fix curate-lists tests * Give up on mergefeed test * Fix mod lists * Fix app view url * Fix profile tests * Fix profile test with hack * Keep using globals * Fix two more * Fix thread view * Better skip for merge feed * Revert debug codezio/stable
parent
ed5a97d0fa
commit
5f553c29df
|
@ -1,3 +1,6 @@
|
||||||
|
# Copy this to `.env` and `.env.test` files
|
||||||
|
|
||||||
SENTRY_AUTH_TOKEN=
|
SENTRY_AUTH_TOKEN=
|
||||||
|
EXPO_PUBLIC_ENV=development
|
||||||
EXPO_PUBLIC_LOG_LEVEL=debug
|
EXPO_PUBLIC_LOG_LEVEL=debug
|
||||||
EXPO_PUBLIC_LOG_DEBUG=
|
EXPO_PUBLIC_LOG_DEBUG=
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer, sleep} from '../util'
|
import {openApp, loginAsAlice, createServer, sleep} from '../util'
|
||||||
|
|
||||||
describe('Composer', () => {
|
describe('Composer', () => {
|
||||||
|
@ -45,6 +47,8 @@ describe('Composer', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Reply text only', async () => {
|
it('Reply text only', async () => {
|
||||||
|
await element(by.id('e2eRefreshHome')).tap()
|
||||||
|
|
||||||
const post = by.id('feedItem-by-alice.test')
|
const post = by.id('feedItem-by-alice.test')
|
||||||
await element(by.id('replyBtn').withAncestor(post)).atIndex(0).tap()
|
await element(by.id('replyBtn').withAncestor(post)).atIndex(0).tap()
|
||||||
await element(by.id('composerTextInput')).typeText('Reply text only')
|
await element(by.id('composerTextInput')).typeText('Reply text only')
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, createServer} from '../util'
|
import {openApp, createServer} from '../util'
|
||||||
|
|
||||||
describe('Create account', () => {
|
describe('Create account', () => {
|
||||||
|
@ -10,6 +12,8 @@ describe('Create account', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('I can create a new account', async () => {
|
it('I can create a new account', async () => {
|
||||||
|
await element(by.id('e2eOpenLoggedOutView')).tap()
|
||||||
|
|
||||||
await element(by.id('createAccountButton')).tap()
|
await element(by.id('createAccountButton')).tap()
|
||||||
await device.takeScreenshot('1- opened create account screen')
|
await device.takeScreenshot('1- opened create account screen')
|
||||||
await element(by.id('otherServerBtn')).tap()
|
await element(by.id('otherServerBtn')).tap()
|
||||||
|
@ -17,14 +21,20 @@ describe('Create account', () => {
|
||||||
await element(by.id('customServerInput')).clearText()
|
await element(by.id('customServerInput')).clearText()
|
||||||
await element(by.id('customServerInput')).typeText(service)
|
await element(by.id('customServerInput')).typeText(service)
|
||||||
await device.takeScreenshot('3- input test server URL')
|
await device.takeScreenshot('3- input test server URL')
|
||||||
|
|
||||||
await element(by.id('nextBtn')).tap()
|
await element(by.id('nextBtn')).tap()
|
||||||
|
|
||||||
await element(by.id('emailInput')).typeText('example@test.com')
|
await element(by.id('emailInput')).typeText('example@test.com')
|
||||||
await element(by.id('passwordInput')).typeText('hunter2')
|
await element(by.id('passwordInput')).typeText('hunter2')
|
||||||
await device.takeScreenshot('4- entered account details')
|
await device.takeScreenshot('4- entered account details')
|
||||||
|
|
||||||
await element(by.id('nextBtn')).tap()
|
await element(by.id('nextBtn')).tap()
|
||||||
|
|
||||||
await element(by.id('handleInput')).typeText('e2e-test')
|
await element(by.id('handleInput')).typeText('e2e-test')
|
||||||
await device.takeScreenshot('4- entered handle')
|
await device.takeScreenshot('4- entered handle')
|
||||||
|
|
||||||
await element(by.id('nextBtn')).tap()
|
await element(by.id('nextBtn')).tap()
|
||||||
|
|
||||||
await expect(element(by.id('welcomeOnboarding'))).toBeVisible()
|
await expect(element(by.id('welcomeOnboarding'))).toBeVisible()
|
||||||
await element(by.id('continueBtn')).tap()
|
await element(by.id('continueBtn')).tap()
|
||||||
await expect(element(by.id('recommendedFeedsOnboarding'))).toBeVisible()
|
await expect(element(by.id('recommendedFeedsOnboarding'))).toBeVisible()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, loginAsBob, createServer, sleep} from '../util'
|
import {openApp, loginAsAlice, loginAsBob, createServer, sleep} from '../util'
|
||||||
|
|
||||||
describe('Curate lists', () => {
|
describe('Curate lists', () => {
|
||||||
|
@ -11,7 +13,6 @@ describe('Curate lists', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Login and create a curatelists', async () => {
|
it('Login and create a curatelists', async () => {
|
||||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
|
||||||
await loginAsAlice()
|
await loginAsAlice()
|
||||||
await element(by.id('e2eGotoLists')).tap()
|
await element(by.id('e2eGotoLists')).tap()
|
||||||
await element(by.id('newUserListBtn')).tap()
|
await element(by.id('newUserListBtn')).tap()
|
||||||
|
@ -27,7 +28,7 @@ describe('Curate lists', () => {
|
||||||
|
|
||||||
it('Edit display name and description via the edit curatelist modal', async () => {
|
it('Edit display name and description via the edit curatelist modal', async () => {
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('editNameInput')).clearText()
|
await element(by.id('editNameInput')).clearText()
|
||||||
await element(by.id('editNameInput')).typeText('Bad Ppl')
|
await element(by.id('editNameInput')).typeText('Bad Ppl')
|
||||||
|
@ -45,7 +46,7 @@ describe('Curate lists', () => {
|
||||||
|
|
||||||
it('Remove description via the edit curatelist modal', async () => {
|
it('Remove description via the edit curatelist modal', async () => {
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('editDescriptionInput')).clearText()
|
await element(by.id('editDescriptionInput')).clearText()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('saveBtn')).tap()
|
||||||
|
@ -60,7 +61,7 @@ describe('Curate lists', () => {
|
||||||
it('Set avi via the edit curatelist modal', async () => {
|
it('Set avi via the edit curatelist modal', async () => {
|
||||||
await expect(element(by.id('userAvatarFallback'))).toExist()
|
await expect(element(by.id('userAvatarFallback'))).toExist()
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('changeAvatarBtn')).tap()
|
await element(by.id('changeAvatarBtn')).tap()
|
||||||
await element(by.text('Library')).tap()
|
await element(by.text('Library')).tap()
|
||||||
|
@ -77,7 +78,7 @@ describe('Curate lists', () => {
|
||||||
it('Remove avi via the edit curatelist modal', async () => {
|
it('Remove avi via the edit curatelist modal', async () => {
|
||||||
await expect(element(by.id('userAvatarImage'))).toExist()
|
await expect(element(by.id('userAvatarImage'))).toExist()
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('changeAvatarBtn')).tap()
|
await element(by.id('changeAvatarBtn')).tap()
|
||||||
await element(by.text('Remove')).tap()
|
await element(by.text('Remove')).tap()
|
||||||
|
@ -98,6 +99,7 @@ describe('Curate lists', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Create a new curatelist', async () => {
|
it('Create a new curatelist', async () => {
|
||||||
|
await element(by.id('e2eGotoLists')).tap()
|
||||||
await element(by.id('newUserListBtn')).tap()
|
await element(by.id('newUserListBtn')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('editNameInput')).typeText('Good Ppl')
|
await element(by.id('editNameInput')).typeText('Good Ppl')
|
||||||
|
@ -128,6 +130,7 @@ describe('Curate lists', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Pins the list', async () => {
|
it('Pins the list', async () => {
|
||||||
|
await expect(element(by.id('pinBtn'))).toBeVisible()
|
||||||
await element(by.id('pinBtn')).tap()
|
await element(by.id('pinBtn')).tap()
|
||||||
await element(by.id('e2eGotoHome')).tap()
|
await element(by.id('e2eGotoHome')).tap()
|
||||||
await element(by.id('homeScreenFeedTabs-Good Ppl')).tap()
|
await element(by.id('homeScreenFeedTabs-Good Ppl')).tap()
|
||||||
|
@ -152,15 +155,15 @@ describe('Curate lists', () => {
|
||||||
await expect(element(by.id('user-bob.test'))).toBeVisible()
|
await expect(element(by.id('user-bob.test'))).toBeVisible()
|
||||||
await element(by.id('user-bob.test-editBtn')).tap()
|
await element(by.id('user-bob.test-editBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
||||||
await element(by.id('toggleBtn-Good Ppl')).tap()
|
await element(by.id('user-bob.test-addBtn')).tap()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('doneBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Shows the curatelist on my profile', async () => {
|
it('Shows the curatelist on my profile', async () => {
|
||||||
await element(by.id('bottomBarProfileBtn')).tap()
|
await element(by.id('bottomBarProfileBtn')).tap()
|
||||||
await element(by.id('selector')).swipe('left')
|
await element(by.id('profilePager-selector')).swipe('left')
|
||||||
await element(by.id('selector-4')).tap()
|
await element(by.id('profilePager-selector-5')).tap()
|
||||||
await element(by.id('list-Good Ppl')).tap()
|
await element(by.id('list-Good Ppl')).tap()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -173,15 +176,15 @@ describe('Curate lists', () => {
|
||||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||||
await element(by.text('Add to Lists')).tap()
|
await element(by.text('Add to Lists')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
||||||
await element(by.id('toggleBtn-Good Ppl')).tap()
|
await element(by.id('user-bob.test-addBtn')).tap()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('doneBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
||||||
|
|
||||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||||
await element(by.text('Add to Lists')).tap()
|
await element(by.text('Add to Lists')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
||||||
await element(by.id('toggleBtn-Good Ppl')).tap()
|
await element(by.id('user-bob.test-addBtn')).tap()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('doneBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -192,8 +195,8 @@ describe('Curate lists', () => {
|
||||||
await element(by.id('bottomBarSearchBtn')).tap()
|
await element(by.id('bottomBarSearchBtn')).tap()
|
||||||
await element(by.id('searchTextInput')).typeText('alice')
|
await element(by.id('searchTextInput')).typeText('alice')
|
||||||
await element(by.id('searchAutoCompleteResult-alice.test')).tap()
|
await element(by.id('searchAutoCompleteResult-alice.test')).tap()
|
||||||
await element(by.id('selector')).swipe('left')
|
await element(by.id('profilePager-selector')).swipe('left')
|
||||||
await element(by.id('selector-3')).tap()
|
await element(by.id('profilePager-selector-3')).tap()
|
||||||
await element(by.id('list-Good Ppl')).tap()
|
await element(by.id('list-Good Ppl')).tap()
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Report List')).tap()
|
await element(by.text('Report List')).tap()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer} from '../util'
|
import {openApp, loginAsAlice, createServer} from '../util'
|
||||||
|
|
||||||
describe('Home screen', () => {
|
describe('Home screen', () => {
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* with the side drawer.
|
* with the side drawer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer} from '../util'
|
import {openApp, loginAsAlice, createServer} from '../util'
|
||||||
|
|
||||||
describe('invite-codes', () => {
|
describe('invite-codes', () => {
|
||||||
|
@ -16,7 +18,6 @@ describe('invite-codes', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('I can fetch invite codes', async () => {
|
it('I can fetch invite codes', async () => {
|
||||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
|
||||||
await loginAsAlice()
|
await loginAsAlice()
|
||||||
await element(by.id('e2eOpenInviteCodesModal')).tap()
|
await element(by.id('e2eOpenInviteCodesModal')).tap()
|
||||||
await expect(element(by.id('inviteCodesModal'))).toBeVisible()
|
await expect(element(by.id('inviteCodesModal'))).toBeVisible()
|
||||||
|
@ -27,6 +28,7 @@ describe('invite-codes', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('I can create a new account with the invite code', async () => {
|
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 element(by.id('createAccountButton')).tap()
|
||||||
await device.takeScreenshot('1- opened create account screen')
|
await device.takeScreenshot('1- opened create account screen')
|
||||||
await element(by.id('otherServerBtn')).tap()
|
await element(by.id('otherServerBtn')).tap()
|
||||||
|
@ -51,19 +53,4 @@ describe('invite-codes', () => {
|
||||||
await element(by.id('continueBtn')).tap()
|
await element(by.id('continueBtn')).tap()
|
||||||
await expect(element(by.id('homeScreen'))).toBeVisible()
|
await expect(element(by.id('homeScreen'))).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('I get a notification for the new user', async () => {
|
|
||||||
await element(by.id('e2eSignOut')).tap()
|
|
||||||
await loginAsAlice()
|
|
||||||
await waitFor(element(by.id('homeScreen')))
|
|
||||||
.toBeVisible()
|
|
||||||
.withTimeout(5000)
|
|
||||||
await element(by.id('bottomBarNotificationsBtn')).tap()
|
|
||||||
await expect(element(by.id('invitedUser'))).toBeVisible()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('I can dismiss the new user notification', async () => {
|
|
||||||
await element(by.id('dismissBtn')).tap()
|
|
||||||
await expect(element(by.id('invitedUser'))).not.toBeVisible()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, login, createServer} from '../util'
|
import {openApp, login, createServer} from '../util'
|
||||||
|
|
||||||
describe('Login', () => {
|
describe('Login', () => {
|
||||||
|
@ -10,6 +12,8 @@ describe('Login', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('As Alice, I can login', async () => {
|
it('As Alice, I can login', async () => {
|
||||||
|
await element(by.id('e2eOpenLoggedOutView')).tap()
|
||||||
|
|
||||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
await expect(element(by.id('signInButton'))).toBeVisible()
|
||||||
await login(service, 'alice', 'hunter2', {
|
await login(service, 'alice', 'hunter2', {
|
||||||
takeScreenshots: true,
|
takeScreenshots: true,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer} from '../util'
|
import {openApp, loginAsAlice, createServer} from '../util'
|
||||||
|
|
||||||
describe('Mergefeed', () => {
|
describe('Mergefeed', () => {
|
||||||
|
@ -9,8 +11,12 @@ describe('Mergefeed', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Login', async () => {
|
it('Login', async () => {
|
||||||
|
await element(by.id('e2eOpenLoggedOutView')).tap()
|
||||||
await loginAsAlice()
|
await loginAsAlice()
|
||||||
await element(by.id('e2eToggleMergefeed')).tap()
|
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 () => {
|
it('Sees the expected mix of posts with default filters', async () => {
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, loginAsBob, createServer, sleep} from '../util'
|
import {openApp, loginAsAlice, loginAsBob, createServer, sleep} from '../util'
|
||||||
|
|
||||||
describe('Mod lists', () => {
|
describe('Mod lists', () => {
|
||||||
|
@ -11,7 +13,6 @@ describe('Mod lists', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Login and view my modlists', async () => {
|
it('Login and view my modlists', async () => {
|
||||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
|
||||||
await loginAsAlice()
|
await loginAsAlice()
|
||||||
await element(by.id('e2eGotoModeration')).tap()
|
await element(by.id('e2eGotoModeration')).tap()
|
||||||
await element(by.id('moderationlistsBtn')).tap()
|
await element(by.id('moderationlistsBtn')).tap()
|
||||||
|
@ -31,7 +32,7 @@ describe('Mod lists', () => {
|
||||||
|
|
||||||
it('Edit display name and description via the edit modlist modal', async () => {
|
it('Edit display name and description via the edit modlist modal', async () => {
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('editNameInput')).clearText()
|
await element(by.id('editNameInput')).clearText()
|
||||||
await element(by.id('editNameInput')).typeText('Bad Ppl')
|
await element(by.id('editNameInput')).typeText('Bad Ppl')
|
||||||
|
@ -49,7 +50,7 @@ describe('Mod lists', () => {
|
||||||
|
|
||||||
it('Remove description via the edit modlist modal', async () => {
|
it('Remove description via the edit modlist modal', async () => {
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('editDescriptionInput')).clearText()
|
await element(by.id('editDescriptionInput')).clearText()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('saveBtn')).tap()
|
||||||
|
@ -64,7 +65,7 @@ describe('Mod lists', () => {
|
||||||
it('Set avi via the edit modlist modal', async () => {
|
it('Set avi via the edit modlist modal', async () => {
|
||||||
await expect(element(by.id('userAvatarFallback'))).toExist()
|
await expect(element(by.id('userAvatarFallback'))).toExist()
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('changeAvatarBtn')).tap()
|
await element(by.id('changeAvatarBtn')).tap()
|
||||||
await element(by.text('Library')).tap()
|
await element(by.text('Library')).tap()
|
||||||
|
@ -81,7 +82,7 @@ describe('Mod lists', () => {
|
||||||
it('Remove avi via the edit modlist modal', async () => {
|
it('Remove avi via the edit modlist modal', async () => {
|
||||||
await expect(element(by.id('userAvatarImage'))).toExist()
|
await expect(element(by.id('userAvatarImage'))).toExist()
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Edit List Details')).tap()
|
await element(by.text('Edit list details')).tap()
|
||||||
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
await expect(element(by.id('createOrEditListModal'))).toBeVisible()
|
||||||
await element(by.id('changeAvatarBtn')).tap()
|
await element(by.id('changeAvatarBtn')).tap()
|
||||||
await element(by.text('Remove')).tap()
|
await element(by.text('Remove')).tap()
|
||||||
|
@ -131,15 +132,15 @@ describe('Mod lists', () => {
|
||||||
await expect(element(by.id('user-warn-posts.test'))).toBeVisible()
|
await expect(element(by.id('user-warn-posts.test'))).toBeVisible()
|
||||||
await element(by.id('user-warn-posts.test-editBtn')).tap()
|
await element(by.id('user-warn-posts.test-editBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
||||||
await element(by.id('toggleBtn-Bad Ppl')).tap()
|
await element(by.id('user-warn-posts.test-addBtn')).tap()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('doneBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Shows the modlist on my profile', async () => {
|
it('Shows the modlist on my profile', async () => {
|
||||||
await element(by.id('bottomBarProfileBtn')).tap()
|
await element(by.id('bottomBarProfileBtn')).tap()
|
||||||
await element(by.id('selector')).swipe('left')
|
await element(by.id('profilePager-selector')).swipe('left')
|
||||||
await element(by.id('selector-4')).tap()
|
await element(by.id('profilePager-selector-5')).tap()
|
||||||
await element(by.id('list-Bad Ppl')).tap()
|
await element(by.id('list-Bad Ppl')).tap()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -152,15 +153,15 @@ describe('Mod lists', () => {
|
||||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||||
await element(by.text('Add to Lists')).tap()
|
await element(by.text('Add to Lists')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
||||||
await element(by.id('toggleBtn-Bad Ppl')).tap()
|
await element(by.id('user-bob.test-addBtn')).tap()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('doneBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
||||||
|
|
||||||
await element(by.id('profileHeaderDropdownBtn')).tap()
|
await element(by.id('profileHeaderDropdownBtn')).tap()
|
||||||
await element(by.text('Add to Lists')).tap()
|
await element(by.text('Add to Lists')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).toBeVisible()
|
||||||
await element(by.id('toggleBtn-Bad Ppl')).tap()
|
await element(by.id('user-bob.test-addBtn')).tap()
|
||||||
await element(by.id('saveBtn')).tap()
|
await element(by.id('doneBtn')).tap()
|
||||||
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
await expect(element(by.id('userAddRemoveListsModal'))).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -171,8 +172,8 @@ describe('Mod lists', () => {
|
||||||
await element(by.id('bottomBarSearchBtn')).tap()
|
await element(by.id('bottomBarSearchBtn')).tap()
|
||||||
await element(by.id('searchTextInput')).typeText('alice')
|
await element(by.id('searchTextInput')).typeText('alice')
|
||||||
await element(by.id('searchAutoCompleteResult-alice.test')).tap()
|
await element(by.id('searchAutoCompleteResult-alice.test')).tap()
|
||||||
await element(by.id('selector')).swipe('left')
|
await element(by.id('profilePager-selector')).swipe('left')
|
||||||
await element(by.id('selector-3')).tap()
|
await element(by.id('profilePager-selector-3')).tap()
|
||||||
await element(by.id('list-Bad Ppl')).tap()
|
await element(by.id('list-Bad Ppl')).tap()
|
||||||
await element(by.id('headerDropdownBtn')).tap()
|
await element(by.id('headerDropdownBtn')).tap()
|
||||||
await element(by.text('Report List')).tap()
|
await element(by.text('Report List')).tap()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer, sleep} from '../util'
|
import {openApp, loginAsAlice, createServer, sleep} from '../util'
|
||||||
|
|
||||||
describe('Profile screen', () => {
|
describe('Profile screen', () => {
|
||||||
|
@ -11,17 +13,16 @@ describe('Profile screen', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Login and navigate to my profile', async () => {
|
it('Login and navigate to my profile', async () => {
|
||||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
|
||||||
await loginAsAlice()
|
await loginAsAlice()
|
||||||
await element(by.id('bottomBarProfileBtn')).tap()
|
await element(by.id('bottomBarProfileBtn')).tap()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Can see feeds', async () => {
|
it('Can see feeds', async () => {
|
||||||
await element(by.id('selector')).swipe('left')
|
await element(by.id('profilePager-selector')).swipe('left')
|
||||||
await element(by.id('selector-4')).tap()
|
await element(by.id('profilePager-selector-4')).tap()
|
||||||
await expect(element(by.id('feed-alice-favs'))).toBeVisible()
|
await expect(element(by.id('feed-alice-favs'))).toBeVisible()
|
||||||
await element(by.id('selector')).swipe('right')
|
await element(by.id('profilePager-selector')).swipe('right')
|
||||||
await element(by.id('selector-0')).tap()
|
await element(by.id('profilePager-selector-0')).tap()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Open and close edit profile modal', async () => {
|
it('Open and close edit profile modal', async () => {
|
||||||
|
@ -135,6 +136,14 @@ describe('Profile screen', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Can like posts', async () => {
|
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')
|
const posts = by.id('feedItem-by-bob.test')
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('likeCount').withAncestor(posts)).atIndex(0),
|
element(by.id('likeCount').withAncestor(posts)).atIndex(0),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer} from '../util'
|
import {openApp, loginAsAlice, createServer} from '../util'
|
||||||
|
|
||||||
describe('Search screen', () => {
|
describe('Search screen', () => {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer, sleep} from '../util'
|
import {openApp, loginAsAlice, createServer, sleep} from '../util'
|
||||||
|
|
||||||
describe('Self-labeling', () => {
|
describe('Self-labeling', () => {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, loginAsBob, createServer} from '../util'
|
import {openApp, loginAsAlice, loginAsBob, createServer} from '../util'
|
||||||
|
|
||||||
describe('Thread muting', () => {
|
describe('Thread muting', () => {
|
||||||
|
@ -48,7 +50,7 @@ describe('Thread muting', () => {
|
||||||
await loginAsBob()
|
await loginAsBob()
|
||||||
|
|
||||||
await element(by.id('bottomBarProfileBtn')).tap()
|
await element(by.id('bottomBarProfileBtn')).tap()
|
||||||
await element(by.id('selector-1')).tap()
|
await element(by.id('profilePager-selector-1')).tap()
|
||||||
const bobPosts = by.id('feedItem-by-bob.test')
|
const bobPosts = by.id('feedItem-by-bob.test')
|
||||||
await element(by.id('replyBtn').withAncestor(bobPosts)).atIndex(0).tap()
|
await element(by.id('replyBtn').withAncestor(bobPosts)).atIndex(0).tap()
|
||||||
await element(by.id('composerTextInput')).typeText('Reply 2')
|
await element(by.id('composerTextInput')).typeText('Reply 2')
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/* eslint-env detox/detox */
|
/* eslint-env detox/detox */
|
||||||
|
|
||||||
|
import {describe, beforeAll, it} from '@jest/globals'
|
||||||
|
import {expect} from 'detox'
|
||||||
import {openApp, loginAsAlice, createServer} from '../util'
|
import {openApp, loginAsAlice, createServer} from '../util'
|
||||||
|
|
||||||
describe('Thread screen', () => {
|
describe('Thread screen', () => {
|
||||||
|
@ -31,15 +33,15 @@ describe('Thread screen', () => {
|
||||||
it('Can like the root post', async () => {
|
it('Can like the root post', async () => {
|
||||||
const post = by.id('postThreadItem-by-bob.test')
|
const post = by.id('postThreadItem-by-bob.test')
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('likeCount').withAncestor(post)).atIndex(0),
|
element(by.id('likeCount-expanded').withAncestor(post)).atIndex(0),
|
||||||
).not.toExist()
|
).not.toExist()
|
||||||
await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap()
|
await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap()
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('likeCount').withAncestor(post)).atIndex(0),
|
element(by.id('likeCount-expanded').withAncestor(post)).atIndex(0),
|
||||||
).toHaveText('1 like')
|
).toHaveText('1 like')
|
||||||
await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap()
|
await element(by.id('likeBtn').withAncestor(post)).atIndex(0).tap()
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('likeCount').withAncestor(post)).atIndex(0),
|
element(by.id('likeCount-expanded').withAncestor(post)).atIndex(0),
|
||||||
).not.toExist()
|
).not.toExist()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -61,21 +63,21 @@ describe('Thread screen', () => {
|
||||||
it('Can repost the root post', async () => {
|
it('Can repost the root post', async () => {
|
||||||
const post = by.id('postThreadItem-by-bob.test')
|
const post = by.id('postThreadItem-by-bob.test')
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('repostCount').withAncestor(post)).atIndex(0),
|
element(by.id('repostCount-expanded').withAncestor(post)).atIndex(0),
|
||||||
).not.toExist()
|
).not.toExist()
|
||||||
await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap()
|
await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap()
|
||||||
await expect(element(by.id('repostModal'))).toBeVisible()
|
await expect(element(by.id('repostModal'))).toBeVisible()
|
||||||
await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap()
|
await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap()
|
||||||
await expect(element(by.id('repostModal'))).not.toBeVisible()
|
await expect(element(by.id('repostModal'))).not.toBeVisible()
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('repostCount').withAncestor(post)).atIndex(0),
|
element(by.id('repostCount-expanded').withAncestor(post)).atIndex(0),
|
||||||
).toHaveText('1 repost')
|
).toHaveText('1 repost')
|
||||||
await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap()
|
await element(by.id('repostBtn').withAncestor(post)).atIndex(0).tap()
|
||||||
await expect(element(by.id('repostModal'))).toBeVisible()
|
await expect(element(by.id('repostModal'))).toBeVisible()
|
||||||
await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap()
|
await element(by.id('repostBtn').withAncestor(by.id('repostModal'))).tap()
|
||||||
await expect(element(by.id('repostModal'))).not.toBeVisible()
|
await expect(element(by.id('repostModal'))).not.toBeVisible()
|
||||||
await expect(
|
await expect(
|
||||||
element(by.id('repostCount').withAncestor(post)).atIndex(0),
|
element(by.id('repostCount-expanded').withAncestor(post)).atIndex(0),
|
||||||
).not.toExist()
|
).not.toExist()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
# Testing instructions
|
# Testing instructions
|
||||||
|
|
||||||
|
Make sure you've copied `.env.example` to `.env.test` and provided any required
|
||||||
|
values.
|
||||||
|
|
||||||
### Using Maestro E2E tests
|
### Using Maestro E2E tests
|
||||||
1. Install Maestro by following [these instructions](https://maestro.mobile.dev/getting-started/installing-maestro). This will help us run the E2E tests.
|
1. Install Maestro by following [these instructions](https://maestro.mobile.dev/getting-started/installing-maestro). This will help us run the E2E tests.
|
||||||
2. You can write Maestro tests in `__e2e__/maestro` directory by creating a new `.yaml` file or by modifying an existing one.
|
2. You can write Maestro tests in `__e2e__/maestro` directory by creating a new `.yaml` file or by modifying an existing one.
|
||||||
|
@ -11,4 +14,4 @@
|
||||||
2. Install Flashlight by following [these instructions](https://docs.flashlight.dev/)
|
2. Install Flashlight by following [these instructions](https://docs.flashlight.dev/)
|
||||||
3. The simplest way to get started is by running `yarn perf:measure` which will run a live preview of the performance test results. You can [see a demo here](https://github.com/bamlab/flashlight/assets/4534323/4038a342-f145-4c3b-8cde-17949bf52612)
|
3. The simplest way to get started is by running `yarn perf:measure` which will run a live preview of the performance test results. You can [see a demo here](https://github.com/bamlab/flashlight/assets/4534323/4038a342-f145-4c3b-8cde-17949bf52612)
|
||||||
4. The `yarn perf:test:measure` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml` and give the results in `.perf/results.json` which can be viewed by running `yarn:perf:results`
|
4. The `yarn perf:test:measure` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml` and give the results in `.perf/results.json` which can be viewed by running `yarn:perf:results`
|
||||||
5. You can also run your own tests by running `yarn perf:test <path_to_test>` where `<path_to_test>` is the path to your test file. For example, `yarn perf:test __e2e__/maestro/scroll.yaml` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml`.
|
5. You can also run your own tests by running `yarn perf:test <path_to_test>` where `<path_to_test>` is the path to your test file. For example, `yarn perf:test __e2e__/maestro/scroll.yaml` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml`.
|
||||||
|
|
12
index.js
12
index.js
|
@ -1,15 +1,21 @@
|
||||||
import 'react-native-gesture-handler' // must be first
|
import 'react-native-gesture-handler' // must be first
|
||||||
|
|
||||||
import {LogBox} from 'react-native'
|
import {LogBox} from 'react-native'
|
||||||
LogBox.ignoreLogs(['Require cycle:']) // suppress require-cycle warnings, it's fine
|
|
||||||
|
|
||||||
import '#/platform/polyfills'
|
import '#/platform/polyfills'
|
||||||
|
import {IS_TEST} from '#/env'
|
||||||
import {registerRootComponent} from 'expo'
|
import {registerRootComponent} from 'expo'
|
||||||
import {doPolyfill} from '#/lib/api/api-polyfill'
|
import {doPolyfill} from '#/lib/api/api-polyfill'
|
||||||
doPolyfill()
|
|
||||||
|
|
||||||
import App from '#/App'
|
import App from '#/App'
|
||||||
|
|
||||||
|
doPolyfill()
|
||||||
|
|
||||||
|
if (IS_TEST) {
|
||||||
|
LogBox.ignoreAllLogs() // suppress all logs in tests
|
||||||
|
} else {
|
||||||
|
LogBox.ignoreLogs(['Require cycle:']) // suppress require-cycle warnings, it's fine
|
||||||
|
}
|
||||||
|
|
||||||
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
||||||
// It also ensures that whether you load the app in Expo Go or in a native build,
|
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||||
// the environment is set up appropriately
|
// the environment is set up appropriately
|
||||||
|
|
|
@ -59,17 +59,21 @@ export async function createServer(
|
||||||
): Promise<TestPDS> {
|
): Promise<TestPDS> {
|
||||||
const port = await getPort()
|
const port = await getPort()
|
||||||
const port2 = await getPort(port + 1)
|
const port2 = await getPort(port + 1)
|
||||||
|
const port3 = await getPort(port2 + 1)
|
||||||
const pdsUrl = `http://localhost:${port}`
|
const pdsUrl = `http://localhost:${port}`
|
||||||
const id = ids.next()
|
const id = ids.next()
|
||||||
|
|
||||||
const testNet = await TestNetwork.create({
|
const testNet = await TestNetwork.create({
|
||||||
pds: {
|
pds: {
|
||||||
port,
|
port,
|
||||||
publicUrl: pdsUrl,
|
hostname: 'localhost',
|
||||||
inviteRequired,
|
|
||||||
dbPostgresSchema: `pds_${id}`,
|
dbPostgresSchema: `pds_${id}`,
|
||||||
|
inviteRequired,
|
||||||
},
|
},
|
||||||
bsky: {
|
bsky: {
|
||||||
dbPostgresSchema: `bsky_${id}`,
|
dbPostgresSchema: `bsky_${id}`,
|
||||||
|
port: port3,
|
||||||
|
publicUrl: 'http://localhost:2584',
|
||||||
},
|
},
|
||||||
plc: {port: port2},
|
plc: {port: port2},
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
|
"lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
|
||||||
"typecheck": "tsc --project ./tsconfig.check.json",
|
"typecheck": "tsc --project ./tsconfig.check.json",
|
||||||
"e2e:mock-server": "./jest/dev-infra/with-test-redis-and-db.sh ts-node __e2e__/mock-server.ts",
|
"e2e:mock-server": "./jest/dev-infra/with-test-redis-and-db.sh ts-node __e2e__/mock-server.ts",
|
||||||
"e2e:metro": "RN_SRC_EXT=e2e.ts,e2e.tsx expo run:ios",
|
"e2e:metro": "NODE_ENV=test RN_SRC_EXT=e2e.ts,e2e.tsx expo run:ios",
|
||||||
"e2e:build": "detox build -c ios.sim.debug",
|
"e2e:build": "NODE_ENV=test detox build -c ios.sim.debug",
|
||||||
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all",
|
"e2e:run": "NODE_ENV=test detox test --configuration ios.sim.debug --take-screenshots all",
|
||||||
"perf:test": "NODE_ENV=test maestro test",
|
"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__/maestro/scroll.yaml",
|
||||||
"perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json",
|
"perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json",
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
"zod": "^3.20.2"
|
"zod": "^3.20.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@atproto/dev-env": "^0.2.5",
|
"@atproto/dev-env": "^0.2.16",
|
||||||
"@babel/core": "^7.23.2",
|
"@babel/core": "^7.23.2",
|
||||||
"@babel/preset-env": "^7.20.0",
|
"@babel/preset-env": "^7.20.0",
|
||||||
"@babel/runtime": "^7.20.0",
|
"@babel/runtime": "^7.20.0",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export const IS_TEST = process.env.NODE_ENV === 'test'
|
export const IS_TEST = process.env.EXPO_PUBLIC_ENV === 'test'
|
||||||
export const IS_DEV = __DEV__
|
export const IS_DEV = __DEV__
|
||||||
export const IS_PROD = !IS_DEV
|
export const IS_PROD = !IS_DEV
|
||||||
export const LOG_DEBUG = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
|
export const LOG_DEBUG = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
|
||||||
|
|
|
@ -61,6 +61,7 @@ export interface CreateOrEditListModal {
|
||||||
export interface UserAddRemoveListsModal {
|
export interface UserAddRemoveListsModal {
|
||||||
name: 'user-add-remove-lists'
|
name: 'user-add-remove-lists'
|
||||||
subject: string
|
subject: string
|
||||||
|
handle: string
|
||||||
displayName: string
|
displayName: string
|
||||||
onAdd?: (listUri: string) => void
|
onAdd?: (listUri: string) => void
|
||||||
onRemove?: (listUri: string) => void
|
onRemove?: (listUri: string) => void
|
||||||
|
|
|
@ -170,6 +170,7 @@ export function FeedSourceCardLoaded({
|
||||||
{showSaveBtn && feed.type === 'feed' && (
|
{showSaveBtn && feed.type === 'feed' && (
|
||||||
<View>
|
<View>
|
||||||
<Pressable
|
<Pressable
|
||||||
|
testID={`feed-${feed.displayName}-toggleSave`}
|
||||||
disabled={isSavePending || isPinPending || isRemovePending}
|
disabled={isSavePending || isPinPending || isRemovePending}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={
|
accessibilityLabel={
|
||||||
|
|
|
@ -132,6 +132,7 @@ export function ListMembers({
|
||||||
name: 'user-add-remove-lists',
|
name: 'user-add-remove-lists',
|
||||||
subject: profile.did,
|
subject: profile.did,
|
||||||
displayName: profile.displayName || profile.handle,
|
displayName: profile.displayName || profile.handle,
|
||||||
|
handle: profile.handle,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
[openModal],
|
[openModal],
|
||||||
|
|
|
@ -28,11 +28,13 @@ export const snapPoints = ['fullscreen']
|
||||||
|
|
||||||
export function Component({
|
export function Component({
|
||||||
subject,
|
subject,
|
||||||
|
handle,
|
||||||
displayName,
|
displayName,
|
||||||
onAdd,
|
onAdd,
|
||||||
onRemove,
|
onRemove,
|
||||||
}: {
|
}: {
|
||||||
subject: string
|
subject: string
|
||||||
|
handle: string
|
||||||
displayName: string
|
displayName: string
|
||||||
onAdd?: (listUri: string) => void
|
onAdd?: (listUri: string) => void
|
||||||
onRemove?: (listUri: string) => void
|
onRemove?: (listUri: string) => void
|
||||||
|
@ -60,6 +62,7 @@ export function Component({
|
||||||
list={list}
|
list={list}
|
||||||
memberships={memberships}
|
memberships={memberships}
|
||||||
subject={subject}
|
subject={subject}
|
||||||
|
handle={handle}
|
||||||
onAdd={onAdd}
|
onAdd={onAdd}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
/>
|
/>
|
||||||
|
@ -87,6 +90,7 @@ function ListItem({
|
||||||
list,
|
list,
|
||||||
memberships,
|
memberships,
|
||||||
subject,
|
subject,
|
||||||
|
handle,
|
||||||
onAdd,
|
onAdd,
|
||||||
onRemove,
|
onRemove,
|
||||||
}: {
|
}: {
|
||||||
|
@ -94,6 +98,7 @@ function ListItem({
|
||||||
list: GraphDefs.ListView
|
list: GraphDefs.ListView
|
||||||
memberships: ListMembersip[] | undefined
|
memberships: ListMembersip[] | undefined
|
||||||
subject: string
|
subject: string
|
||||||
|
handle: string
|
||||||
onAdd?: (listUri: string) => void
|
onAdd?: (listUri: string) => void
|
||||||
onRemove?: (listUri: string) => void
|
onRemove?: (listUri: string) => void
|
||||||
}) {
|
}) {
|
||||||
|
@ -182,7 +187,7 @@ function ListItem({
|
||||||
<ActivityIndicator />
|
<ActivityIndicator />
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
testID={`user-${subject}-addBtn`}
|
testID={`user-${handle}-addBtn`}
|
||||||
type="default"
|
type="default"
|
||||||
label={membership === false ? _(msg`Add`) : _(msg`Remove`)}
|
label={membership === false ? _(msg`Add`) : _(msg`Remove`)}
|
||||||
onPress={onToggleMembership}
|
onPress={onToggleMembership}
|
||||||
|
|
|
@ -375,7 +375,10 @@ let PostThreadItemLoaded = ({
|
||||||
style={styles.expandedInfoItem}
|
style={styles.expandedInfoItem}
|
||||||
href={repostsHref}
|
href={repostsHref}
|
||||||
title={repostsTitle}>
|
title={repostsTitle}>
|
||||||
<Text testID="repostCount" type="lg" style={pal.textLight}>
|
<Text
|
||||||
|
testID="repostCount-expanded"
|
||||||
|
type="lg"
|
||||||
|
style={pal.textLight}>
|
||||||
<Text type="xl-bold" style={pal.text}>
|
<Text type="xl-bold" style={pal.text}>
|
||||||
{formatCount(post.repostCount)}
|
{formatCount(post.repostCount)}
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
|
@ -390,7 +393,10 @@ let PostThreadItemLoaded = ({
|
||||||
style={styles.expandedInfoItem}
|
style={styles.expandedInfoItem}
|
||||||
href={likesHref}
|
href={likesHref}
|
||||||
title={likesTitle}>
|
title={likesTitle}>
|
||||||
<Text testID="likeCount" type="lg" style={pal.textLight}>
|
<Text
|
||||||
|
testID="likeCount-expanded"
|
||||||
|
type="lg"
|
||||||
|
style={pal.textLight}>
|
||||||
<Text type="xl-bold" style={pal.text}>
|
<Text type="xl-bold" style={pal.text}>
|
||||||
{formatCount(post.likeCount)}
|
{formatCount(post.likeCount)}
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
|
|
|
@ -217,6 +217,7 @@ let ProfileHeaderLoaded = ({
|
||||||
openModal({
|
openModal({
|
||||||
name: 'user-add-remove-lists',
|
name: 'user-add-remove-lists',
|
||||||
subject: profile.did,
|
subject: profile.did,
|
||||||
|
handle: profile.handle,
|
||||||
displayName: profile.displayName || profile.handle,
|
displayName: profile.displayName || profile.handle,
|
||||||
onAdd: invalidateProfileQuery,
|
onAdd: invalidateProfileQuery,
|
||||||
onRemove: invalidateProfileQuery,
|
onRemove: invalidateProfileQuery,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {useModalControls} from '#/state/modals'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
import {useSessionApi} from '#/state/session'
|
import {useSessionApi} from '#/state/session'
|
||||||
import {useSetFeedViewPreferencesMutation} from '#/state/queries/preferences'
|
import {useSetFeedViewPreferencesMutation} from '#/state/queries/preferences'
|
||||||
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This utility component is only included in the test simulator
|
* This utility component is only included in the test simulator
|
||||||
|
@ -19,6 +20,7 @@ export function TestCtrls() {
|
||||||
const {logout, login} = useSessionApi()
|
const {logout, login} = useSessionApi()
|
||||||
const {openModal} = useModalControls()
|
const {openModal} = useModalControls()
|
||||||
const {mutate: setFeedViewPref} = useSetFeedViewPreferencesMutation()
|
const {mutate: setFeedViewPref} = useSetFeedViewPreferencesMutation()
|
||||||
|
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||||
const onPressSignInAlice = async () => {
|
const onPressSignInAlice = async () => {
|
||||||
await login({
|
await login({
|
||||||
service: 'http://localhost:3000',
|
service: 'http://localhost:3000',
|
||||||
|
@ -95,6 +97,12 @@ export function TestCtrls() {
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
style={BTN}
|
style={BTN}
|
||||||
/>
|
/>
|
||||||
|
<Pressable
|
||||||
|
testID="e2eOpenLoggedOutView"
|
||||||
|
onPress={() => setShowLoggedOut(true)}
|
||||||
|
accessibilityRole="button"
|
||||||
|
style={BTN}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {colors} from 'lib/styles'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
||||||
|
import {IS_TEST} from '#/env'
|
||||||
|
|
||||||
const TIMEOUT = 4e3
|
const TIMEOUT = 4e3
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ export function show(
|
||||||
message: string,
|
message: string,
|
||||||
_icon: FontAwesomeProps['icon'] = 'check',
|
_icon: FontAwesomeProps['icon'] = 'check',
|
||||||
) {
|
) {
|
||||||
|
if (IS_TEST) return
|
||||||
const item = new RootSiblings(<Toast message={message} />)
|
const item = new RootSiblings(<Toast message={message} />)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
item.destroy()
|
item.destroy()
|
||||||
|
|
|
@ -42,6 +42,7 @@ export function SearchResultCard({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
testID={`searchAutoCompleteResult-${profile.handle}`}
|
||||||
href={makeProfileLink(profile)}
|
href={makeProfileLink(profile)}
|
||||||
title={profile.handle}
|
title={profile.handle}
|
||||||
asAnchor
|
asAnchor
|
||||||
|
|
Loading…
Reference in New Issue