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
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