fix(medusa): Query SalesChannel Products in storefront (#2272)
This commit is contained in:
1 parent
a2bb504e6e
commit
8797a1441b
5 files changed
+131
-26
No files matched your search
@@ -126,8 +126,11 @@ describe("sales channels", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("POST /store/cart/:id", () => {
|
describe("POST /store/cart/:id", () => {
|
||||||
let salesChannel1, salesChannel2, disabledSalesChannel
|
let salesChannel1
|
||||||
let product1, product2
|
let salesChannel2
|
||||||
|
let disabledSalesChannel
|
||||||
|
let product1
|
||||||
|
let product2
|
||||||
let cart
|
let cart
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -289,4 +292,94 @@ describe("sales channels", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("GET /store/products", () => {
|
||||||
|
let salesChannel1
|
||||||
|
let salesChannel2
|
||||||
|
let product1
|
||||||
|
let product2
|
||||||
|
beforeEach(async () => {
|
||||||
|
salesChannel1 = await simpleSalesChannelFactory(dbConnection, {
|
||||||
|
name: "salesChannel1",
|
||||||
|
description: "salesChannel1",
|
||||||
|
})
|
||||||
|
|
||||||
|
salesChannel2 = await simpleSalesChannelFactory(dbConnection, {
|
||||||
|
name: "salesChannel2",
|
||||||
|
description: "salesChannel2",
|
||||||
|
})
|
||||||
|
|
||||||
|
product1 = await simpleProductFactory(dbConnection, {
|
||||||
|
title: "prod 1",
|
||||||
|
status: "published",
|
||||||
|
sales_channels: [salesChannel1],
|
||||||
|
})
|
||||||
|
|
||||||
|
product2 = await simpleProductFactory(dbConnection, {
|
||||||
|
title: "prod 2",
|
||||||
|
status: "published",
|
||||||
|
sales_channels: [salesChannel2],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns products from a specific sales channel", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(
|
||||||
|
`/store/products?sales_channel_id[]=${salesChannel1.id}`
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.data.products.length).toBe(1)
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns products from multiples sales channels", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(
|
||||||
|
`/store/products?sales_channel_id[]=${salesChannel1.id}&sales_channel_id[]=${salesChannel2.id}`
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.data.products.length).toBe(2)
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns all products by default", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.get(`/store/products`)
|
||||||
|
|
||||||
|
expect(response.data.products.length).toBe(2)
|
||||||
|
expect(response.data.products).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@@ -4,17 +4,17 @@ import {
|
|||||||
ProductTag,
|
ProductTag,
|
||||||
ProductType,
|
ProductType,
|
||||||
ShippingProfile,
|
ShippingProfile,
|
||||||
ShippingProfileType,
|
ShippingProfileType
|
||||||
} from "@medusajs/medusa"
|
} from "@medusajs/medusa"
|
||||||
import faker from "faker"
|
import faker from "faker"
|
||||||
import { Connection } from "typeorm"
|
import { Connection } from "typeorm"
|
||||||
import {
|
import {
|
||||||
ProductVariantFactoryData,
|
ProductVariantFactoryData,
|
||||||
simpleProductVariantFactory,
|
simpleProductVariantFactory
|
||||||
} from "./simple-product-variant-factory"
|
} from "./simple-product-variant-factory"
|
||||||
import {
|
import {
|
||||||
SalesChannelFactoryData,
|
SalesChannelFactoryData,
|
||||||
simpleSalesChannelFactory,
|
simpleSalesChannelFactory
|
||||||
} from "./simple-sales-channel-factory"
|
} from "./simple-sales-channel-factory"
|
||||||
|
|
||||||
export type ProductFactoryData = {
|
export type ProductFactoryData = {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { IsNumber, IsOptional, IsString } from "class-validator"
|
import { IsNumber, IsOptional, IsString } from "class-validator"
|
||||||
import { PricingService, ProductService } from "../../../../services"
|
import { PricingService, ProductService } from "../../../../services"
|
||||||
|
|
||||||
import { FilterableProductProps } from "../../../../types/product"
|
|
||||||
import { PricedProduct } from "../../../../types/pricing"
|
|
||||||
import { Product } from "../../../../models"
|
|
||||||
import { Type } from "class-transformer"
|
import { Type } from "class-transformer"
|
||||||
|
import { Product } from "../../../../models"
|
||||||
|
import { PricedProduct } from "../../../../types/pricing"
|
||||||
|
import { FilterableProductProps } from "../../../../types/product"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [get] /products
|
* @oas [get] /products
|
||||||
|
|||||||
@@ -1,28 +1,30 @@
|
|||||||
import {
|
import { Transform, Type } from "class-transformer"
|
||||||
CartService,
|
|
||||||
ProductService,
|
|
||||||
RegionService,
|
|
||||||
} from "../../../../services"
|
|
||||||
import {
|
import {
|
||||||
IsArray,
|
IsArray,
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
IsNumber,
|
IsNumber,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
IsString,
|
IsString,
|
||||||
ValidateNested,
|
ValidateNested
|
||||||
} from "class-validator"
|
} from "class-validator"
|
||||||
import { Transform, Type } from "class-transformer"
|
|
||||||
import { omit, pickBy } from "lodash"
|
import { omit, pickBy } from "lodash"
|
||||||
|
import {
|
||||||
|
CartService,
|
||||||
|
ProductService,
|
||||||
|
RegionService
|
||||||
|
} from "../../../../services"
|
||||||
|
|
||||||
import { DateComparisonOperator } from "../../../../types/common"
|
|
||||||
import { IsType } from "../../../../utils/validators/is-type"
|
|
||||||
import { PriceSelectionParams } from "../../../../types/price-selection"
|
|
||||||
import PricingService from "../../../../services/pricing"
|
|
||||||
import { Product } from "../../../../models"
|
|
||||||
import { defaultStoreProductsRelations } from "."
|
import { defaultStoreProductsRelations } from "."
|
||||||
import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean"
|
import SalesChannelFeatureFlag from "../../../../loaders/feature-flags/sales-channels"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { Product } from "../../../../models"
|
||||||
|
import PricingService from "../../../../services/pricing"
|
||||||
|
import { DateComparisonOperator } from "../../../../types/common"
|
||||||
|
import { PriceSelectionParams } from "../../../../types/price-selection"
|
||||||
import { isDefined } from "../../../../utils"
|
import { isDefined } from "../../../../utils"
|
||||||
|
import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators"
|
||||||
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean"
|
||||||
|
import { IsType } from "../../../../utils/validators/is-type"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [get] /products
|
* @oas [get] /products
|
||||||
@@ -294,6 +296,12 @@ export class StoreGetProductsParams extends StoreGetProductsPaginationParams {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
type?: string
|
type?: string
|
||||||
|
|
||||||
|
@FeatureFlagDecorators(SalesChannelFeatureFlag.key, [
|
||||||
|
IsOptional(),
|
||||||
|
IsArray(),
|
||||||
|
])
|
||||||
|
sales_channel_id?: string[]
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@Type(() => DateComparisonOperator)
|
@Type(() => DateComparisonOperator)
|
||||||
|
|||||||
@@ -5,15 +5,17 @@ import {
|
|||||||
IsEnum,
|
IsEnum,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
IsString,
|
IsString,
|
||||||
ValidateNested,
|
ValidateNested
|
||||||
} from "class-validator"
|
} from "class-validator"
|
||||||
|
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
|
||||||
import { Product, ProductOptionValue, ProductStatus } from "../models"
|
import { Product, ProductOptionValue, ProductStatus } from "../models"
|
||||||
|
import { FeatureFlagDecorators } from "../utils/feature-flag-decorators"
|
||||||
import { optionalBooleanMapper } from "../utils/validators/is-boolean"
|
import { optionalBooleanMapper } from "../utils/validators/is-boolean"
|
||||||
import { IsType } from "../utils/validators/is-type"
|
import { IsType } from "../utils/validators/is-type"
|
||||||
import {
|
import {
|
||||||
DateComparisonOperator,
|
DateComparisonOperator,
|
||||||
FindConfig,
|
FindConfig,
|
||||||
StringComparisonOperator,
|
StringComparisonOperator
|
||||||
} from "./common"
|
} from "./common"
|
||||||
import { PriceListLoadConfig } from "./price-list"
|
import { PriceListLoadConfig } from "./price-list"
|
||||||
|
|
||||||
@@ -66,8 +68,10 @@ export class FilterableProductProps {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
type?: string
|
type?: string
|
||||||
|
|
||||||
@IsArray()
|
@FeatureFlagDecorators(SalesChannelFeatureFlag.key, [
|
||||||
@IsOptional()
|
IsOptional(),
|
||||||
|
IsArray(),
|
||||||
|
])
|
||||||
sales_channel_id?: string[]
|
sales_channel_id?: string[]
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
|||||||
Reference in new issue
Block a user