blob: 0bb02529cc74af6a244c664e768d75afa9448d11 [file]
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { afterEach, describe, expect, it, vi } from 'vitest';
import type { MessageReceiveDataTypeMap } from './interfaces/message-data-type-map.interface';
import { OP } from './interfaces/message-operator.interface';
import type { WebSocketMessage } from './interfaces/websocket-message.interface';
import { Message } from './message';
const asReceivedMessage = (message: unknown): WebSocketMessage<MessageReceiveDataTypeMap> =>
message as WebSocketMessage<MessageReceiveDataTypeMap>;
afterEach(() => {
vi.restoreAllMocks();
});
describe('Message.receive', () => {
it('passes a non-removal job update with noteName', () => {
const message = new Message();
const listener = vi.fn();
const data = {
noteRunningJobs: {
jobs: [
{
noteId: 'note-1',
noteName: 'Test Note',
isRemoved: false
}
]
}
};
message.receive(OP.LIST_UPDATE_NOTE_JOBS).subscribe(listener);
message.shortCircuit(
asReceivedMessage({
op: OP.LIST_UPDATE_NOTE_JOBS,
data
})
);
expect(listener).toHaveBeenCalledWith(data);
});
it('passes a partial removal payload without noteName', () => {
const message = new Message();
const listener = vi.fn();
const data = {
noteRunningJobs: {
jobs: [
{
noteId: 'note-1',
isRemoved: true
}
]
}
};
message.receive(OP.LIST_UPDATE_NOTE_JOBS).subscribe(listener);
message.shortCircuit(
asReceivedMessage({
op: OP.LIST_UPDATE_NOTE_JOBS,
data
})
);
expect(listener).toHaveBeenCalledWith(data);
});
it('filters a non-removal job update without noteName and warns with the OP only', () => {
const message = new Message();
const listener = vi.fn();
const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {});
message.receive(OP.LIST_UPDATE_NOTE_JOBS).subscribe(listener);
message.shortCircuit(
asReceivedMessage({
op: OP.LIST_UPDATE_NOTE_JOBS,
data: {
noteRunningJobs: {
jobs: [
{
noteId: 'note-1',
isRemoved: false
}
]
}
}
})
);
expect(listener).not.toHaveBeenCalled();
expect(consoleWarn).toHaveBeenCalledTimes(1);
expect(consoleWarn).toHaveBeenCalledWith(
`Dropped WebSocket OP ${String(OP.LIST_UPDATE_NOTE_JOBS)}: payload failed validation`
);
});
it('filters a payload without a jobs array', () => {
const message = new Message();
const listener = vi.fn();
vi.spyOn(console, 'warn').mockImplementation(() => {});
message.receive(OP.LIST_UPDATE_NOTE_JOBS).subscribe(listener);
message.shortCircuit(
asReceivedMessage({
op: OP.LIST_UPDATE_NOTE_JOBS,
data: {
noteRunningJobs: {}
}
})
);
expect(listener).not.toHaveBeenCalled();
});
it('keeps existing behavior for an OP without a guard', () => {
const message = new Message();
const listener = vi.fn();
const data = {};
message.receive(OP.NOTE).subscribe(listener);
message.shortCircuit(
asReceivedMessage({
op: OP.NOTE,
data
})
);
expect(listener).toHaveBeenCalledWith(data);
});
});