feat: Add support for search to all endpoints (#7149)

* feat: Add search capability to api keys

* feat: Add support for searching to currency and customer endpoints

* fix: Clean up product search filters

* feat: Add search support to regions

* feat: Add search support to sales channels

* feat: Add search support to store module

* feat: Add search support to user module

* fix: Clean up inventory search

* feat: Add search support for payments

* fix: Add searchable attributes to stock location models

* feat: Add search support to tax

* feat: Add search support to promotions

* feat: Add search support for pricing, filtering cleanup

* fix: Further cleanups around search
This commit is contained in:
Stevche Radevski
2024-04-25 17:36:59 +02:00
committed by GitHub
parent d02905cefa
commit f03a822253
52 changed files with 640 additions and 64 deletions
@@ -85,6 +85,43 @@ medusaIntegrationTestRunner({
expect(listedApiKeys.data.api_keys).toHaveLength(0)
})
it("should allow searching for api keys", async () => {
await api.post(
`/admin/api-keys`,
{
title: "Test Secret Key",
type: ApiKeyType.SECRET,
},
adminHeaders
)
await api.post(
`/admin/api-keys`,
{
title: "Test Publishable Key",
type: ApiKeyType.PUBLISHABLE,
},
adminHeaders
)
const listedSecretKeys = await api.get(
`/admin/api-keys?q=Secret`,
adminHeaders
)
const listedPublishableKeys = await api.get(
`/admin/api-keys?q=Publish`,
adminHeaders
)
expect(listedSecretKeys.data.api_keys).toHaveLength(1)
expect(listedSecretKeys.data.api_keys[0].title).toEqual(
"Test Secret Key"
)
expect(listedPublishableKeys.data.api_keys).toHaveLength(1)
expect(listedPublishableKeys.data.api_keys[0].title).toEqual(
"Test Publishable Key"
)
})
it("can use a secret api key for authentication", async () => {
const created = await api.post(
`/admin/api-keys`,
@@ -1948,6 +1948,46 @@ medusaIntegrationTestRunner({
])
)
})
it("should allow searching of variants", async () => {
await breaking(
() => {},
async () => {
const newProduct = (
await api.post(
"/admin/products",
getProductFixture({
variants: [
{ title: "First variant", prices: [] },
{ title: "Second variant", prices: [] },
],
}),
adminHeaders
)
).data.product
const res = await api
.get(
`/admin/products/${newProduct.id}/variants?q=first`,
adminHeaders
)
.catch((err) => {
console.log(err)
})
expect(res.status).toEqual(200)
expect(res.data.variants).toHaveLength(1)
expect(res.data.variants).toEqual(
expect.arrayContaining([
expect.objectContaining({
title: "First variant",
product_id: newProduct.id,
}),
])
)
}
)
})
})
describe("updates a variant's default prices (ignores prices associated with a Price List)", () => {
@@ -157,40 +157,30 @@ medusaIntegrationTestRunner({
})
it("should list the sales channel using filters", async () => {
const response = await breaking(
async () => {
return await api.get(`/admin/sales-channels?q=2`, adminReqConfig)
},
() => undefined
const response = await api.get(
`/admin/sales-channels?q=2`,
adminReqConfig
)
breaking(
() => {
expect(response.status).toEqual(200)
expect(response.data.sales_channels).toBeTruthy()
expect(response.data.sales_channels.length).toBe(1)
expect(response.data).toEqual({
count: 1,
limit: 20,
offset: 0,
sales_channels: expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
name: salesChannel2.name,
description: salesChannel2.description,
is_disabled: false,
deleted_at: null,
created_at: expect.any(String),
updated_at: expect.any(String),
}),
]),
})
},
() => {
// TODO: Free text search is not supported in the new sales channel API (yet)
expect(response).toBeUndefined()
}
)
expect(response.status).toEqual(200)
expect(response.data.sales_channels).toBeTruthy()
expect(response.data.sales_channels.length).toBe(1)
expect(response.data).toEqual({
count: 1,
limit: 20,
offset: 0,
sales_channels: expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
name: salesChannel2.name,
description: salesChannel2.description,
is_disabled: false,
deleted_at: null,
created_at: expect.any(String),
updated_at: expect.any(String),
}),
]),
})
})
it("should list the sales channel using properties filters", async () => {
@@ -219,6 +209,37 @@ medusaIntegrationTestRunner({
]),
})
})
it("should support searching of sales channels", async () => {
await breaking(
() => {},
async () => {
await api.post(
"/admin/sales-channels",
{ name: "first channel", description: "to fetch" },
adminReqConfig
)
await api.post(
"/admin/sales-channels",
{ name: "second channel", description: "not in response" },
adminReqConfig
)
const response = await api.get(
`/admin/sales-channels?q=fetch`,
adminReqConfig
)
expect(response.status).toEqual(200)
expect(response.data.sales_channels).toEqual([
expect.objectContaining({
name: "first channel",
}),
])
}
)
})
})
describe("POST /admin/sales-channels/:id", () => {
+34 -1
View File
@@ -50,7 +50,11 @@ medusaIntegrationTestRunner({
() =>
api
.get("/admin/stores", adminHeaders)
.then((r) => r.data.stores[0])
.then((r) =>
r.data.stores.find(
(s) => s.default_sales_channel_id === "sc_12345"
)
)
)
expect(store).toEqual(
@@ -245,6 +249,35 @@ medusaIntegrationTestRunner({
)
})
})
describe("GET /admin/store", () => {
it("supports searching of stores", async () => {
await breaking(
() => {},
async () => {
const service = container.resolve(ModuleRegistrationName.STORE)
const secondStore = await service.create({
name: "Second Store",
supported_currency_codes: ["eur"],
default_currency_code: "eur",
})
const response = await api.get(
"/admin/stores?q=second",
adminHeaders
)
expect(response.status).toEqual(200)
expect(response.data.stores).toEqual([
expect.objectContaining({
id: secondStore.id,
name: "Second Store",
}),
])
}
)
})
})
})
},
})
@@ -143,7 +143,6 @@ medusaIntegrationTestRunner({
)
})
// TODO: Free text search not supported in 2.0 yet
it("should list users that match the free text search", async () => {
const response = await api.get("/admin/users?q=member", adminHeaders)
@@ -159,7 +158,10 @@ medusaIntegrationTestRunner({
last_name: "user",
created_at: expect.any(String),
updated_at: expect.any(String),
role: "member",
...breaking(
() => ({ role: "member" }),
() => ({})
),
}),
])
)
@@ -53,6 +53,18 @@ medusaIntegrationTestRunner({
expect.objectContaining({ code: "zwl", name: "Zimbabwean Dollar" })
)
})
it("should allow for searching of currencies", async () => {
const listResp = await api.get(
"/admin/currencies?q=zimbabwean",
adminHeaders
)
expect(listResp.data.currencies).toHaveLength(1)
expect(listResp.data.currencies[0]).toEqual(
expect.objectContaining({ code: "zwl", name: "Zimbabwean Dollar" })
)
})
})
},
})
@@ -44,6 +44,29 @@ medusaIntegrationTestRunner({
}),
])
})
it("should support searching of customer groups", async () => {
await customerModuleService.createCustomerGroup([
{
name: "First group",
},
{ name: "Second group" },
])
const response = await api.get(
`/admin/customer-groups?q=fir`,
adminHeaders
)
expect(response.status).toEqual(200)
expect(response.data.customer_groups).toHaveLength(1)
expect(response.data.customer_groups[0]).toEqual(
expect.objectContaining({
id: expect.any(String),
name: "First group",
})
)
})
})
},
})
@@ -92,6 +92,53 @@ medusaIntegrationTestRunner({
])
)
})
it("should support searching through the addresses", async () => {
const [customer] = await customerModuleService.create([
{
first_name: "Test",
last_name: "Test",
email: "test@me.com",
addresses: [
{
first_name: "John",
last_name: "Doe",
address_1: "Huntingdon 123",
},
{
first_name: "Jane",
last_name: "Doe",
address_1: "Horseshoe 555",
},
{
first_name: "Jack",
last_name: "Doe",
address_1: "Hawkins 12",
},
],
},
])
const response = await api.get(
`/admin/customers/${customer.id}/addresses?q=12`,
adminHeaders
)
expect(response.status).toEqual(200)
expect(response.data.addresses).toHaveLength(2)
expect(response.data.addresses).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
address_1: "Huntingdon 123",
}),
expect.objectContaining({
id: expect.any(String),
address_1: "Hawkins 12",
}),
])
)
})
})
},
})
@@ -141,6 +141,43 @@ medusaIntegrationTestRunner({
})
)
})
it("should support searching of customers", async () => {
await customerModuleService.create([
{
first_name: "Jane",
last_name: "Doe",
email: "jane@me.com",
},
{
first_name: "John",
last_name: "Doe",
email: "john@me.com",
},
{
first_name: "LeBron",
last_name: "James",
email: "lebron@me.com",
},
])
const response = await api.get(`/admin/customers?q=do`, adminHeaders)
expect(response.status).toEqual(200)
expect(response.data.customers).toHaveLength(2)
expect(response.data.customers).toEqual(
expect.arrayContaining([
expect.objectContaining({
first_name: "Jane",
last_name: "Doe",
}),
expect.objectContaining({
first_name: "John",
last_name: "Doe",
}),
])
)
})
})
},
})
@@ -162,6 +162,71 @@ medusaIntegrationTestRunner({
},
])
})
it("should support searching of price lists", async () => {
const priceSet = await createVariantPriceSet({
container: appContainer,
variantId: variant.id,
prices: [],
})
await pricingModule.createPriceLists([
{
title: "first price list",
description: "test price",
ends_at: new Date(),
starts_at: new Date(),
status: PriceListStatus.ACTIVE,
type: PriceListType.OVERRIDE,
prices: [
{
amount: 5000,
currency_code: "usd",
price_set_id: priceSet.id,
rules: {
region_id: region.id,
},
},
],
rules: {
customer_group_id: [customerGroup.id],
},
},
{
title: "second price list",
description: "second test",
ends_at: new Date(),
starts_at: new Date(),
status: PriceListStatus.ACTIVE,
type: PriceListType.OVERRIDE,
prices: [
{
amount: 5000,
currency_code: "usd",
price_set_id: priceSet.id,
rules: {
region_id: region.id,
},
},
],
rules: {
customer_group_id: [customerGroup.id],
},
},
])
let response = await api.get(
`/admin/price-lists?q=second`,
adminHeaders
)
expect(response.status).toEqual(200)
expect(response.data.price_lists).toEqual([
expect.objectContaining({
title: "second price list",
}),
])
})
})
describe("GET /admin/price-lists/:id", () => {
@@ -130,6 +130,20 @@ medusaIntegrationTestRunner({
)
})
it("should support search on campaigns", async () => {
const response = await api.get(
`/admin/campaigns?q=ign%202`,
adminHeaders
)
expect(response.status).toEqual(200)
expect(response.data.campaigns).toEqual([
expect.objectContaining({
name: "campaign 2",
}),
])
})
it("should get all campaigns and its count filtered", async () => {
const response = await api.get(
`/admin/campaigns?fields=name,created_at,budget.id`,
@@ -67,6 +67,38 @@ medusaIntegrationTestRunner({
])
})
it("should support search of promotions", async () => {
await promotionModuleService.create([
{
code: "first",
type: PromotionType.STANDARD,
application_method: {
type: "fixed",
target_type: "order",
value: 100,
},
},
{
code: "second",
type: PromotionType.STANDARD,
application_method: {
type: "fixed",
target_type: "order",
value: 100,
},
},
])
const response = await api.get(`/admin/promotions?q=fir`, adminHeaders)
expect(response.status).toEqual(200)
expect(response.data.promotions).toEqual([
expect.objectContaining({
code: "first",
}),
])
})
it("should get all promotions and its count filtered", async () => {
await promotionModuleService.create([
{
@@ -343,6 +343,31 @@ medusaIntegrationTestRunner({
])
})
it("should support searching of regions", async () => {
await service.create([
{
name: "APAC",
currency_code: "usd",
countries: ["jp"],
},
{
name: "Europe",
currency_code: "eur",
countries: ["de"],
},
])
const response = await api.get(`/admin/regions?q=eu`, adminHeaders)
expect(response.status).toEqual(200)
expect(response.data.regions).toEqual([
expect.objectContaining({
name: "Europe",
currency_code: "eur",
}),
])
})
it("should get a region", async () => {
const [region] = await service.create([
{
@@ -64,6 +64,33 @@ medusaIntegrationTestRunner({
})
})
it("can search through tax rates", async () => {
const region = await service.createTaxRegions({
country_code: "us",
})
await service.create({
tax_region_id: region.id,
code: "low",
rate: 2.5,
name: "low rate",
})
await service.create({
tax_region_id: region.id,
code: "high",
rate: 5,
name: "high rate",
})
const response = await api.get(`/admin/tax-rates?q=high`, adminHeaders)
expect(response.status).toEqual(200)
expect(response.data.tax_rates).toEqual(
expect.arrayContaining([expect.objectContaining({ code: "high" })])
)
})
it("can create a tax region with rates and rules", async () => {
const regionRes = await api.post(
`/admin/tax-regions`,
@@ -402,6 +429,31 @@ medusaIntegrationTestRunner({
})
})
it("can search through tax regions", async () => {
await service.createTaxRegions([
{
country_code: "us",
province_code: "texas",
},
{
country_code: "us",
province_code: "florida",
},
])
const response = await api.get(`/admin/tax-regions?q=ida`, adminHeaders)
expect(response.status).toEqual(200)
expect(response.data.tax_regions).toEqual(
expect.arrayContaining([
expect.objectContaining({
country_code: "us",
province_code: "florida",
}),
])
)
})
it("can create a tax region and delete it", async () => {
const regionRes = await api.post(
`/admin/tax-regions`,