This repository has been archived by the owner on Sep 11, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 828
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6895 from andybalaam/simon-auto-avatars
Use fallback avatar only for DMs with 2 people
- Loading branch information
Showing
3 changed files
with
266 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
import "../../../skinned-sdk"; | ||
|
||
import * as TestUtils from '../../../test-utils'; | ||
|
||
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg'; | ||
|
||
import DMRoomMap from '../../../../src/utils/DMRoomMap'; | ||
import RoomHeader from '../../../../src/components/views/rooms/RoomHeader'; | ||
|
||
import { Room, PendingEventOrdering, MatrixEvent, MatrixClient } from 'matrix-js-sdk'; | ||
import { SearchScope } from '../../../../src/components/views/rooms/SearchBar'; | ||
import { E2EStatus } from '../../../../src/utils/ShieldUtils'; | ||
import { PlaceCallType } from '../../../../src/CallHandler'; | ||
import { mkEvent } from '../../../test-utils'; | ||
|
||
describe('RoomHeader', () => { | ||
it('shows the room avatar in a room with only ourselves', () => { | ||
// When we render a non-DM room with 1 person in it | ||
const room = createRoom({ name: "X Room", isDm: false, userIds: [] }); | ||
const rendered = render(room); | ||
|
||
// Then the room's avatar is the initial of its name | ||
const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); | ||
expect(initial.innerHTML).toEqual("X"); | ||
|
||
// And there is no image avatar (because it's not set on this room) | ||
const image = findImg(rendered, ".mx_BaseAvatar_image"); | ||
expect(image.src).toEqual("data:image/png;base64,00"); | ||
}); | ||
|
||
it('shows the room avatar in a room with 2 people', () => { | ||
// When we render a non-DM room with 2 people in it | ||
const room = createRoom( | ||
{ name: "Y Room", isDm: false, userIds: ["other"] }); | ||
const rendered = render(room); | ||
|
||
// Then the room's avatar is the initial of its name | ||
const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); | ||
expect(initial.innerHTML).toEqual("Y"); | ||
|
||
// And there is no image avatar (because it's not set on this room) | ||
const image = findImg(rendered, ".mx_BaseAvatar_image"); | ||
expect(image.src).toEqual("data:image/png;base64,00"); | ||
}); | ||
|
||
it('shows the room avatar in a room with >2 people', () => { | ||
// When we render a non-DM room with 3 people in it | ||
const room = createRoom( | ||
{ name: "Z Room", isDm: false, userIds: ["other1", "other2"] }); | ||
const rendered = render(room); | ||
|
||
// Then the room's avatar is the initial of its name | ||
const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); | ||
expect(initial.innerHTML).toEqual("Z"); | ||
|
||
// And there is no image avatar (because it's not set on this room) | ||
const image = findImg(rendered, ".mx_BaseAvatar_image"); | ||
expect(image.src).toEqual("data:image/png;base64,00"); | ||
}); | ||
|
||
it('shows the room avatar in a DM with only ourselves', () => { | ||
// When we render a non-DM room with 1 person in it | ||
const room = createRoom({ name: "Z Room", isDm: true, userIds: [] }); | ||
const rendered = render(room); | ||
|
||
// Then the room's avatar is the initial of its name | ||
const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); | ||
expect(initial.innerHTML).toEqual("Z"); | ||
|
||
// And there is no image avatar (because it's not set on this room) | ||
const image = findImg(rendered, ".mx_BaseAvatar_image"); | ||
expect(image.src).toEqual("data:image/png;base64,00"); | ||
}); | ||
|
||
it('shows the user avatar in a DM with 2 people', () => { | ||
// Note: this is the interesting case - this is the ONLY | ||
// time we should use the user's avatar. | ||
|
||
// When we render a DM room with only 2 people in it | ||
const room = createRoom({ name: "Y Room", isDm: true, userIds: ["other"] }); | ||
const rendered = render(room); | ||
|
||
// Then we use the other user's avatar as our room's image avatar | ||
const image = findImg(rendered, ".mx_BaseAvatar_image"); | ||
expect(image.src).toEqual( | ||
"http://this.is.a.url/example.org/other"); | ||
|
||
// And there is no initial avatar | ||
expect( | ||
rendered.querySelectorAll(".mx_BaseAvatar_initial"), | ||
).toHaveLength(0); | ||
}); | ||
|
||
it('shows the room avatar in a DM with >2 people', () => { | ||
// When we render a DM room with 3 people in it | ||
const room = createRoom({ | ||
name: "Z Room", isDm: true, userIds: ["other1", "other2"] }); | ||
const rendered = render(room); | ||
|
||
// Then the room's avatar is the initial of its name | ||
const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); | ||
expect(initial.innerHTML).toEqual("Z"); | ||
|
||
// And there is no image avatar (because it's not set on this room) | ||
const image = findImg(rendered, ".mx_BaseAvatar_image"); | ||
expect(image.src).toEqual("data:image/png;base64,00"); | ||
}); | ||
}); | ||
|
||
interface IRoomCreationInfo { | ||
name: string; | ||
isDm: boolean; | ||
userIds: string[]; | ||
} | ||
|
||
function createRoom(info: IRoomCreationInfo) { | ||
TestUtils.stubClient(); | ||
const client: MatrixClient = MatrixClientPeg.get(); | ||
|
||
const roomId = '!1234567890:domain'; | ||
const userId = client.getUserId(); | ||
if (info.isDm) { | ||
client.getAccountData = (eventType) => { | ||
expect(eventType).toEqual("m.direct"); | ||
return mkDirectEvent(roomId, userId, info.userIds); | ||
}; | ||
} | ||
|
||
DMRoomMap.makeShared().start(); | ||
|
||
const room = new Room(roomId, client, userId, { | ||
pendingEventOrdering: PendingEventOrdering.Detached, | ||
}); | ||
|
||
const otherJoinEvents = []; | ||
for (const otherUserId of info.userIds) { | ||
otherJoinEvents.push(mkJoinEvent(roomId, otherUserId)); | ||
} | ||
|
||
room.currentState.setStateEvents([ | ||
mkCreationEvent(roomId, userId), | ||
mkNameEvent(roomId, userId, info.name), | ||
mkJoinEvent(roomId, userId), | ||
...otherJoinEvents, | ||
]); | ||
room.recalculate(); | ||
|
||
return room; | ||
} | ||
|
||
function render(room: Room): HTMLDivElement { | ||
const parentDiv = document.createElement('div'); | ||
document.body.appendChild(parentDiv); | ||
ReactDOM.render( | ||
( | ||
<RoomHeader | ||
room={room} | ||
inRoom={true} | ||
onSettingsClick={() => {}} | ||
onSearchClick={() => {}} | ||
onForgetClick={() => {}} | ||
onCallPlaced={(_type: PlaceCallType) => {}} | ||
onAppsClick={() => {}} | ||
e2eStatus={E2EStatus.Normal} | ||
appsShown={true} | ||
searchInfo={{ | ||
searchTerm: "", | ||
searchScope: SearchScope.Room, | ||
searchCount: 0, | ||
}} | ||
/> | ||
), | ||
parentDiv, | ||
); | ||
return parentDiv; | ||
} | ||
|
||
function mkCreationEvent(roomId: string, userId: string): MatrixEvent { | ||
return mkEvent({ | ||
event: true, | ||
type: "m.room.create", | ||
room: roomId, | ||
user: userId, | ||
content: { | ||
creator: userId, | ||
room_version: "5", | ||
predecessor: { | ||
room_id: "!prevroom", | ||
event_id: "$someevent", | ||
}, | ||
}, | ||
}); | ||
} | ||
|
||
function mkNameEvent( | ||
roomId: string, userId: string, name: string, | ||
): MatrixEvent { | ||
return mkEvent({ | ||
event: true, | ||
type: "m.room.name", | ||
room: roomId, | ||
user: userId, | ||
content: { name }, | ||
}); | ||
} | ||
|
||
function mkJoinEvent(roomId: string, userId: string) { | ||
const ret = mkEvent({ | ||
event: true, | ||
type: "m.room.member", | ||
room: roomId, | ||
user: userId, | ||
content: { | ||
"membership": "join", | ||
"avatar_url": "mxc://example.org/" + userId, | ||
}, | ||
}); | ||
ret.event.state_key = userId; | ||
return ret; | ||
} | ||
|
||
function mkDirectEvent( | ||
roomId: string, userId: string, otherUsers: string[], | ||
): MatrixEvent { | ||
const content = {}; | ||
for (const otherUserId of otherUsers) { | ||
content[otherUserId] = [roomId]; | ||
} | ||
return mkEvent({ | ||
event: true, | ||
type: "m.direct", | ||
room: roomId, | ||
user: userId, | ||
content, | ||
}); | ||
} | ||
|
||
function findSpan(parent: HTMLElement, selector: string): HTMLSpanElement { | ||
const els = parent.querySelectorAll(selector); | ||
expect(els.length).toEqual(1); | ||
return els[0] as HTMLSpanElement; | ||
} | ||
|
||
function findImg(parent: HTMLElement, selector: string): HTMLImageElement { | ||
const els = parent.querySelectorAll(selector); | ||
expect(els.length).toEqual(1); | ||
return els[0] as HTMLImageElement; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters