mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
test: consolidate tests
This commit is contained in:
@@ -95,8 +95,8 @@ export class BlockService extends BaseService<
|
||||
block: B,
|
||||
subscriber?: Subscriber,
|
||||
) {
|
||||
if (!subscriber) {
|
||||
return block;
|
||||
if (!subscriber || !subscriber.labels) {
|
||||
return true; // No subscriber or labels to match against
|
||||
}
|
||||
|
||||
const triggerLabels = block.trigger_labels.map((l: string | Label) =>
|
||||
|
||||
@@ -207,12 +207,16 @@ describe('NlpSampleController', () => {
|
||||
const patterns: NlpValueMatchPattern[] = [
|
||||
{ entity: 'intent', match: 'value', value: 'nonexistent' },
|
||||
];
|
||||
jest.spyOn(nlpSampleService, 'findByPatternsAndPopulate');
|
||||
const result = await nlpSampleController.findPage(
|
||||
pageQuery,
|
||||
['language', 'entities'],
|
||||
{},
|
||||
patterns,
|
||||
);
|
||||
expect(nlpSampleService.findByPatternsAndPopulate).toHaveBeenCalledTimes(
|
||||
1,
|
||||
);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
@@ -220,7 +224,9 @@ describe('NlpSampleController', () => {
|
||||
|
||||
describe('count', () => {
|
||||
it('should count the nlp samples', async () => {
|
||||
jest.spyOn(nlpSampleService, 'count');
|
||||
const result = await nlpSampleController.count({});
|
||||
expect(nlpSampleService.count).toHaveBeenCalledTimes(1);
|
||||
const count = nlpSampleFixtures.length;
|
||||
expect(result).toEqual({ count });
|
||||
});
|
||||
@@ -478,7 +484,9 @@ describe('NlpSampleController', () => {
|
||||
describe('filterCount', () => {
|
||||
it('should count the nlp samples without patterns', async () => {
|
||||
const filters = { text: 'Hello' };
|
||||
jest.spyOn(nlpSampleService, 'countByPatterns');
|
||||
const result = await nlpSampleController.filterCount(filters, []);
|
||||
expect(nlpSampleService.countByPatterns).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqual({ count: 1 });
|
||||
});
|
||||
|
||||
@@ -487,7 +495,9 @@ describe('NlpSampleController', () => {
|
||||
const patterns: NlpValueMatchPattern[] = [
|
||||
{ entity: 'intent', match: 'value', value: 'greeting' },
|
||||
];
|
||||
jest.spyOn(nlpSampleService, 'countByPatterns');
|
||||
const result = await nlpSampleController.filterCount(filters, patterns);
|
||||
expect(nlpSampleService.countByPatterns).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqual({ count: 1 });
|
||||
});
|
||||
|
||||
|
||||
@@ -52,6 +52,35 @@ export class NlpSampleRepository extends BaseRepository<
|
||||
super(model, NlpSample, NLP_SAMPLE_POPULATE, NlpSampleFull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the filter query.
|
||||
*
|
||||
* @param filters - The filters to normalize.
|
||||
* @returns The normalized filters.
|
||||
*/
|
||||
private normalizeFilters(
|
||||
filters: TFilterQuery<NlpSample>,
|
||||
): TFilterQuery<NlpSample> {
|
||||
if (filters?.$and) {
|
||||
return {
|
||||
...filters,
|
||||
$and: filters.$and.map((condition) => {
|
||||
// @todo: think of a better way to handle language to objectId conversion
|
||||
// This is a workaround for the fact that language is stored as an ObjectId
|
||||
// in the database, but we want to filter by its string representation.
|
||||
if ('language' in condition && condition.language) {
|
||||
return {
|
||||
...condition,
|
||||
language: new Types.ObjectId(condition.language as string),
|
||||
};
|
||||
}
|
||||
return condition;
|
||||
}),
|
||||
};
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the aggregation stages that restrict a *nlpSampleEntities* collection
|
||||
* to links which:
|
||||
@@ -77,27 +106,12 @@ export class NlpSampleRepository extends BaseRepository<
|
||||
value: new Types.ObjectId(id),
|
||||
}));
|
||||
|
||||
const normalizedFilters = this.normalizeFilters(filters);
|
||||
|
||||
return [
|
||||
{
|
||||
$match: {
|
||||
// @todo: think of a better way to handle language to objectId conversion
|
||||
// This is a workaround for the fact that language is stored as an ObjectId
|
||||
// in the database, but we want to filter by its string representation.
|
||||
...filters,
|
||||
...(filters?.$and
|
||||
? {
|
||||
$and: filters.$and?.map((condition) => {
|
||||
if ('language' in condition && condition.language) {
|
||||
return {
|
||||
language: new Types.ObjectId(
|
||||
condition.language as string,
|
||||
),
|
||||
};
|
||||
}
|
||||
return condition;
|
||||
}),
|
||||
}
|
||||
: {}),
|
||||
...normalizedFilters,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ describe('NlpSampleService', () => {
|
||||
let nlpEntityService: NlpEntityService;
|
||||
let nlpSampleService: NlpSampleService;
|
||||
let nlpSampleEntityService: NlpSampleEntityService;
|
||||
let nlpValueService: NlpValueService;
|
||||
let languageService: LanguageService;
|
||||
let nlpSampleEntityRepository: NlpSampleEntityRepository;
|
||||
let nlpSampleRepository: NlpSampleRepository;
|
||||
@@ -100,6 +101,7 @@ describe('NlpSampleService', () => {
|
||||
nlpEntityService,
|
||||
nlpSampleService,
|
||||
nlpSampleEntityService,
|
||||
nlpValueService,
|
||||
nlpSampleRepository,
|
||||
nlpSampleEntityRepository,
|
||||
nlpSampleEntityRepository,
|
||||
@@ -109,6 +111,7 @@ describe('NlpSampleService', () => {
|
||||
NlpEntityService,
|
||||
NlpSampleService,
|
||||
NlpSampleEntityService,
|
||||
NlpValueService,
|
||||
NlpSampleRepository,
|
||||
NlpSampleEntityRepository,
|
||||
NlpSampleEntityRepository,
|
||||
@@ -364,17 +367,29 @@ describe('NlpSampleService', () => {
|
||||
});
|
||||
|
||||
describe('findByPatterns', () => {
|
||||
it('should return samples without providing patterns', async () => {
|
||||
const result = await nlpSampleService.findByPatterns(
|
||||
{ filters: {}, patterns: [] },
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should return samples matching the given patterns', async () => {
|
||||
// Assume pattern: entity 'intent', value 'greeting'
|
||||
const patterns: NlpValueMatchPattern[] = [
|
||||
{ entity: 'intent', match: 'value', value: 'greeting' },
|
||||
];
|
||||
|
||||
jest.spyOn(nlpSampleRepository, 'findByEntities');
|
||||
jest.spyOn(nlpValueService, 'findByPatterns');
|
||||
const result = await nlpSampleService.findByPatterns(
|
||||
{ filters: {}, patterns },
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(nlpSampleRepository.findByEntities).toHaveBeenCalled();
|
||||
expect(nlpValueService.findByPatterns).toHaveBeenCalled();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result[0].text).toBe('Hello');
|
||||
});
|
||||
@@ -384,11 +399,15 @@ describe('NlpSampleService', () => {
|
||||
{ entity: 'intent', match: 'value', value: 'nonexistent' },
|
||||
];
|
||||
|
||||
jest.spyOn(nlpSampleRepository, 'findByEntities');
|
||||
jest.spyOn(nlpValueService, 'findByPatterns');
|
||||
const result = await nlpSampleService.findByPatterns(
|
||||
{ filters: {}, patterns },
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(nlpSampleRepository.findByEntities).not.toHaveBeenCalled();
|
||||
expect(nlpValueService.findByPatterns).toHaveBeenCalled();
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
@@ -434,6 +453,19 @@ describe('NlpSampleService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return populated NlpSampleFull without providing patterns', async () => {
|
||||
const result = await nlpSampleService.findByPatternsAndPopulate(
|
||||
{ filters: { text: /Hello/gi }, patterns: [] },
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toBeInstanceOf(NlpSampleFull);
|
||||
expect(result[0].entities).toBeDefined();
|
||||
expect(Array.isArray(result[0].entities)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return an empty array if no samples match the patterns', async () => {
|
||||
const patterns: NlpValueMatchPattern[] = [
|
||||
{ entity: 'intent', match: 'value', value: 'nonexistent' },
|
||||
@@ -474,15 +506,33 @@ describe('NlpSampleService', () => {
|
||||
{ entity: 'intent', match: 'value', value: 'greeting' },
|
||||
];
|
||||
|
||||
jest.spyOn(nlpSampleRepository, 'countByEntities');
|
||||
jest.spyOn(nlpValueService, 'findByPatterns');
|
||||
const count = await nlpSampleService.countByPatterns({
|
||||
filters: {},
|
||||
patterns,
|
||||
});
|
||||
|
||||
expect(nlpSampleRepository.countByEntities).toHaveBeenCalled();
|
||||
expect(nlpValueService.findByPatterns).toHaveBeenCalled();
|
||||
expect(typeof count).toBe('number');
|
||||
expect(count).toBe(2);
|
||||
});
|
||||
|
||||
it('should return the correct count without providing patterns', async () => {
|
||||
jest.spyOn(nlpSampleRepository, 'findByEntities');
|
||||
jest.spyOn(nlpValueService, 'findByPatterns');
|
||||
const count = await nlpSampleService.countByPatterns({
|
||||
filters: {},
|
||||
patterns: [],
|
||||
});
|
||||
|
||||
expect(nlpSampleRepository.findByEntities).not.toHaveBeenCalled();
|
||||
expect(nlpValueService.findByPatterns).not.toHaveBeenCalled();
|
||||
expect(typeof count).toBe('number');
|
||||
expect(count).toBeGreaterThan(2);
|
||||
});
|
||||
|
||||
it('should return 0 if no samples match the patterns', async () => {
|
||||
const patterns: NlpValueMatchPattern[] = [
|
||||
{ entity: 'intent', match: 'value', value: 'nonexistent' },
|
||||
|
||||
@@ -104,7 +104,7 @@ export class NlpSampleService extends BaseService<
|
||||
* Same as `findByPatterns`, but also populates all relations declared
|
||||
* in the repository (`populatePaths`).
|
||||
*
|
||||
* @param criteras `{ filters, patterns }`
|
||||
* @param criteria `{ filters, patterns }`
|
||||
* @param page Optional paging / sorting descriptor.
|
||||
* @param projection Optional Mongo projection.
|
||||
* @returns Promise resolving to the populated samples.
|
||||
|
||||
@@ -378,7 +378,7 @@ export abstract class BaseRepository<
|
||||
criteria: string | TFilterQuery<T>,
|
||||
options?: ClassTransformOptions,
|
||||
projection?: ProjectionType<T>,
|
||||
) {
|
||||
): Promise<T | null> {
|
||||
if (!criteria) {
|
||||
// @TODO : Issue a warning ?
|
||||
return null;
|
||||
@@ -768,7 +768,7 @@ export abstract class BaseRepository<
|
||||
* @param filter Mongo filter selecting the documents to update.
|
||||
* @param dto Update payload.
|
||||
* @param options `{ shouldFlatten?: boolean }`.
|
||||
* @returns MongoDB `UpdateWriteOpResult` describing the operation outcome.
|
||||
* @returns Promise that resolves a MongoDB `UpdateWriteOpResult` describing the operation outcome.
|
||||
*/
|
||||
async updateMany<D extends Partial<U>>(
|
||||
filter: TFilterQuery<T>,
|
||||
|
||||
Reference in New Issue
Block a user