implement requesting to follow someone
This commit is contained in:
parent
c11f2454ad
commit
56f7efb78f
|
@ -326,5 +326,12 @@ export const actions = times(30, i => ({
|
||||||
inReplyTo: 'bazthread-thread 2b2',
|
inReplyTo: 'bazthread-thread 2b2',
|
||||||
privacy: 'unlisted'
|
privacy: 'unlisted'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user: 'LockedAccount',
|
||||||
|
post: {
|
||||||
|
text: 'This account is locked',
|
||||||
|
privacy: 'private'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]))
|
]))
|
||||||
|
|
|
@ -30,5 +30,6 @@ module.exports = [
|
||||||
{id: 'fa-smile', src: 'node_modules/font-awesome-svg-png/white/svg/smile-o.svg', title: 'Custom emoji'},
|
{id: 'fa-smile', src: 'node_modules/font-awesome-svg-png/white/svg/smile-o.svg', title: 'Custom emoji'},
|
||||||
{id: 'fa-exclamation-triangle', src: 'node_modules/font-awesome-svg-png/white/svg/exclamation-triangle.svg', title: 'Content warning'},
|
{id: 'fa-exclamation-triangle', src: 'node_modules/font-awesome-svg-png/white/svg/exclamation-triangle.svg', title: 'Content warning'},
|
||||||
{id: 'fa-check', src: 'node_modules/font-awesome-svg-png/white/svg/check.svg', title: 'Check'},
|
{id: 'fa-check', src: 'node_modules/font-awesome-svg-png/white/svg/check.svg', title: 'Check'},
|
||||||
{id: 'fa-trash', src: 'node_modules/font-awesome-svg-png/white/svg/trash-o.svg', title: 'Delete'}
|
{id: 'fa-trash', src: 'node_modules/font-awesome-svg-png/white/svg/trash-o.svg', title: 'Delete'},
|
||||||
|
{id: 'fa-hourglass', src: 'node_modules/font-awesome-svg-png/white/svg/hourglass.svg', title: 'Follow requested'}
|
||||||
]
|
]
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,7 @@ import { store } from '../_store/store'
|
||||||
import { followAccount, unfollowAccount } from '../_api/follow'
|
import { followAccount, unfollowAccount } from '../_api/follow'
|
||||||
import { database } from '../_database/database'
|
import { database } from '../_database/database'
|
||||||
import { toast } from '../_utils/toast'
|
import { toast } from '../_utils/toast'
|
||||||
|
import { updateProfileAndRelationship } from './accounts'
|
||||||
|
|
||||||
export async function setAccountFollowed (accountId, follow, toastOnSuccess) {
|
export async function setAccountFollowed (accountId, follow, toastOnSuccess) {
|
||||||
let instanceName = store.get('currentInstance')
|
let instanceName = store.get('currentInstance')
|
||||||
|
@ -12,11 +13,18 @@ export async function setAccountFollowed (accountId, follow, toastOnSuccess) {
|
||||||
} else {
|
} else {
|
||||||
await unfollowAccount(instanceName, accessToken, accountId)
|
await unfollowAccount(instanceName, accessToken, accountId)
|
||||||
}
|
}
|
||||||
|
await updateProfileAndRelationship(accountId)
|
||||||
let relationship = await database.getRelationship(instanceName, accountId)
|
let relationship = await database.getRelationship(instanceName, accountId)
|
||||||
relationship.following = follow
|
|
||||||
await database.setRelationship(instanceName, relationship)
|
|
||||||
if (toastOnSuccess) {
|
if (toastOnSuccess) {
|
||||||
toast.say(`${follow ? 'Followed' : 'Unfollowed'}`)
|
if (follow) {
|
||||||
|
if (relationship.requested) {
|
||||||
|
toast.say('Requested to follow account')
|
||||||
|
} else {
|
||||||
|
toast.say('Followed account')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast.say('Unfollowed account')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
|
17
routes/_actions/followRequests.js
Normal file
17
routes/_actions/followRequests.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { getWithTimeout, postWithTimeout } from '../_utils/ajax'
|
||||||
|
import { auth, basename } from '../_api/utils'
|
||||||
|
|
||||||
|
export async function getFollowRequests (instanceName, accessToken) {
|
||||||
|
let url = `${basename(instanceName)}/api/v1/follow_requests`
|
||||||
|
return getWithTimeout(url, auth(accessToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function authorizeFollowRequest (instanceName, accessToken, id) {
|
||||||
|
let url = `${basename(instanceName)}/api/v1/follow_requests/${id}/authorize`
|
||||||
|
return postWithTimeout(url, null, auth(accessToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function rejectFollowRequest (instanceName, accessToken, id) {
|
||||||
|
let url = `${basename(instanceName)}/api/v1/follow_requests/${id}/reject`
|
||||||
|
return postWithTimeout(url, null, auth(accessToken))
|
||||||
|
}
|
|
@ -40,10 +40,10 @@ async function addTimelineItems (instanceName, timelineName, items, stale) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addTimelineItemIds (instanceName, timelineName, newIds, newStale) {
|
export async function addTimelineItemIds (instanceName, timelineName, newIds, newStale) {
|
||||||
let oldIds = store.getForTimeline(instanceName, timelineName, 'timelineItemIds') || []
|
let oldIds = store.getForTimeline(instanceName, timelineName, 'timelineItemIds')
|
||||||
let oldStale = store.getForTimeline(instanceName, timelineName, 'timelineItemIdsAreStale')
|
let oldStale = store.getForTimeline(instanceName, timelineName, 'timelineItemIdsAreStale')
|
||||||
|
|
||||||
let mergedIds = mergeArrays(oldIds, newIds)
|
let mergedIds = mergeArrays(oldIds || [], newIds)
|
||||||
|
|
||||||
if (!isEqual(oldIds, mergedIds)) {
|
if (!isEqual(oldIds, mergedIds)) {
|
||||||
store.setForTimeline(instanceName, timelineName, {timelineItemIds: mergedIds})
|
store.setForTimeline(instanceName, timelineName, {timelineItemIds: mergedIds})
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
<div class="account-profile-follow">
|
<div class="account-profile-follow">
|
||||||
{{#if verifyCredentials && relationship && verifyCredentials.id !== relationship.id}}
|
{{#if verifyCredentials && relationship && verifyCredentials.id !== relationship.id}}
|
||||||
<IconButton
|
<IconButton
|
||||||
label="{{following ? 'Unfollow' : 'Follow'}}"
|
label="{{followLabel}}"
|
||||||
href="{{following ? '#fa-user-times' : '#fa-user-plus'}}"
|
href="{{followIcon}}"
|
||||||
pressable="true"
|
pressable="true"
|
||||||
pressed="{{following}}"
|
pressed="{{following}}"
|
||||||
big="true"
|
big="true"
|
||||||
|
@ -201,14 +201,34 @@
|
||||||
}
|
}
|
||||||
return note
|
return note
|
||||||
},
|
},
|
||||||
following: (relationship) => relationship && relationship.following
|
following: (relationship) => relationship && relationship.following,
|
||||||
|
followRequested: (relationship) => relationship && relationship.requested,
|
||||||
|
followLabel: (following, followRequested) => {
|
||||||
|
if (following) {
|
||||||
|
return 'Unfollow'
|
||||||
|
} else if (followRequested) {
|
||||||
|
return 'Unfollow (follow requested)'
|
||||||
|
} else {
|
||||||
|
return 'Follow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
followIcon: (following, followRequested) => {
|
||||||
|
if (following) {
|
||||||
|
return '#fa-user-times'
|
||||||
|
} else if (followRequested) {
|
||||||
|
return '#fa-hourglass'
|
||||||
|
} else {
|
||||||
|
return '#fa-user-plus'
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onFollowButtonClick() {
|
async onFollowButtonClick() {
|
||||||
let accountId = this.get('profile').id
|
let accountId = this.get('profile').id
|
||||||
let instanceName = this.store.get('currentInstance')
|
let instanceName = this.store.get('currentInstance')
|
||||||
let following = this.get('following')
|
let following = this.get('following')
|
||||||
await setAccountFollowed(accountId, !following)
|
let followRequested = this.get('followRequested')
|
||||||
|
await setAccountFollowed(accountId, !(following || followRequested))
|
||||||
this.set({relationship: await database.getRelationship(instanceName, accountId)})
|
this.set({relationship: await database.getRelationship(instanceName, accountId)})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,22 +14,25 @@ export default {
|
||||||
account: ($currentAccountProfile) => $currentAccountProfile,
|
account: ($currentAccountProfile) => $currentAccountProfile,
|
||||||
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials,
|
verifyCredentials: ($currentVerifyCredentials) => $currentVerifyCredentials,
|
||||||
verifyCredentialsId: (verifyCredentials) => verifyCredentials.id,
|
verifyCredentialsId: (verifyCredentials) => verifyCredentials.id,
|
||||||
following: (relationship) => relationship && !!relationship.following,
|
following: (relationship) => relationship && relationship.following,
|
||||||
|
followRequested: (relationship) => relationship && relationship.requested,
|
||||||
accountName: (account) => account && (account.display_name || account.acct),
|
accountName: (account) => account && (account.display_name || account.acct),
|
||||||
accountId: (account) => account && account.id,
|
accountId: (account) => account && account.id,
|
||||||
followLabel: (following, accountName) => {
|
followLabel: (following, followRequested, accountName) => {
|
||||||
if (typeof following === 'undefined' || !accountName) {
|
if (typeof following === 'undefined' || !accountName) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return following ? `Unfollow ${accountName}` : `Follow ${accountName}`
|
return (following || followRequested)
|
||||||
|
? `Unfollow ${accountName}`
|
||||||
|
: `Follow ${accountName}`
|
||||||
},
|
},
|
||||||
items: (followLabel, following, accountId, verifyCredentialsId) => (
|
items: (followLabel, following, followRequested, accountId, verifyCredentialsId) => (
|
||||||
[
|
[
|
||||||
accountId !== verifyCredentialsId &&
|
accountId !== verifyCredentialsId &&
|
||||||
{
|
{
|
||||||
key: 'follow',
|
key: 'follow',
|
||||||
label: followLabel,
|
label: followLabel,
|
||||||
icon: following ? '#fa-user-times' : '#fa-user-plus'
|
icon: following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus'
|
||||||
},
|
},
|
||||||
accountId === verifyCredentialsId &&
|
accountId === verifyCredentialsId &&
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<:Head>
|
<:Head>
|
||||||
<title>Pinafore – {{profileName}}</title>
|
<title>Pinafore – Profile</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
<Layout page='tags'>
|
<Layout page='tags'>
|
||||||
<LazyPage :pageComponent :params />
|
<LazyPage :pageComponent :params />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<:Head>
|
<:Head>
|
||||||
<title>Pinafore – {{listTitle}}</title>
|
<title>Pinafore – List</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
<Layout page='lists'>
|
<Layout page='lists'>
|
||||||
<LazyPage :pageComponent :params />
|
<LazyPage :pageComponent :params />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<:Head>
|
<:Head>
|
||||||
<title>Pinafore – {{params.instanceName}}</title>
|
<title>Pinafore – Instance</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
<Layout page='settings'>
|
<Layout page='settings'>
|
||||||
<LazyPage :pageComponent :params />
|
<LazyPage :pageComponent :params />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<:Head>
|
<:Head>
|
||||||
<title>Pinafore – #{{params.tagName}}</title>
|
<title>Pinafore – Hashtag</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
<Layout page='tags'>
|
<Layout page='tags'>
|
||||||
<LazyPage :pageComponent :params />
|
<LazyPage :pageComponent :params />
|
||||||
|
|
|
@ -96,6 +96,7 @@ body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-o
|
||||||
<symbol id="fa-exclamation-triangle" viewBox="0 0 1792 1792"><title>Content warning</title><path d="M1024 1375v-190q0-14-9.5-23.5T992 1152H800q-13 0-22.5 9.5T768 1185v190q0 14 9.5 23.5t22.5 9.5h192q13 0 22.5-9.5t9.5-23.5zm-2-374l18-459q0-12-10-19-13-11-24-11H786q-11 0-24 11-10 7-10 21l17 457q0 10 10 16.5t24 6.5h185q14 0 23.5-6.5t10.5-16.5zm-14-934l768 1408q35 63-2 126-17 29-46.5 46t-63.5 17H128q-34 0-63.5-17T18 1601q-37-63-2-126L784 67q17-31 47-49t65-18 65 18 47 49z"></path></symbol>
|
<symbol id="fa-exclamation-triangle" viewBox="0 0 1792 1792"><title>Content warning</title><path d="M1024 1375v-190q0-14-9.5-23.5T992 1152H800q-13 0-22.5 9.5T768 1185v190q0 14 9.5 23.5t22.5 9.5h192q13 0 22.5-9.5t9.5-23.5zm-2-374l18-459q0-12-10-19-13-11-24-11H786q-11 0-24 11-10 7-10 21l17 457q0 10 10 16.5t24 6.5h185q14 0 23.5-6.5t10.5-16.5zm-14-934l768 1408q35 63-2 126-17 29-46.5 46t-63.5 17H128q-34 0-63.5-17T18 1601q-37-63-2-126L784 67q17-31 47-49t65-18 65 18 47 49z"></path></symbol>
|
||||||
<symbol id="fa-check" viewBox="0 0 1792 1792"><title>Check</title><path d="M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"></path></symbol>
|
<symbol id="fa-check" viewBox="0 0 1792 1792"><title>Check</title><path d="M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"></path></symbol>
|
||||||
<symbol id="fa-trash" viewBox="0 0 1792 1792"><title>Delete</title><path d="M704 736v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm128 724V512H448v948q0 22 7 40.5t14.5 27 10.5 8.5h832q3 0 10.5-8.5t14.5-27 7-40.5zM672 384h448l-48-117q-7-9-17-11H738q-10 2-17 11zm928 32v64q0 14-9 23t-23 9h-96v948q0 83-47 143.5t-113 60.5H480q-66 0-113-58.5T320 1464V512h-96q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h309l70-167q15-37 54-63t79-26h320q40 0 79 26t54 63l70 167h309q14 0 23 9t9 23z"></path></symbol>
|
<symbol id="fa-trash" viewBox="0 0 1792 1792"><title>Delete</title><path d="M704 736v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23V736q0-14 9-23t23-9h64q14 0 23 9t9 23zm128 724V512H448v948q0 22 7 40.5t14.5 27 10.5 8.5h832q3 0 10.5-8.5t14.5-27 7-40.5zM672 384h448l-48-117q-7-9-17-11H738q-10 2-17 11zm928 32v64q0 14-9 23t-23 9h-96v948q0 83-47 143.5t-113 60.5H480q-66 0-113-58.5T320 1464V512h-96q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h309l70-167q15-37 54-63t79-26h320q40 0 79 26t54 63l70 167h309q14 0 23 9t9 23z"></path></symbol>
|
||||||
|
<symbol id="fa-hourglass" viewBox="0 0 1792 1792"><title>Follow requested</title><path d="M1632 1600q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23v-128q0-14 9-23t23-9h1472zm-1374-64q3-55 16-107t30-95 46-87 53.5-76 64.5-69.5 66-60 70.5-55T671 939t65-43q-43-28-65-43t-66.5-47.5-70.5-55-66-60-64.5-69.5-53.5-76-46-87-30-95-16-107h1276q-3 55-16 107t-30 95-46 87-53.5 76-64.5 69.5-66 60-70.5 55T1121 853t-65 43q43 28 65 43t66.5 47.5 70.5 55 66 60 64.5 69.5 53.5 76 46 87 30 95 16 107H258zM1632 0q14 0 23 9t9 23v128q0 14-9 23t-23 9H160q-14 0-23-9t-9-23V32q0-14 9-23t23-9h1472z"></path></symbol>
|
||||||
</svg><!-- end insert svg here -->
|
</svg><!-- end insert svg here -->
|
||||||
</svg>
|
</svg>
|
||||||
<!-- The application will be rendered inside this element,
|
<!-- The application will be rendered inside this element,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import FileApi from 'file-api'
|
||||||
import { users } from './users'
|
import { users } from './users'
|
||||||
import { postStatus } from '../routes/_api/statuses'
|
import { postStatus } from '../routes/_api/statuses'
|
||||||
import { deleteStatus } from '../routes/_api/delete'
|
import { deleteStatus } from '../routes/_api/delete'
|
||||||
|
import { authorizeFollowRequest, getFollowRequests } from '../routes/_actions/followRequests'
|
||||||
|
|
||||||
global.fetch = fetch
|
global.fetch = fetch
|
||||||
global.File = FileApi.File
|
global.File = FileApi.File
|
||||||
|
@ -28,3 +29,11 @@ export async function postReplyAsAdmin (text, inReplyTo) {
|
||||||
export async function deleteAsAdmin (statusId) {
|
export async function deleteAsAdmin (statusId) {
|
||||||
return deleteStatus(instanceName, users.admin.accessToken, statusId)
|
return deleteStatus(instanceName, users.admin.accessToken, statusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getFollowRequestsAsLockedAccount () {
|
||||||
|
return getFollowRequests(instanceName, users.LockedAccount.accessToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function authorizeFollowRequestAsLockedAccount (id) {
|
||||||
|
return authorizeFollowRequest(instanceName, users.LockedAccount.accessToken, id)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { Selector as $ } from 'testcafe'
|
import { Selector as $ } from 'testcafe'
|
||||||
import { getUrl, validateTimeline } from '../utils'
|
import {
|
||||||
|
accountProfileFollowButton,
|
||||||
|
accountProfileFollowedBy, accountProfileName, accountProfileUsername, getUrl,
|
||||||
|
validateTimeline
|
||||||
|
} from '../utils'
|
||||||
import { foobarRole } from '../roles'
|
import { foobarRole } from '../roles'
|
||||||
import { quuxStatuses } from '../fixtures'
|
import { quuxStatuses } from '../fixtures'
|
||||||
|
|
||||||
|
@ -10,32 +14,32 @@ test('shows account profile', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.click($('.status-author-name').withText(('quux')))
|
.click($('.status-author-name').withText(('quux')))
|
||||||
.expect(getUrl()).contains('/accounts/3')
|
.expect(getUrl()).contains('/accounts/3')
|
||||||
.expect($('.account-profile .account-profile-name').innerText).contains('quux')
|
.expect(accountProfileName.innerText).contains('quux')
|
||||||
.expect($('.account-profile .account-profile-username').innerText).contains('@quux')
|
.expect(accountProfileUsername.innerText).contains('@quux')
|
||||||
.expect($('.account-profile .account-profile-followed-by').innerText).match(/follows you/i)
|
.expect(accountProfileFollowedBy.innerText).match(/follows you/i)
|
||||||
.expect($('.account-profile .account-profile-follow button').getAttribute('aria-label')).eql('Follow')
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow')
|
||||||
.expect($('.account-profile .account-profile-follow button').getAttribute('aria-pressed')).eql('false')
|
.expect(accountProfileFollowButton.getAttribute('aria-pressed')).eql('false')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('shows account profile 2', async t => {
|
test('shows account profile 2', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.click($('.status-author-name').withText(('admin')))
|
.click($('.status-author-name').withText(('admin')))
|
||||||
.expect(getUrl()).contains('/accounts/1')
|
.expect(getUrl()).contains('/accounts/1')
|
||||||
.expect($('.account-profile .account-profile-name').innerText).contains('admin')
|
.expect(accountProfileName.innerText).contains('admin')
|
||||||
.expect($('.account-profile .account-profile-username').innerText).contains('@admin')
|
.expect(accountProfileUsername.innerText).contains('@admin')
|
||||||
.expect($('.account-profile .account-profile-followed-by').innerText).match(/follows you/i)
|
.expect(accountProfileFollowedBy.innerText).match(/follows you/i)
|
||||||
.expect($('.account-profile .account-profile-follow button').getAttribute('aria-label')).eql('Unfollow')
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Unfollow')
|
||||||
.expect($('.account-profile .account-profile-follow button').getAttribute('aria-pressed')).eql('true')
|
.expect(accountProfileFollowButton.getAttribute('aria-pressed')).eql('true')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('shows account profile 3', async t => {
|
test('shows account profile 3', async t => {
|
||||||
await t.useRole(foobarRole)
|
await t.useRole(foobarRole)
|
||||||
.click($('.mention').withText(('foobar')))
|
.click($('.mention').withText(('foobar')))
|
||||||
.expect(getUrl()).contains('/accounts/2')
|
.expect(getUrl()).contains('/accounts/2')
|
||||||
.expect($('.account-profile .account-profile-name').innerText).contains('foobar')
|
.expect(accountProfileName.innerText).contains('foobar')
|
||||||
.expect($('.account-profile .account-profile-username').innerText).contains('@foobar')
|
.expect(accountProfileUsername.innerText).contains('@foobar')
|
||||||
// can't follow or be followed by your own account
|
// can't follow or be followed by your own account
|
||||||
.expect($('.account-profile .account-profile-followed-by').innerText).eql('')
|
.expect(accountProfileFollowedBy.innerText).eql('')
|
||||||
.expect($('.account-profile .account-profile-follow').innerText).eql('')
|
.expect($('.account-profile .account-profile-follow').innerText).eql('')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
35
tests/spec/106-follow-requests.js
Normal file
35
tests/spec/106-follow-requests.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { foobarRole } from '../roles'
|
||||||
|
import {
|
||||||
|
accountProfileFollowButton,
|
||||||
|
getNthStatus,
|
||||||
|
sleep
|
||||||
|
} from '../utils'
|
||||||
|
import {
|
||||||
|
authorizeFollowRequestAsLockedAccount, getFollowRequestsAsLockedAccount
|
||||||
|
} from '../serverActions'
|
||||||
|
|
||||||
|
fixture`106-follow-requests.js`
|
||||||
|
.page`http://localhost:4002`
|
||||||
|
|
||||||
|
test('can request to follow an account', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.navigateTo('/accounts/6')
|
||||||
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow')
|
||||||
|
.click(accountProfileFollowButton)
|
||||||
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Unfollow (follow requested)')
|
||||||
|
.click(accountProfileFollowButton)
|
||||||
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow')
|
||||||
|
.click(accountProfileFollowButton)
|
||||||
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Unfollow (follow requested)')
|
||||||
|
|
||||||
|
let requests = await getFollowRequestsAsLockedAccount()
|
||||||
|
await authorizeFollowRequestAsLockedAccount(requests.slice(-1)[0].id)
|
||||||
|
|
||||||
|
await sleep(2000)
|
||||||
|
|
||||||
|
await t.navigateTo('/accounts/6')
|
||||||
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Unfollow')
|
||||||
|
.expect(getNthStatus(0).innerText).contains('This account is locked')
|
||||||
|
.click(accountProfileFollowButton)
|
||||||
|
.expect(accountProfileFollowButton.getAttribute('aria-label')).eql('Follow')
|
||||||
|
})
|
|
@ -28,5 +28,11 @@ export const users = {
|
||||||
password: 'bazbazbaz',
|
password: 'bazbazbaz',
|
||||||
accessToken: '0639238783efdfde849304bc89ec0c4b60b5ef5f261f60859fcd597de081cfdc',
|
accessToken: '0639238783efdfde849304bc89ec0c4b60b5ef5f261f60859fcd597de081cfdc',
|
||||||
id: 5
|
id: 5
|
||||||
|
},
|
||||||
|
LockedAccount: {
|
||||||
|
username: 'LockedAccount',
|
||||||
|
password: 'LockedAccountLockedAccount',
|
||||||
|
accessToken: '39ed9aeffa4b25eda4940f22f29fea66e625c6282c2a8bf0430203c9779e9e98',
|
||||||
|
id: 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@ export const logInToInstanceLink = $('a[href="/settings/instances/add"]')
|
||||||
export const searchInput = $('.search-input')
|
export const searchInput = $('.search-input')
|
||||||
export const postStatusButton = $('.compose-box-button')
|
export const postStatusButton = $('.compose-box-button')
|
||||||
export const showMoreButton = $('.more-items-header button')
|
export const showMoreButton = $('.more-items-header button')
|
||||||
|
export const accountProfileName = $('.account-profile .account-profile-name')
|
||||||
|
export const accountProfileUsername = $('.account-profile .account-profile-username')
|
||||||
|
export const accountProfileFollowedBy = $('.account-profile .account-profile-followed-by')
|
||||||
|
export const accountProfileFollowButton = $('.account-profile .account-profile-follow button')
|
||||||
|
|
||||||
export const favoritesCountElement = $('.status-favs-reblogs:nth-child(3)').addCustomDOMProperties({
|
export const favoritesCountElement = $('.status-favs-reblogs:nth-child(3)').addCustomDOMProperties({
|
||||||
innerCount: el => parseInt(el.innerText, 10)
|
innerCount: el => parseInt(el.innerText, 10)
|
||||||
|
|
Loading…
Reference in a new issue