Skip to content

Commit

Permalink
Merge pull request #327 from someone635/populate-not-working-bug-origDoc
Browse files Browse the repository at this point in the history
Fix bug - populate not working - idField mapped to undefined (issue #325, maybe #296)
  • Loading branch information
icebob authored Nov 6, 2022
2 parents d6c163a + a532cc3 commit f34e6c6
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 13 deletions.
29 changes: 17 additions & 12 deletions packages/moleculer-db/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,13 +493,13 @@ module.exports = {
// Convert entity to JS object
.then(docs => docs.map(doc => this.adapter.entityToObject(doc)))

// Apply idField
.then(docs => docs.map(doc => this.adapter.afterRetrieveTransformID(doc, this.settings.idField)))
// Encode IDs
.then(docs => docs.map(doc => {
doc[this.settings.idField] = this.encodeID(doc[this.settings.idField]);
return doc;
}))
// Apply idField
.then(docs => docs.map(doc => this.adapter.afterRetrieveTransformID(doc, this.settings.idField)))
// Populate
.then(json => (ctx && params.populate) ? this.populateDocs(ctx, json, params.populate) : json)

Expand Down Expand Up @@ -844,28 +844,33 @@ module.exports = {
_get(ctx, params) {
let id = params.id;
let origDoc;
let shouldMapping = params.mapping === true;
return this.getById(id, true)
.then(doc => {
if (!doc)
return Promise.reject(new EntityNotFoundError(id));
origDoc = doc;

if (shouldMapping)
origDoc = _.isArray(doc) ? doc.map(d => _.cloneDeep(d)) : _.cloneDeep(doc);
else
origDoc = doc;

return this.transformDocuments(ctx, params, doc);
})
.then(json => {
if (_.isArray(json) && params.mapping === true) {
let res = {};
if (params.mapping !== true) return json;

let res = {};
if (_.isArray(json)) {
json.forEach((doc, i) => {
const id = this.adapter.afterRetrieveTransformID(origDoc[i], this.settings.idField)[this.settings.idField];
const id = this.encodeID(this.adapter.afterRetrieveTransformID(origDoc[i], this.settings.idField)[this.settings.idField]);
res[id] = doc;
});
return res;
} else if (_.isObject(json) && params.mapping === true) {
let res = {};
const id = this.adapter.afterRetrieveTransformID(origDoc, this.settings.idField)[this.settings.idField];
} else if (_.isObject(json)) {
const id = this.encodeID(this.adapter.afterRetrieveTransformID(origDoc, this.settings.idField)[this.settings.idField]);
res[id] = json;
return res;
}
return json;
return res;
});
},

Expand Down
199 changes: 198 additions & 1 deletion packages/moleculer-db/test/integration/idField.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe("Test CRUD methods with idField", () => {
];

it("should create a new entity", () => {
broker.call("posts.create", posts[0]).then(res => {
return broker.call("posts.create", posts[0]).then(res => {
expect(typeof res).toBe("object");
expect(res._id).toEqual(undefined);
expect(typeof res.myID).toEqual("string");
Expand All @@ -45,6 +45,7 @@ describe("Test CRUD methods with idField", () => {
});

it("should throw an error", () => {
expect.assertions(1);
return broker.call("posts.create", posts[0]).catch(err => {
expect(err).toEqual(new Error("Can't insert key 0000000, it violates the unique constraint"));
});
Expand All @@ -66,6 +67,7 @@ describe("Test CRUD methods with idField", () => {
});

it("should throw an error", () => {
expect.assertions(1);
return broker.call("posts.insert", { entities: [ posts[1], posts[2]] })
.catch(err => {
expect(err).toEqual(new Error("Can't insert key 0000001, it violates the unique constraint"));
Expand All @@ -77,6 +79,11 @@ describe("Test CRUD methods with idField", () => {
.then(res => expect(res).toEqual(posts[1]));
});

it("should return with the entity mapped by ID", () => {
return broker.call("posts.get", { id: posts[1].myID, mapping:true })
.then(res => expect(res[posts[1].myID]).toEqual(posts[1]));
});

it("should return with multiple entity by IDs", () => {
return broker.call("posts.get", { id: [posts[2].myID, posts[0].myID] })
.then(res => {
Expand All @@ -85,6 +92,14 @@ describe("Test CRUD methods with idField", () => {
});
});

it("should return with multiple entities mapped by IDs", () => {
return broker.call("posts.get", { id: [posts[2].myID, posts[0].myID], mapping: true })
.then(res => {
expect(res[posts[2].myID]).toEqual(posts[2]);
expect(res[posts[0].myID]).toEqual(posts[0]);
});
});

it("should find filtered entities (search)", () => {
return broker.call("posts.find", { search: "first" })
.then(res => {
Expand Down Expand Up @@ -169,6 +184,7 @@ describe("Test CRUD methods with idField", () => {
});

test("should throw an error", () => {
expect.assertions(1);
return broker.call("posts.insert", { entity: posts[3] })
.catch(err => {
expect(err).toEqual(new Error("Can't insert key 0000003, it violates the unique constraint"));
Expand All @@ -182,3 +198,184 @@ describe("Test CRUD methods with idField", () => {
});
});
});

describe("Test CRUD methods with idField and encoding", () => {
// Create broker
let broker = new ServiceBroker({
logger: console,
logLevel: "error"
});

// Load my service
broker.createService(DbService, Object.assign({
name: "posts",
settings: {
idField: "myID"
},
adapter: new Adapter(),
methods: {
encodeID(id) {
return "enc:" + id;
},
decodeID(id) {
return id.substring(4);
}
}
}));

beforeAll(() => {
return broker.start().delay(1000);
});

afterAll(() => {
return broker.stop();
});

const posts = [
{ title: "My first post", content: "This is the content", votes: 2 },
{ title: "Second post", content: "Waiting for the next...", votes: 5 },
{ title: "My post", content: "This is the end! Good bye!", votes: 0 },
{ title: "Final post", content: "A final good bye!", votes: 123 }
];

it("should create a new entity", () => {
return broker.call("posts.create", posts[0]).then(res => {
expect(typeof res).toBe("object");
expect(res._id).toEqual(undefined);
expect(typeof res.myID).toEqual("string");
posts[0].myID = res.myID;
});
});

it("should create multiple entities", () => {
return broker.call("posts.insert", { entities: [ posts[1], posts[2]] })
.then(res => {
expect(res.length).toBe(2);

expect(res[0]._id).toEqual(undefined);
expect(typeof res[0].myID).toEqual("string");
posts[1].myID = res[0].myID;

expect(res[1]._id).toEqual(undefined);
expect(typeof res[1].myID).toEqual("string");
posts[2].myID = res[1].myID;
});
});

it("should return with the entity by ID", () => {
return broker.call("posts.get", { id: posts[1].myID })
.then(res => expect(res).toEqual(posts[1]));
});

it("should return with the entity mapped by ID", () => {
return broker.call("posts.get", { id: posts[1].myID, mapping:true })
.then(res => expect(res[posts[1].myID]).toEqual(posts[1]));
});

it("should return with multiple entity by IDs", () => {
return broker.call("posts.get", { id: [posts[2].myID, posts[0].myID] })
.then(res => {
expect(res[0]).toEqual(posts[2]);
expect(res[1]).toEqual(posts[0]);
});
});

it("should return with multiple entities mapped by IDs", () => {
return broker.call("posts.get", { id: [posts[2].myID, posts[0].myID], mapping: true })
.then(res => {
expect(res[posts[2].myID]).toEqual(posts[2]);
expect(res[posts[0].myID]).toEqual(posts[0]);
});
});

it("should find filtered entities (search)", () => {
return broker.call("posts.find", { search: "first" })
.then(res => {
expect(res[0]).toEqual(posts[0]);
});
});

it("should update an entity", () => {
return broker.call("posts.update", {
id: posts[1].myID,
title: "Other title",
content: "Modify my content",
votes: 8
}).then(res => {
expect(res.myID).toEqual(posts[1].myID);
expect(res.title).toEqual("Other title");
expect(res.content).toEqual("Modify my content");
expect(res.votes).toEqual(8);
});
});

it("should find filtered entities (sort)", () => {
return broker.call("posts.find", { sort: "-votes" })
.then(res => {
expect(res.length).toBe(3);

expect(res[0].myID).toEqual(posts[1].myID);
expect(res[1].myID).toEqual(posts[0].myID);
expect(res[2].myID).toEqual(posts[2].myID);
});
});

it("should find filtered entities (limit, offset)", () => {
return broker.call("posts.find", { sort: "votes", limit: "2", offset: 1 })
.then(res => {
expect(res.length).toBe(2);
expect(res[0].myID).toEqual(posts[0].myID);
expect(res[1].myID).toEqual(posts[1].myID);
});
});

it("should find filtered entities (search)", () => {
return broker.call("posts.find", { search: "post", sort: "-votes" })
.then(res => {
expect(res.length).toBe(2);
expect(res[0].myID).toEqual(posts[0].myID);
expect(res[1].myID).toEqual(posts[2].myID);
});
});

it("should find filtered entities (search)", () => {
return broker.call("posts.find", { search: "post", searchFields: ["title"], sort: "-votes" })
.then(res => {
expect(res.length).toBe(2);
expect(res[0].myID).toEqual(posts[0].myID);
expect(res[1].myID).toEqual(posts[2].myID);
});
});

it("should list paginated entities", () => {
return broker.call("posts.list", { sort: "-votes" })
.then(res => {
expect(res.page).toBe(1);
expect(res.pageSize).toBe(10);
expect(res.total).toBe(3);
expect(res.totalPages).toBe(1);

expect(res.rows.length).toBe(3);
expect(res.rows[0].myID).toEqual(posts[1].myID);
expect(res.rows[1].myID).toEqual(posts[0].myID);
expect(res.rows[2].myID).toEqual(posts[2].myID);
});
});

it("should create single entity", () => {
return broker.call("posts.insert", { entity: posts[3] })
.then(res => {
expect(res).toBeInstanceOf(Object);
expect(res._id).toEqual(undefined);
expect(typeof res.myID).toEqual("string");
posts[3].myID = res.myID;
});
});

it("should remove entity by ID", () => {
return broker.call("posts.remove", { id: posts[2].myID })
.then(res => {
expect(res).toBe(1);
});
});
});

0 comments on commit f34e6c6

Please sign in to comment.