fix(medusa): Query SalesChannel Products in storefront (#2272)
This commit is contained in:
@@ -126,8 +126,11 @@ describe("sales channels", () => {
|
||||
})
|
||||
|
||||
describe("POST /store/cart/:id", () => {
|
||||
let salesChannel1, salesChannel2, disabledSalesChannel
|
||||
let product1, product2
|
||||
let salesChannel1
|
||||
let salesChannel2
|
||||
let disabledSalesChannel
|
||||
let product1
|
||||
let product2
|
||||
let cart
|
||||
|
||||
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,
|
||||
ProductType,
|
||||
ShippingProfile,
|
||||
ShippingProfileType,
|
||||
ShippingProfileType
|
||||
} from "@medusajs/medusa"
|
||||
import faker from "faker"
|
||||
import { Connection } from "typeorm"
|
||||
import {
|
||||
ProductVariantFactoryData,
|
||||
simpleProductVariantFactory,
|
||||
simpleProductVariantFactory
|
||||
} from "./simple-product-variant-factory"
|
||||
import {
|
||||
SalesChannelFactoryData,
|
||||
simpleSalesChannelFactory,
|
||||
simpleSalesChannelFactory
|
||||
} from "./simple-sales-channel-factory"
|
||||
|
||||
export type ProductFactoryData = {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { IsNumber, IsOptional, IsString } from "class-validator"
|
||||
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 { Product } from "../../../../models"
|
||||
import { PricedProduct } from "../../../../types/pricing"
|
||||
import { FilterableProductProps } from "../../../../types/product"
|
||||
|
||||
/**
|
||||
* @oas [get] /products
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
import {
|
||||
CartService,
|
||||
ProductService,
|
||||
RegionService,
|
||||
} from "../../../../services"
|
||||
import { Transform, Type } from "class-transformer"
|
||||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
ValidateNested
|
||||
} from "class-validator"
|
||||
import { Transform, Type } from "class-transformer"
|
||||
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 { optionalBooleanMapper } from "../../../../utils/validators/is-boolean"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
import SalesChannelFeatureFlag from "../../../../loaders/feature-flags/sales-channels"
|
||||
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 { 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
|
||||
@@ -294,6 +296,12 @@ export class StoreGetProductsParams extends StoreGetProductsPaginationParams {
|
||||
@IsOptional()
|
||||
type?: string
|
||||
|
||||
@FeatureFlagDecorators(SalesChannelFeatureFlag.key, [
|
||||
IsOptional(),
|
||||
IsArray(),
|
||||
])
|
||||
sales_channel_id?: string[]
|
||||
|
||||
@IsOptional()
|
||||
@ValidateNested()
|
||||
@Type(() => DateComparisonOperator)
|
||||
|
||||
@@ -5,15 +5,17 @@ import {
|
||||
IsEnum,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
ValidateNested
|
||||
} from "class-validator"
|
||||
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
|
||||
import { Product, ProductOptionValue, ProductStatus } from "../models"
|
||||
import { FeatureFlagDecorators } from "../utils/feature-flag-decorators"
|
||||
import { optionalBooleanMapper } from "../utils/validators/is-boolean"
|
||||
import { IsType } from "../utils/validators/is-type"
|
||||
import {
|
||||
DateComparisonOperator,
|
||||
FindConfig,
|
||||
StringComparisonOperator,
|
||||
StringComparisonOperator
|
||||
} from "./common"
|
||||
import { PriceListLoadConfig } from "./price-list"
|
||||
|
||||
@@ -66,8 +68,10 @@ export class FilterableProductProps {
|
||||
@IsOptional()
|
||||
type?: string
|
||||
|
||||
@IsArray()
|
||||
@IsOptional()
|
||||
@FeatureFlagDecorators(SalesChannelFeatureFlag.key, [
|
||||
IsOptional(),
|
||||
IsArray(),
|
||||
])
|
||||
sales_channel_id?: string[]
|
||||
|
||||
@IsOptional()
|
||||
|
||||
Reference in New Issue
Block a user