Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Code scanning - action / CodeQL-Build (push) Failing after 2s
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
192 lines
4.7 KiB
TypeScript
192 lines
4.7 KiB
TypeScript
import type { IOmnichannelRoom } from '@rocket.chat/core-typings';
|
|
|
|
import { UpdaterImpl } from './updater';
|
|
|
|
test('updater typings', () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
t: 'l';
|
|
a: {
|
|
b: string;
|
|
};
|
|
c?: number;
|
|
|
|
d?: {
|
|
e: string;
|
|
};
|
|
e: string[];
|
|
}>();
|
|
|
|
// @ts-expect-error: it should not allow any string to `t` only `l` is allowed
|
|
updater.set('t', 'a');
|
|
// `l` is allowed
|
|
updater.set('t', 'l');
|
|
|
|
// `a` is { b: string }
|
|
updater.set('a', { b: 'test' });
|
|
updater.set('a.b', 'test');
|
|
// @ts-expect-error: it should not allow strings to `a`, a is an object containing `b: string`
|
|
updater.set('a', 'b');
|
|
// @ts-expect-error: `a` is not optional so unset is not allowed
|
|
updater.unset('a');
|
|
// @ts-expect-error: strings cannot be incremented
|
|
updater.inc('a', 1);
|
|
|
|
// `c` is number but it should be optional, so unset is allowed
|
|
updater.unset('c');
|
|
updater.set('c', 1);
|
|
// @ts-expect-error: `c` is a number
|
|
updater.set('c', 'b');
|
|
// inc is allowed for numbers
|
|
updater.inc('c', 1);
|
|
|
|
// `d` is { e: string } but it should be optional, so unset is allowed
|
|
updater.unset('d');
|
|
updater.set('d', { e: 'a' });
|
|
// @ts-expect-error: `d` is an object
|
|
updater.set('d', 'a');
|
|
|
|
// @ts-expect-error: it should not allow numbers, since e is a string
|
|
updater.addToSet('e', 1);
|
|
// @ts-expect-error: it should not allow strings, since a is an object
|
|
updater.addToSet('a', 'b');
|
|
|
|
updater.addToSet('e', 'a');
|
|
// @ts-expect-error: it should not allow `njame` its not specified in the model
|
|
updater.set('njame', 1);
|
|
|
|
// `d` is { e: string } and also it should be optional, so unset is allowed
|
|
updater.unset('d.e');
|
|
// @ts-expect-error: `d` is an object cannot be incremented
|
|
updater.inc('d', 1);
|
|
|
|
// `activity` is a string
|
|
const omnichannel = new UpdaterImpl<IOmnichannelRoom>();
|
|
omnichannel.addToSet('v.activity', 'asd');
|
|
// @ts-expect-error: it should not allow numbers, since activity is a string
|
|
omnichannel.addToSet('v.activity', 1);
|
|
// @ts-expect-error: it should not allow objects, since activity is a string
|
|
omnichannel.addToSet('v.activity', {
|
|
asdas: 1,
|
|
});
|
|
// @ts-expect-error: it should not allow sub properties, since activity is a string
|
|
omnichannel.addToSet('v.activity.asd', {
|
|
asdas: 1,
|
|
});
|
|
});
|
|
|
|
test('updater supports nested paths up to 3 levels deep', () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
level1: {
|
|
level2: {
|
|
level3: string;
|
|
};
|
|
};
|
|
}>();
|
|
|
|
// 1-level deep path
|
|
updater.set('level1', { level2: { level3: 'test' } });
|
|
// 2-level deep path
|
|
updater.set('level1.level2', { level3: 'test' });
|
|
// 3-level deep path
|
|
updater.set('level1.level2.level3', 'test');
|
|
});
|
|
|
|
test('updater validates keys on real schemas with nested paths', () => {
|
|
const updater = new UpdaterImpl<IOmnichannelRoom>();
|
|
|
|
// valid 1-level paths
|
|
updater.set('fname', 'test');
|
|
// valid 2-level paths
|
|
updater.set('responseBy.lastMessageTs', new Date());
|
|
updater.set('v.activity', ['period1']);
|
|
// valid 3-level paths
|
|
updater.inc('metrics.response.total', 1);
|
|
updater.set('metrics.response.avg', 42);
|
|
updater.set('metrics.reaction.ft', 100);
|
|
|
|
// @ts-expect-error: non-existent top-level key
|
|
updater.set('nonExistentField', 'hello');
|
|
// @ts-expect-error: non-existent nested key
|
|
updater.set('responseBy.nonExistent', new Date());
|
|
// @ts-expect-error: 'fname' is a string, not a number — inc should reject it
|
|
updater.inc('fname', 1);
|
|
});
|
|
|
|
test('updater $set operations', async () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
t: 'l';
|
|
a: {
|
|
b: string;
|
|
};
|
|
c?: number;
|
|
}>();
|
|
|
|
updater.set('a', {
|
|
b: 'set',
|
|
});
|
|
|
|
expect(updater.getUpdateFilter()).toEqual({ $set: { a: { b: 'set' } } });
|
|
});
|
|
|
|
test('updater $unset operations', async () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
t: 'l';
|
|
a: {
|
|
b: string;
|
|
};
|
|
c?: number;
|
|
}>();
|
|
updater.unset('c');
|
|
expect(updater.getUpdateFilter()).toEqual({ $unset: { c: 1 } });
|
|
});
|
|
|
|
test('updater inc multiple operations', async () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
t: 'l';
|
|
a: {
|
|
b: string;
|
|
};
|
|
c?: number;
|
|
}>();
|
|
|
|
updater.inc('c', 1);
|
|
updater.inc('c', 1);
|
|
|
|
expect(updater.getUpdateFilter()).toEqual({ $inc: { c: 2 } });
|
|
});
|
|
|
|
test('it should add items to array', async () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
a: string[];
|
|
}>();
|
|
|
|
updater.addToSet('a', 'b');
|
|
updater.addToSet('a', 'c');
|
|
|
|
expect(updater.getUpdateFilter()).toEqual({ $addToSet: { a: { $each: ['b', 'c'] } } });
|
|
});
|
|
|
|
test('it should getUpdateFilter only once', async () => {
|
|
const updater = new UpdaterImpl<{
|
|
_id: string;
|
|
t: 'l';
|
|
a: {
|
|
b: string;
|
|
};
|
|
c?: number;
|
|
}>();
|
|
|
|
updater.set('a', {
|
|
b: 'set',
|
|
});
|
|
|
|
expect(updater.getUpdateFilter()).toEqual({ $set: { a: { b: 'set' } } });
|
|
expect(() => updater.getUpdateFilter()).toThrow();
|
|
});
|