Skip to content
This repository has been archived by the owner on Dec 6, 2024. It is now read-only.

Commit

Permalink
fix: enum rule for array element (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
batrdn authored Mar 2, 2024
1 parent fb026da commit 2dcdfe5
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 20 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ jobs:
node-version: 20
registry-url: https://registry.npmjs.org/
- name: Install dependencies
run: npm ci
run: npm install
- name: Format
run: |
UNFORMATTED_FILES=$(npm run format:check)
UNFORMATTED_FILES=$(npx nx format:check)
if [ -n "$UNFORMATTED_FILES" ]; then
echo "Unformatted files found:"
echo "$UNFORMATTED_FILES"
exit 1
fi
- name: Lint
run: npm run lint
run: npx nx affected -t lint
- name: Build
run: npm run build
run: npx nx affected -t build
- name: Test
run: npm run test
run: npx nx affected -t test
2 changes: 1 addition & 1 deletion nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"extends": "nx/presets/npm.json",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"affected": {
"defaultBase": "main"
"defaultBase": "origin/main"
},
"release": {
"projects": ["@mocking-bird/core", "@mocking-bird/mongoose"],
Expand Down
20 changes: 11 additions & 9 deletions packages/core/src/core-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export abstract class CoreFixture<T> {
protected constructor(
pathfinder: CorePathFinder,
typeMapper: CoreTypeMapper,
validator?: Validator
validator?: Validator,
) {
this.pathfinder = pathfinder;
this.typeMapper = typeMapper;
Expand All @@ -53,7 +53,7 @@ export abstract class CoreFixture<T> {
abstract bulkGenerate(
size: number,
overrideValues?: Record<FieldPath, Value>,
options?: FixtureOptions
options?: FixtureOptions,
): T[];

/**
Expand All @@ -66,7 +66,7 @@ export abstract class CoreFixture<T> {
*/
abstract generate(
overrideValues?: Record<FieldPath, Value>,
options?: FixtureOptions
options?: FixtureOptions,
): T;

/**
Expand All @@ -91,7 +91,7 @@ export abstract class CoreFixture<T> {
fieldName: string,
type: NonArrayFieldType,
rule: Rule | undefined,
isAccurate = true
isAccurate = true,
): Value {
return this.fakerApi.generate(fieldName, type, rule, isAccurate);
}
Expand All @@ -106,7 +106,8 @@ export abstract class CoreFixture<T> {
*
* @param fieldName The name of the field for which the value should be generated.
* @param type The non array type of the field, i.e., only the based types.
* @param rule The rule to be used to generate the value.
* @param size The size of the array to be generated.
* @param rule The rule to use for the array element.
* @param isAccurate If set to `true`, the value will be generated with the highest possible accuracy.
*
* @returns An array of mock values based on the given field name and type.
Expand All @@ -116,12 +117,13 @@ export abstract class CoreFixture<T> {
protected generateArrayValue(
fieldName: string,
type: NonArrayFieldType,
size: number | undefined,
rule: Rule | undefined,
isAccurate = true
isAccurate = true,
): Value[] {
if (rule?.size) {
return Array.from({ length: rule.size }, () =>
this.fakerApi.generate(fieldName, type, rule, isAccurate)
if (size) {
return Array.from({ length: size }, () =>
this.fakerApi.generate(fieldName, type, rule, isAccurate),
);
}

Expand Down
1 change: 1 addition & 0 deletions packages/mongoose/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export default {
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/packages/mongoose',
testTimeout: 30000,
};
9 changes: 7 additions & 2 deletions packages/mongoose/src/mongoose-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,17 @@ export class MongooseFixture<T> extends CoreFixture<T> {
if (type === FieldType.ARRAY) {
// caster is the schema type of the array elements, from which we can get the array type, e.g., String, Number, etc.
const { caster } = schemaType as Schema.Types.Array;

return caster?.instance
? this.generateArrayValue(
fieldName,
this.typeMapper.getArrayType(caster.instance),
combinedRule,
combinedRule?.size,
/**
* The parsed rule here is the rule for the array elements.
* @example
* const schema = new Schema({ values: [type: String, enum: ['A', 'B', 'C']] });
*/
this.mongooseValidator.parseValidators(caster.validators),
isAccurate,
)
: undefined;
Expand Down
4 changes: 3 additions & 1 deletion packages/mongoose/src/mongoose-type-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ export class MongooseTypeMapper extends CoreTypeMapper {
return FieldType.UUID;
case 'bigint':
return FieldType.BIGINT;
case 'mixed':
case 'map':
// TODO: support map type
throw new Error('Map type is not supported yet.');
case 'mixed':
case 'schema':
return FieldType.OBJECT;
default:
Expand Down
16 changes: 16 additions & 0 deletions packages/mongoose/test/models/enum-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import mongoose from 'mongoose';

export enum Authors {
DOSTOEVSKY = 'DOSTOEVSKY',
NIEZTSHE = 'NIEZTSHE',
KAFKA = 'KAFKA',
TOLSTOY = 'TOLSTOY',
HEMINGWAY = 'HEMINGWAY',
}

export const AuthorSchema = new mongoose.Schema(
{
authors: [{ type: String, enum: Authors }],
},
{ _id: false, timestamps: false },
);
2 changes: 2 additions & 0 deletions packages/mongoose/test/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './basic-model';
export * from './nested-model';
export * from './enum-schema';
export * from './map-type-model';
60 changes: 60 additions & 0 deletions packages/mongoose/test/models/map-type-model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { model, Schema } from 'mongoose';

export type UserAddress = Record<
string,
{
street: string;
buildingNo: number;
}[]
>;

export type UserInfo = Record<
string,
{
name: string;
age: number;
address: UserAddress;
}[]
>;

export interface IMapDocument {
userAddress: UserAddress[];
userInfo: UserInfo;
basicInfo: Record<string, string>;
}

export const MapDocumentSchema = new Schema({
userAddress: {
type: Schema.Types.Map,
of: [
new Schema({
street: { type: String },
buildingNo: { type: Number },
}),
],
},
userInfo: {
type: Schema.Types.Map,
of: new Schema({
name: { type: String },
age: { type: Number },
address: {
type: Schema.Types.Map,
of: new Schema({
street: { type: String },
buildingNo: { type: Number },
}),
},
}),
},
basicInfo: {
type: Schema.Types.Map,
of: String,
},
});

export const MapModel = model<IMapDocument>(
'MapDocument',
MapDocumentSchema,
'MapDocuments',
);
10 changes: 9 additions & 1 deletion packages/mongoose/test/mongodb-integration.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MongoDBContainer } from '@testcontainers/mongodb';
import * as mongoose from 'mongoose';
import { MongooseFixture } from '../src';
import { BasicModel, NestedModel } from './models';
import { BasicModel, MapModel, NestedModel } from './models';

describe('MongoDB Integration Test', () => {
beforeAll(async () => {
Expand Down Expand Up @@ -50,4 +50,12 @@ describe('MongoDB Integration Test', () => {
const error = nestedDoc.validateSync();
expect(error).toBeUndefined();
});

// TODO - Fix this test
it.skip('should save a document with a complex map type', async () => {
const fixture = new MongooseFixture(MapModel);
const mockData = fixture.generate();

expect(await MapModel.create(mockData)).not.toThrow();
});
});
18 changes: 17 additions & 1 deletion packages/mongoose/test/mongoose.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { MongooseFixture } from '../src';
import { NestedModel, BasicModel, IBasicDocument } from './models';
import {
NestedModel,
BasicModel,
IBasicDocument,
Authors,
AuthorSchema,
} from './models';

describe('Mocking Bird - Mongoose', () => {
const assertRequiredFields = (mock: IBasicDocument) => {
Expand Down Expand Up @@ -438,6 +444,16 @@ describe('Mocking Bird - Mongoose', () => {
});
});

describe('Schema with enums', () => {
it('should generate a mock with the correct enum value', () => {
const fixture = new MongooseFixture(AuthorSchema);
const { authors } = fixture.generate();

expect(authors).toHaveLength(1);
expect(Object.values(Authors).includes(authors[0])).toBe(true);
});
});

describe('Global options', () => {
beforeEach(() => {
MongooseFixture.setGlobalOptions({
Expand Down

0 comments on commit 2dcdfe5

Please sign in to comment.