Fix lightbox mock test

This commit is contained in:
Fedor Indutny
2025-08-05 13:37:47 -07:00
committed by GitHub
parent f80aef0ba4
commit 98ba28d726
6 changed files with 69 additions and 63 deletions

View File

@@ -393,7 +393,7 @@ export const CompositionArea = memo(function CompositionArea({
const draftEditMessageBody = draftEditMessage?.body; const draftEditMessageBody = draftEditMessage?.body;
const editedMessageId = draftEditMessage?.targetMessageId; const editedMessageId = draftEditMessage?.targetMessageId;
const canSend = let canSend =
// Text or link preview edited // Text or link preview edited
dirty || dirty ||
// Quote of edited message changed // Quote of edited message changed
@@ -406,6 +406,11 @@ export const CompositionArea = memo(function CompositionArea({
// Not edit message, but has attachments // Not edit message, but has attachments
(draftEditMessage == null && draftAttachments.length !== 0); (draftEditMessage == null && draftAttachments.length !== 0);
// Draft attachments should finish loading
if (draftAttachments.some(attachment => attachment.pending)) {
canSend = false;
}
const handleSubmit = useCallback( const handleSubmit = useCallback(
( (
message: string, message: string,

View File

@@ -232,6 +232,7 @@ export function Image({
className={classNames( className={classNames(
'module-image', 'module-image',
className, className,
attachment.path ? 'module-image--loaded' : null,
!noBackground ? 'module-image--with-background' : null, !noBackground ? 'module-image--with-background' : null,
cropWidth || cropHeight ? 'module-image--cropped' : null cropWidth || cropHeight ? 'module-image--cropped' : null
)} )}

View File

@@ -103,7 +103,7 @@ const log = createLogger('composer');
type ComposerStateByConversationType = { type ComposerStateByConversationType = {
attachments: ReadonlyArray<AttachmentDraftType>; attachments: ReadonlyArray<AttachmentDraftType>;
focusCounter: number; focusCounter: number;
isDisabled: boolean; disabledCounter: number;
linkPreviewLoading: boolean; linkPreviewLoading: boolean;
linkPreviewResult?: LinkPreviewForUIType; linkPreviewResult?: LinkPreviewForUIType;
messageCompositionId: string; messageCompositionId: string;
@@ -128,7 +128,7 @@ function getEmptyComposerState(): ComposerStateByConversationType {
return { return {
attachments: [], attachments: [],
focusCounter: 0, focusCounter: 0,
isDisabled: false, disabledCounter: 0,
linkPreviewLoading: false, linkPreviewLoading: false,
messageCompositionId: generateUuid(), messageCompositionId: generateUuid(),
sendCounter: 0, sendCounter: 0,
@@ -151,7 +151,7 @@ const RESET_COMPOSER = 'composer/RESET_COMPOSER';
export const SET_FOCUS = 'composer/SET_FOCUS'; export const SET_FOCUS = 'composer/SET_FOCUS';
const SET_HIGH_QUALITY_SETTING = 'composer/SET_HIGH_QUALITY_SETTING'; const SET_HIGH_QUALITY_SETTING = 'composer/SET_HIGH_QUALITY_SETTING';
const SET_QUOTED_MESSAGE = 'composer/SET_QUOTED_MESSAGE'; const SET_QUOTED_MESSAGE = 'composer/SET_QUOTED_MESSAGE';
const SET_COMPOSER_DISABLED = 'composer/SET_COMPOSER_DISABLED'; const UPDATE_COMPOSER_DISABLED = 'composer/UPDATE_COMPOSER_DISABLED';
type AddPendingAttachmentActionType = ReadonlyDeep<{ type AddPendingAttachmentActionType = ReadonlyDeep<{
type: typeof ADD_PENDING_ATTACHMENT; type: typeof ADD_PENDING_ATTACHMENT;
@@ -184,8 +184,8 @@ export type ResetComposerActionType = ReadonlyDeep<{
}; };
}>; }>;
type SetComposerDisabledStateActionType = ReadonlyDeep<{ type UpdateComposerDisabledActionType = ReadonlyDeep<{
type: typeof SET_COMPOSER_DISABLED; type: typeof UPDATE_COMPOSER_DISABLED;
payload: { payload: {
conversationId: string; conversationId: string;
value: boolean; value: boolean;
@@ -226,7 +226,7 @@ type ComposerActionType =
| ReplaceAttachmentsActionType | ReplaceAttachmentsActionType
| ResetComposerActionType | ResetComposerActionType
| TargetedConversationChangedActionType | TargetedConversationChangedActionType
| SetComposerDisabledStateActionType | UpdateComposerDisabledActionType
| SetFocusActionType | SetFocusActionType
| SetHighQualitySettingActionType | SetHighQualitySettingActionType
| SetQuotedMessageActionType; | SetQuotedMessageActionType;
@@ -252,11 +252,11 @@ export const actions = {
sendEditedMessage, sendEditedMessage,
sendMultiMediaMessage, sendMultiMediaMessage,
sendStickerMessage, sendStickerMessage,
setComposerDisabledState,
setComposerFocus, setComposerFocus,
setMediaQualitySetting, setMediaQualitySetting,
setQuoteByMessageId, setQuoteByMessageId,
setQuotedMessage, setQuotedMessage,
updateComposerDisabled,
}; };
function incrementSendCounter(conversationId: string): IncrementSendActionType { function incrementSendCounter(conversationId: string): IncrementSendActionType {
@@ -413,7 +413,7 @@ async function withPreSendChecks(
dispatch: ThunkDispatch< dispatch: ThunkDispatch<
RootStateType, RootStateType,
unknown, unknown,
SetComposerDisabledStateActionType | ShowToastActionType UpdateComposerDisabledActionType | ShowToastActionType
>, >,
body: () => Promise<void> body: () => Promise<void>
): Promise<void> { ): Promise<void> {
@@ -432,7 +432,7 @@ async function withPreSendChecks(
options.draftAttachments ?? conversation.attributes.draftAttachments; options.draftAttachments ?? conversation.attributes.draftAttachments;
try { try {
dispatch(setComposerDisabledState(conversationId, true)); dispatch(updateComposerDisabled(conversationId, true));
try { try {
const sendAnyway = await blockSendUntilConversationsAreVerified( const sendAnyway = await blockSendUntilConversationsAreVerified(
@@ -440,7 +440,6 @@ async function withPreSendChecks(
SafetyNumberChangeSource.MessageSend SafetyNumberChangeSource.MessageSend
); );
if (!sendAnyway) { if (!sendAnyway) {
dispatch(setComposerDisabledState(conversationId, false));
return; return;
} }
} catch (error) { } catch (error) {
@@ -475,7 +474,7 @@ async function withPreSendChecks(
await body(); await body();
} finally { } finally {
dispatch(setComposerDisabledState(conversationId, false)); dispatch(updateComposerDisabled(conversationId, false));
} }
conversation.clearTypingTimers(); conversation.clearTypingTimers();
@@ -493,7 +492,7 @@ function sendEditedMessage(
void, void,
RootStateType, RootStateType,
unknown, unknown,
SetComposerDisabledStateActionType | ShowToastActionType UpdateComposerDisabledActionType | ShowToastActionType
> { > {
return async dispatch => { return async dispatch => {
const conversation = window.ConversationController.get(conversationId); const conversation = window.ConversationController.get(conversationId);
@@ -548,7 +547,7 @@ function sendMultiMediaMessage(
| IncrementSendActionType | IncrementSendActionType
| NoopActionType | NoopActionType
| ResetComposerActionType | ResetComposerActionType
| SetComposerDisabledStateActionType | UpdateComposerDisabledActionType
| SetQuotedMessageActionType | SetQuotedMessageActionType
| ShowToastActionType | ShowToastActionType
> { > {
@@ -622,7 +621,6 @@ function sendMultiMediaMessage(
undefined undefined
); );
dispatch(incrementSendCounter(conversationId)); dispatch(incrementSendCounter(conversationId));
dispatch(setComposerDisabledState(conversationId, false));
if (state.items.audioMessage) { if (state.items.audioMessage) {
drop(new Sound({ soundType: SoundType.Whoosh }).play()); drop(new Sound({ soundType: SoundType.Whoosh }).play());
@@ -707,12 +705,7 @@ function getAttachmentsFromConversationModel(
export function setQuoteByMessageId( export function setQuoteByMessageId(
conversationId: string, conversationId: string,
messageId: string | undefined messageId: string | undefined
): ThunkAction< ): ThunkAction<void, RootStateType, unknown, SetQuotedMessageActionType> {
void,
RootStateType,
unknown,
SetComposerDisabledStateActionType | SetQuotedMessageActionType
> {
return async (dispatch, getState) => { return async (dispatch, getState) => {
const conversation = window.ConversationController.get(conversationId); const conversation = window.ConversationController.get(conversationId);
if (!conversation) { if (!conversation) {
@@ -790,7 +783,6 @@ export function setQuoteByMessageId(
); );
dispatch(setComposerFocus(conversation.id)); dispatch(setComposerFocus(conversation.id));
dispatch(setComposerDisabledState(conversationId, false));
} else { } else {
dispatch(setQuotedMessage(conversationId, undefined)); dispatch(setQuotedMessage(conversationId, undefined));
} }
@@ -1006,7 +998,7 @@ function processAttachments({
void, void,
RootStateType, RootStateType,
unknown, unknown,
NoopActionType | ShowToastActionType NoopActionType | ShowToastActionType | UpdateComposerDisabledActionType
> { > {
return async (dispatch, getState) => { return async (dispatch, getState) => {
if (!files.length) { if (!files.length) {
@@ -1062,6 +1054,9 @@ function processAttachments({
} }
} }
dispatch(updateComposerDisabled(conversationId, true));
try {
await Promise.all( await Promise.all(
filesToProcess.map(async file => { filesToProcess.map(async file => {
try { try {
@@ -1096,6 +1091,9 @@ function processAttachments({
} }
}) })
); );
} finally {
dispatch(updateComposerDisabled(conversationId, false));
}
if (toastToShow) { if (toastToShow) {
dispatch({ dispatch({
@@ -1349,12 +1347,12 @@ function saveDraft(
} }
} }
function setComposerDisabledState( function updateComposerDisabled(
conversationId: string, conversationId: string,
value: boolean value: boolean
): SetComposerDisabledStateActionType { ): UpdateComposerDisabledActionType {
return { return {
type: SET_COMPOSER_DISABLED, type: UPDATE_COMPOSER_DISABLED,
payload: { payload: {
conversationId, conversationId,
value, value,
@@ -1525,9 +1523,10 @@ export function reducer(
})); }));
} }
if (action.type === SET_COMPOSER_DISABLED) { if (action.type === UPDATE_COMPOSER_DISABLED) {
return updateComposerState(state, action, () => ({ return updateComposerState(state, action, oldState => ({
isDisabled: action.payload.value, disabledCounter:
oldState.disabledCounter + (action.payload.value ? 1 : -1),
})); }));
} }

View File

@@ -127,7 +127,7 @@ export const SmartCompositionArea = memo(function SmartCompositionArea({
const { const {
attachments: draftAttachments, attachments: draftAttachments,
focusCounter, focusCounter,
isDisabled, disabledCounter,
linkPreviewLoading, linkPreviewLoading,
linkPreviewResult, linkPreviewResult,
messageCompositionId, messageCompositionId,
@@ -135,6 +135,8 @@ export const SmartCompositionArea = memo(function SmartCompositionArea({
shouldSendHighQualityAttachments, shouldSendHighQualityAttachments,
} = composerState; } = composerState;
const isDisabled = disabledCounter > 0;
const areSelectedMessagesForwardable = useMemo(() => { const areSelectedMessagesForwardable = useMemo(() => {
return selectedMessageIds?.every(messageId => { return selectedMessageIds?.every(messageId => {
const message = messageLookup[messageId]; const message = messageLookup[messageId];

View File

@@ -335,16 +335,15 @@ export async function composerAttachImages(
const AttachmentInput = page.getByTestId('attachfile-input'); const AttachmentInput = page.getByTestId('attachfile-input');
const AttachmentsList = page.locator('.module-attachments'); const AttachmentsList = page.locator('.module-attachments');
const AttachmentsListImage = AttachmentsList.locator('.module-image'); const AttachmentsListImageLoaded = AttachmentsList.locator(
const AttachmentsListImageLoaded = AttachmentsListImage.locator( '.module-image--loaded'
'.module-image__image'
); );
debug('setting input files'); debug('setting input files');
await AttachmentInput.setInputFiles(filePaths); await AttachmentInput.setInputFiles(filePaths);
debug(`waiting for ${filePaths.length} items`); debug(`waiting for ${filePaths.length} items`);
await AttachmentsListImage.nth(filePaths.length - 1).waitFor(); await AttachmentsListImageLoaded.nth(filePaths.length - 1).waitFor();
await Promise.all( await Promise.all(
filePaths.map(async (_, index) => { filePaths.map(async (_, index) => {

View File

@@ -78,7 +78,7 @@ describe('lightbox', function (this: Mocha.Suite) {
}); });
debug('wait for message to appear in timeline'); debug('wait for message to appear in timeline');
const Message = getMessageInTimelineByTimestamp(page, timestamp); const Message = getMessageInTimelineByTimestamp(page, timestamp);
const MessageImageLoaded = Message.locator('img.module-image__image'); const MessageImageLoaded = Message.locator('.module-image--loaded');
await Message.waitFor(); await Message.waitFor();