Skip to content
Snippets Groups Projects
Unverified Commit e203c404 authored by Guilherme Gazzo's avatar Guilherme Gazzo Committed by GitHub
Browse files

fix: proxified model props were missing context before attribution (#32056)

parent 9d23d406
No related branches found
No related tags found
No related merge requests found
---
"@rocket.chat/models": patch
---
Fix proxified model props were missing context before attribution
---
"@rocket.chat/meteor": patch
---
Fix error during migration 304. Throwing `Cannot read property 'finally' of undefined` error.
......@@ -29,6 +29,7 @@
"oauthapps",
"omnichannel",
"photoswipe",
"proxify",
"searchbox",
"tmid",
"tshow"
......
export default {
preset: 'ts-jest',
errorOnDeprecated: true,
testEnvironment: 'jsdom',
modulePathIgnorePatterns: ['<rootDir>/dist/'],
testMatch: ['**/**.spec.ts'],
transform: {
'^.+\\.(t|j)sx?$': '@swc/jest',
},
moduleNameMapper: {
'\\.css$': 'identity-obj-proxy',
},
collectCoverage: true,
};
......@@ -7,7 +7,9 @@
"eslint": "~8.45.0",
"jest": "~29.6.4",
"ts-jest": "~29.1.1",
"typescript": "~5.3.3"
"typescript": "~5.3.3",
"@swc/core": "^1.3.95",
"@swc/jest": "^0.2.29"
},
"dependencies": {
"@rocket.chat/model-typings": "workspace:^"
......@@ -17,7 +19,9 @@
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix",
"test": "jest",
"dev": "tsc --watch --preserveWatchOutput -p tsconfig.json",
"build": "rm -rf dist && tsc -p tsconfig.json"
"build": "rm -rf dist && tsc -p tsconfig.json",
"unit": "jest",
"testunit": "jest"
},
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
......
import { proxify, registerModel } from './proxify';
type MockedModel = {
method: () => MockedModel;
};
describe('non lazy proxify', () => {
it('should keep this inside functions', () => {
const collectionMocked = proxify('collection') as MockedModel;
const collection = {
method() {
return this;
},
};
registerModel<any>('collection', collection);
expect(collectionMocked.method()).toBe(collection);
});
it('should throw an error if the model is not found', () => {
const collectionMocked = proxify('collection-not-found') as MockedModel;
expect(() => collectionMocked.method()).toThrowError('Model collection-not-found not found');
});
it('should return a proxified property', () => {
const collectionMocked = proxify('collection-prop') as {
prop: string;
};
const collection = {
prop: 'value',
};
registerModel<any>('collection-prop', collection);
expect(collectionMocked.prop).toBe('value');
});
it('should throw an error if trying to set a property from the proxified object', () => {
const collectionMocked = proxify('collection-prop') as {
prop: string;
};
const collection = {
prop: 'value',
};
registerModel<any>('collection-prop', collection);
expect(() => {
collectionMocked.prop = 'new value';
}).toThrowError('Models accessed via proxify are read-only, use the model instance directly to modify it.');
});
});
describe('lazy proxify', () => {
it('should keep this inside functions', () => {
const collectionMocked = proxify('collection-lazy') as MockedModel;
const collection = {
method() {
return this;
},
};
registerModel<any>('collection-lazy', () => collection);
expect(collectionMocked.method()).toBe(collection);
});
it('should throw an error if the model is not found', () => {
const collectionMocked = proxify('collection-not-found') as MockedModel;
expect(() => collectionMocked.method()).toThrowError('Model collection-not-found not found');
});
it('should return a proxified property', () => {
const collectionMocked = proxify('collection-prop') as {
prop: string;
};
const collection = {
prop: 'value',
};
registerModel<any>('collection-prop', () => collection);
expect(collectionMocked.prop).toBe('value');
});
it('should throw an error if trying to set a property from the proxified object', () => {
const collectionMocked = proxify('collection-prop') as {
prop: string;
};
const collection = {
prop: 'value',
};
registerModel<any>('collection-prop', () => collection);
expect(() => {
collectionMocked.prop = 'new value';
}).toThrowError('Models accessed via proxify are read-only, use the model instance directly to modify it.');
});
});
......@@ -5,7 +5,7 @@ const models = new Map<string, IBaseModel<any>>();
function handler<T extends object>(namespace: string): ProxyHandler<T> {
return {
get: (_target: T, prop: keyof IBaseModel<any>): any => {
get: (_target: T, nameProp: keyof IBaseModel<any>): any => {
if (!models.has(namespace) && lazyModels.has(namespace)) {
const getModel = lazyModels.get(namespace);
if (getModel) {
......@@ -19,7 +19,21 @@ function handler<T extends object>(namespace: string): ProxyHandler<T> {
throw new Error(`Model ${namespace} not found`);
}
return model[prop];
const prop = model[nameProp];
if (typeof prop === 'function') {
return prop.bind(model);
}
return prop;
},
set() {
if (process.env.NODE_ENV !== 'production') {
throw new Error('Models accessed via proxify are read-only, use the model instance directly to modify it.');
}
/* istanbul ignore next */
return true;
},
};
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment