Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,15 @@ export class Poll {
const { id: _id, ...pollData } = extractPollData(event.poll);
if (pollData.is_closed) this.closeConfirmed = true;
// @ts-expect-error type mismatch
this.state.partialNext({ ...pollData, lastActivityAt: event.created_at });
this.state.partialNext({
...pollData,
// Server-owned translations, which `extractPollData` (an update request) leaves out. Copied
// even when absent: the event carries the whole poll, and a change made under channel-only
// translation drops the stale ones.
description_i18n: event.poll.description_i18n,
lastActivityAt: event.created_at,
name_i18n: event.poll.name_i18n,
});
this.upsertOfflineDb();
};

Expand Down
60 changes: 60 additions & 0 deletions test/unit/poll.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,66 @@
expect(poll.data.description).to.equal(description);
});

describe('translations on poll.updated', () => {
const nameI18n = { en_text: 'XY', es_text: 'XY (es)', language: 'en' };
const descriptionI18n = { en_text: 'About', es_text: 'Acerca de', language: 'en' };

it('stores the translations of an edited question', () => {
const poll = new Poll({ client, poll: { ...pollResponse, name_i18n: nameI18n } });
const editedNameI18n = { en_text: 'XYZ', es_text: 'XYZ (es)', language: 'en' };

poll.handlePollUpdated({
type: 'poll.updated',
poll: { ...pollResponse, name: 'XYZ', name_i18n: editedNameI18n },
});

expect(poll.data.name).to.equal('XYZ');
expect(poll.data.name_i18n).to.eql(editedNameI18n);
});

it('stores a language added after the poll was sent', () => {
const poll = new Poll({ client, poll: { ...pollResponse, name_i18n: nameI18n } });
const withGerman = { ...nameI18n, de_text: 'XY (de)' };

poll.handlePollUpdated({
type: 'poll.updated',
poll: { ...pollResponse, name_i18n: withGerman },
});

expect(poll.data.name_i18n).to.eql(withGerman);
});

it('stores the translations of the description', () => {
const poll = new Poll({ client, poll: pollResponse });

poll.handlePollUpdated({
type: 'poll.updated',
poll: {
...pollResponse,
description: 'About',
description_i18n: descriptionI18n,
},
});

expect(poll.data.description_i18n).to.eql(descriptionI18n);
});

it('clears translations the event no longer carries', () => {
const poll = new Poll({
client,
poll: { ...pollResponse, description_i18n: descriptionI18n, name_i18n: nameI18n },
});

poll.handlePollUpdated({
type: 'poll.updated',
poll: { ...pollResponse, name: 'XYZ' },
});

expect(poll.data.name_i18n).to.be.undefined;
expect(poll.data.description_i18n).to.be.undefined;
});
});

it("should not update poll state when handlePollUpdated is called with other poll's event", () => {
const poll = new Poll({ client, poll: { ...pollResponse, id: 'X' } });
const description = 'Description update';
Expand Down Expand Up @@ -1653,7 +1713,7 @@
expect(poll.data.ownVotesByOptionId[optionD]).toBeUndefined();

// the removal's event is lost too, so the failed vote stays shown until the timeout
slowRequest.reject(new Error('failed'));

Check failure on line 1716 in test/unit/poll.test.js

View workflow job for this annotation

GitHub Actions / test

Unhandled error

Error: failed ❯ test/unit/poll.test.js:1716:24 This error originated in "test/unit/poll.test.js" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. The latest test that might've caused the error is "waits for vote requests still in flight before rebuilding the own votes". It might mean one of the following: - The error was thrown, while Vitest was running this test. - If the error occurred after the test had been completed, this was the last documented test before it was thrown.
await vi.advanceTimersByTimeAsync(0);
expect(poll.data.ownVotesByOptionId[optionC].id).toMatch(/^local-/);

Expand Down
15 changes: 15 additions & 0 deletions test/unit/poll_manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,21 @@ describe('PollManager', () => {
expect(spy2.calledOnce).to.be.false;
});

it('should keep the translations of poll.updated in the cached poll', () => {
const nameI18n = { de_text: 'Neuer Titel', en_text: 'New title', language: 'en' };

client.dispatchEvent({
type: 'poll.updated',
poll: {
...pollMessage1.poll,
name: 'New title',
name_i18n: nameI18n,
} as PollResponse,
});

expect(pollManager.fromState(pollId1)?.data.name_i18n).to.eql(nameI18n);
});

const eventHandlerPairs = [
['poll.closed', 'handlePollClosed'],
['poll.vote_casted', 'handleVoteCasted'],
Expand Down
Loading