Skip to content

Commit

Permalink
Fix reading state events without a specific state key (#81)
Browse files Browse the repository at this point in the history
And add some tests for reading state events while we're at it.

Regressed by a8fc2b9
  • Loading branch information
robintown authored Mar 20, 2023
1 parent cf6bd7f commit e0f25a0
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/ClientWidgetApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export class ClientWidgetApi extends EventEmitter {
return this.allowedEvents.some(e => e.matchesAsRoomEvent(EventDirection.Receive, eventType, msgtype));
}

public canReceiveStateEvent(eventType: string, stateKey: string): boolean {
public canReceiveStateEvent(eventType: string, stateKey: string | null): boolean {
return this.allowedEvents.some(e => e.matchesAsStateEvent(EventDirection.Receive, eventType, stateKey));
}

Expand Down Expand Up @@ -401,7 +401,7 @@ export class ClientWidgetApi extends EventEmitter {
let events: Promise<IRoomEvent[]> = Promise.resolve([]);
if (request.data.state_key !== undefined) {
const stateKey = request.data.state_key === true ? undefined : request.data.state_key.toString();
if (!stateKey || !this.canReceiveStateEvent(request.data.type, stateKey)) {
if (!this.canReceiveStateEvent(request.data.type, stateKey ?? null)) {
return this.transport.reply<IWidgetApiErrorResponseData>(request, {
error: {message: "Cannot read state events of this type"},
});
Expand Down
2 changes: 1 addition & 1 deletion src/models/WidgetEventCapability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class WidgetEventCapability {
) {
}

public matchesAsStateEvent(direction: EventDirection, eventType: string, stateKey: string): boolean {
public matchesAsStateEvent(direction: EventDirection, eventType: string, stateKey: string | null): boolean {
if (this.kind !== EventKind.State) return false; // not a state event
if (this.direction !== direction) return false; // direction mismatch
if (this.eventType !== eventType) return false; // event type mismatch
Expand Down
123 changes: 123 additions & 0 deletions test/ClientWidgetApi-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { WidgetApiFromWidgetAction } from '../src/interfaces/WidgetApiAction';
import { WidgetApiDirection } from '../src/interfaces/WidgetApiDirection';
import { Widget } from '../src/models/Widget';
import { PostmessageTransport } from '../src/transport/PostmessageTransport';
import { IReadEventFromWidgetActionRequest } from '../src';

jest.mock('../src/transport/PostmessageTransport')

Expand Down Expand Up @@ -74,6 +75,7 @@ describe('ClientWidgetApi', () => {
document.body.appendChild(iframe);

driver = {
readStateEvents: jest.fn(),
readEventRelations: jest.fn(),
validateCapabilities: jest.fn(),
searchUserDirectory: jest.fn(),
Expand Down Expand Up @@ -111,6 +113,127 @@ describe('ClientWidgetApi', () => {
expect(clientWidgetApi.hasCapability('m.sticker')).toBe(false);
});

describe('org.matrix.msc2876.read_events action', () => {
it('reads state events with any state key', async () => {
driver.readStateEvents.mockResolvedValue([
createRoomEvent({ type: 'net.example.test', state_key: 'A' }),
createRoomEvent({ type: 'net.example.test', state_key: 'B' }),
])

const event: IReadEventFromWidgetActionRequest = {
api: WidgetApiDirection.FromWidget,
widgetId: 'test',
requestId: '0',
action: WidgetApiFromWidgetAction.MSC2876ReadEvents,
data: {
type: 'net.example.test',
state_key: true,
},
};

await loadIframe(['org.matrix.msc2762.receive.state_event:net.example.test']);

emitEvent(new CustomEvent('', { detail: event }));

await waitFor(() => {
expect(transport.reply).toBeCalledWith(event, {
events: [
createRoomEvent({ type: 'net.example.test', state_key: 'A' }),
createRoomEvent({ type: 'net.example.test', state_key: 'B' }),
],
});
});

expect(driver.readStateEvents).toBeCalledWith(
'net.example.test', undefined, 0, null,
)
});

it('fails to read state events with any state key', async () => {
const event: IReadEventFromWidgetActionRequest = {
api: WidgetApiDirection.FromWidget,
widgetId: 'test',
requestId: '0',
action: WidgetApiFromWidgetAction.MSC2876ReadEvents,
data: {
type: 'net.example.test',
state_key: true,
},
};

await loadIframe([]); // Without the required capability

emitEvent(new CustomEvent('', { detail: event }));

await waitFor(() => {
expect(transport.reply).toBeCalledWith(event, {
error: { message: expect.any(String) },
});
});

expect(driver.readStateEvents).not.toBeCalled()
});

it('reads state events with a specific state key', async () => {
driver.readStateEvents.mockResolvedValue([
createRoomEvent({ type: 'net.example.test', state_key: 'B' }),
])

const event: IReadEventFromWidgetActionRequest = {
api: WidgetApiDirection.FromWidget,
widgetId: 'test',
requestId: '0',
action: WidgetApiFromWidgetAction.MSC2876ReadEvents,
data: {
type: 'net.example.test',
state_key: 'B',
},
};

await loadIframe(['org.matrix.msc2762.receive.state_event:net.example.test#B']);

emitEvent(new CustomEvent('', { detail: event }));

await waitFor(() => {
expect(transport.reply).toBeCalledWith(event, {
events: [
createRoomEvent({ type: 'net.example.test', state_key: 'B' }),
],
});
});

expect(driver.readStateEvents).toBeCalledWith(
'net.example.test', 'B', 0, null,
)
});

it('fails to read state events with a specific state key', async () => {
const event: IReadEventFromWidgetActionRequest = {
api: WidgetApiDirection.FromWidget,
widgetId: 'test',
requestId: '0',
action: WidgetApiFromWidgetAction.MSC2876ReadEvents,
data: {
type: 'net.example.test',
state_key: 'B',
},
};

// Request the capability for the wrong state key
await loadIframe(['org.matrix.msc2762.receive.state_event:net.example.test#A']);

emitEvent(new CustomEvent('', { detail: event }));

await waitFor(() => {
expect(transport.reply).toBeCalledWith(event, {
error: { message: expect.any(String) },
});
});

expect(driver.readStateEvents).not.toBeCalled()
});
})

describe('org.matrix.msc3869.read_relations action', () => {
it('should present as supported api version', () => {
const event: ISupportedVersionsActionRequest = {
Expand Down

0 comments on commit e0f25a0

Please sign in to comment.