chore(): Add new regression tests to the remote joiner (#14119)
* Add tests * Add tests * Add tests
This commit is contained in:
1 parent
2cc42ca0ef
commit
6057afdfaa
3 files changed
+244
-2
No files matched your search
@@ -186,4 +186,62 @@ export const remoteJoinerData = {
|
|||||||
user_id: 1,
|
user_id: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
link: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
url: "https://example.com/post-1",
|
||||||
|
product_id: 101,
|
||||||
|
post_id: 501,
|
||||||
|
metadata: {
|
||||||
|
source: "blog",
|
||||||
|
category: "tech",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
url: "https://example.com/post-2",
|
||||||
|
product_id: 102,
|
||||||
|
post_id: 502,
|
||||||
|
metadata: {
|
||||||
|
source: "news",
|
||||||
|
category: "general",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
url: "https://example.com/post-3",
|
||||||
|
product_id: 103,
|
||||||
|
post_id: 503,
|
||||||
|
metadata: {
|
||||||
|
source: "forum",
|
||||||
|
category: "discussion",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
post: [
|
||||||
|
{
|
||||||
|
id: 501,
|
||||||
|
title: "First Post",
|
||||||
|
content: "Content of first post",
|
||||||
|
author: "John Doe",
|
||||||
|
published: true,
|
||||||
|
views: 1000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 502,
|
||||||
|
title: "Second Post",
|
||||||
|
content: "Content of second post",
|
||||||
|
author: "Jane Smith",
|
||||||
|
published: true,
|
||||||
|
views: 2500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 503,
|
||||||
|
title: "Third Post",
|
||||||
|
content: "Content of third post",
|
||||||
|
author: "Bob Johnson",
|
||||||
|
published: false,
|
||||||
|
views: 150,
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { JoinerServiceConfig } from "@medusajs/types"
|
import { JoinerServiceConfig, ModuleJoinerConfig } from "@medusajs/types"
|
||||||
import { remoteJoinerData } from "./../../__fixtures__/joiner/data"
|
import { remoteJoinerData } from "./../../__fixtures__/joiner/data"
|
||||||
|
|
||||||
export const serviceConfigs: JoinerServiceConfig[] = [
|
export const serviceConfigs: (JoinerServiceConfig | ModuleJoinerConfig)[] = [
|
||||||
{
|
{
|
||||||
serviceName: "user",
|
serviceName: "user",
|
||||||
primaryKeys: ["id"],
|
primaryKeys: ["id"],
|
||||||
@@ -49,6 +49,13 @@ export const serviceConfigs: JoinerServiceConfig[] = [
|
|||||||
primaryKey: "id",
|
primaryKey: "id",
|
||||||
alias: "user",
|
alias: "user",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
foreignKey: "product_id",
|
||||||
|
primaryKey: "id",
|
||||||
|
serviceName: "link",
|
||||||
|
alias: "links",
|
||||||
|
inverse: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -106,6 +113,74 @@ export const serviceConfigs: JoinerServiceConfig[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
serviceName: "link",
|
||||||
|
isLink: true,
|
||||||
|
primaryKeys: ["id", "product_id", "post_id"],
|
||||||
|
relationships: [
|
||||||
|
{
|
||||||
|
serviceName: "product",
|
||||||
|
entity: "Product",
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "product_id",
|
||||||
|
alias: "product",
|
||||||
|
args: {
|
||||||
|
methodSuffix: "Products",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serviceName: "post",
|
||||||
|
entity: "Post",
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "post_id",
|
||||||
|
alias: "post",
|
||||||
|
args: {
|
||||||
|
methodSuffix: "Posts",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
extends: [
|
||||||
|
{
|
||||||
|
serviceName: "product",
|
||||||
|
entity: "Product",
|
||||||
|
fieldAlias: {
|
||||||
|
posts: "links.post",
|
||||||
|
},
|
||||||
|
relationship: {
|
||||||
|
serviceName: "link",
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "product_id",
|
||||||
|
alias: "links",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serviceName: "post",
|
||||||
|
entity: "Post",
|
||||||
|
fieldAlias: {
|
||||||
|
product: "links.product",
|
||||||
|
},
|
||||||
|
relationship: {
|
||||||
|
serviceName: "link",
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "post_id",
|
||||||
|
alias: "links",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
serviceName: "post",
|
||||||
|
primaryKeys: ["id"],
|
||||||
|
relationships: [
|
||||||
|
{
|
||||||
|
serviceName: "link",
|
||||||
|
primaryKey: "id",
|
||||||
|
foreignKey: "post_id",
|
||||||
|
alias: "links",
|
||||||
|
inverse: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export const mockServiceList = (serviceName) => {
|
export const mockServiceList = (serviceName) => {
|
||||||
@@ -115,6 +190,8 @@ export const mockServiceList = (serviceName) => {
|
|||||||
productService: remoteJoinerData.product,
|
productService: remoteJoinerData.product,
|
||||||
variantService: remoteJoinerData.variant,
|
variantService: remoteJoinerData.variant,
|
||||||
orderService: remoteJoinerData.order,
|
orderService: remoteJoinerData.order,
|
||||||
|
linkService: remoteJoinerData.link,
|
||||||
|
postService: remoteJoinerData.post,
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultset = JSON.parse(JSON.stringify(src[serviceName]))
|
let resultset = JSON.parse(JSON.stringify(src[serviceName]))
|
||||||
@@ -134,6 +211,18 @@ export const mockServiceList = (serviceName) => {
|
|||||||
resultset = resultset.filter((item) => data.options.id.includes(item.id))
|
resultset = resultset.filter((item) => data.options.id.includes(item.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mock filtering on service link
|
||||||
|
if (serviceName === "linkService" && data.options?.product_id) {
|
||||||
|
resultset = resultset.filter((item) =>
|
||||||
|
data.options.product_id.includes(item.product_id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mock filtering on service post
|
||||||
|
if (serviceName === "postService" && data.options?.id) {
|
||||||
|
resultset = resultset.filter((item) => data.options.id.includes(item.id))
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: resultset,
|
data: resultset,
|
||||||
path: serviceName === "productService" ? "rows" : undefined,
|
path: serviceName === "productService" ? "rows" : undefined,
|
||||||
@@ -146,4 +235,6 @@ export const serviceMock = {
|
|||||||
userService: mockServiceList("userService"),
|
userService: mockServiceList("userService"),
|
||||||
productService: mockServiceList("productService"),
|
productService: mockServiceList("productService"),
|
||||||
variantService: mockServiceList("variantService"),
|
variantService: mockServiceList("variantService"),
|
||||||
|
linkService: mockServiceList("linkService"),
|
||||||
|
postService: mockServiceList("postService"),
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,9 @@ const container = {
|
|||||||
list: (...args) => {
|
list: (...args) => {
|
||||||
return serviceMock[serviceName].apply(this, args)
|
return serviceMock[serviceName].apply(this, args)
|
||||||
},
|
},
|
||||||
|
getByProductId: (...args) => {
|
||||||
|
return serviceMock[serviceName].apply(this, args)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
} as MedusaContainer
|
} as MedusaContainer
|
||||||
@@ -610,4 +613,94 @@ describe("RemoteJoiner", () => {
|
|||||||
options: { id: expect.arrayContaining([103, 102]) },
|
options: { id: expect.arrayContaining([103, 102]) },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should not lose fields when querying with specific nested fields and wildcard on deeply nested relations", async () => {
|
||||||
|
// This ensures that when we have:
|
||||||
|
// - A specific field from the root entity (product.name)
|
||||||
|
// - A specific field from an intermediate relation (links.metadata)
|
||||||
|
// - A wildcard on a relation accessed through that intermediate (links.post.*)
|
||||||
|
// ...the intermediate field (links.metadata) is not lost
|
||||||
|
const query = {
|
||||||
|
alias: "product",
|
||||||
|
fields: ["id", "name"],
|
||||||
|
expands: [
|
||||||
|
{
|
||||||
|
property: "links",
|
||||||
|
fields: ["metadata"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
property: "posts",
|
||||||
|
fields: ["*"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
args: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await joiner.query(query)
|
||||||
|
|
||||||
|
expect(serviceMock.productService).toHaveBeenCalledTimes(1)
|
||||||
|
expect(serviceMock.productService).toHaveBeenCalledWith({
|
||||||
|
args: undefined,
|
||||||
|
fields: expect.arrayContaining(["id", "name"]),
|
||||||
|
expands: undefined,
|
||||||
|
options: { id: undefined },
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(serviceMock.linkService).toHaveBeenCalledTimes(1)
|
||||||
|
expect(serviceMock.linkService).toHaveBeenCalledWith({
|
||||||
|
args: undefined,
|
||||||
|
expands: undefined,
|
||||||
|
fields: expect.arrayContaining(["metadata", "product_id"]),
|
||||||
|
options: { product_id: expect.arrayContaining([101, 102, 103]) },
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(serviceMock.postService).toHaveBeenCalledTimes(1)
|
||||||
|
expect(serviceMock.postService).toHaveBeenCalledWith({
|
||||||
|
args: undefined,
|
||||||
|
expands: undefined,
|
||||||
|
fields: ["*", "id"],
|
||||||
|
options: { id: [501, 502, 503] }, // All posts are fetched
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result.rows).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: 101,
|
||||||
|
name: "Product 1",
|
||||||
|
links: expect.objectContaining({
|
||||||
|
metadata: expect.objectContaining({
|
||||||
|
source: expect.any(String),
|
||||||
|
category: expect.any(String),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
posts: expect.objectContaining({
|
||||||
|
id: 501,
|
||||||
|
title: expect.any(String),
|
||||||
|
content: expect.any(String),
|
||||||
|
author: expect.any(String),
|
||||||
|
published: expect.any(Boolean),
|
||||||
|
views: expect.any(Number),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
// Critical assertion: metadata must not be lost
|
||||||
|
const firstProduct = result.rows[0]
|
||||||
|
expect(firstProduct.links).toBeDefined()
|
||||||
|
expect(firstProduct.links).toHaveProperty("metadata")
|
||||||
|
expect(firstProduct.links.metadata).toEqual({
|
||||||
|
source: "blog",
|
||||||
|
category: "tech",
|
||||||
|
})
|
||||||
|
|
||||||
|
// posts.* should include all fields
|
||||||
|
expect(firstProduct).toHaveProperty("posts")
|
||||||
|
expect(firstProduct.posts).toHaveProperty("id")
|
||||||
|
expect(firstProduct.posts).toHaveProperty("title")
|
||||||
|
expect(firstProduct.posts).toHaveProperty("content")
|
||||||
|
expect(firstProduct.posts).toHaveProperty("author")
|
||||||
|
expect(firstProduct.posts).toHaveProperty("published")
|
||||||
|
expect(firstProduct.posts).toHaveProperty("views")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
Reference in new issue
Block a user