** What
- Allow auto-loaded Medusa files to export a config object.
- Currently supports isDisabled to control loading.
- new instance `FeatureFlag` exported by `@medusajs/framework/utils`
- `feature-flags` is now a supported folder for medusa projects, modules, providers and plugins. They will be loaded and added to `FeatureFlag`
** Why
- Enables conditional loading of routes, migrations, jobs, subscribers, workflows, and other files based on feature flags.
```ts
// /src/feature-flags
import { FlagSettings } from "@medusajs/framework/feature-flags"
const CustomFeatureFlag: FlagSettings = {
key: "custom_feature",
default_val: false,
env_key: "FF_MY_CUSTOM_FEATURE",
description: "Enable xyz",
}
export default CustomFeatureFlag
```
```ts
// /src/modules/my-custom-module/migration/Migration20250822135845.ts
import { FeatureFlag } from "@medusajs/framework/utils"
export class Migration20250822135845 extends Migration {
override async up(){ }
override async down(){ }
}
defineFileConfig({
isDisabled: () => !FeatureFlag.isFeatureEnabled("custom_feature")
})
```
949 lines
31 KiB
TypeScript
949 lines
31 KiB
TypeScript
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
|
import { adminHeaders, createAdminUser } from "../../helpers/create-admin-user"
|
|
|
|
jest.setTimeout(50000)
|
|
|
|
const env = { MEDUSA_FF_VIEW_CONFIGURATIONS: true }
|
|
|
|
medusaIntegrationTestRunner({
|
|
env,
|
|
testSuite: ({ dbConnection, api, getContainer }) => {
|
|
describe("View Configurations API", () => {
|
|
let adminHeader
|
|
let secondAdminHeader
|
|
let secondAdminUserId
|
|
let adminUserId
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const { user: adminUser } = await createAdminUser(
|
|
dbConnection,
|
|
adminHeaders,
|
|
container
|
|
)
|
|
adminHeader = adminHeaders.headers
|
|
adminUserId = adminUser.id
|
|
|
|
// Create a second admin user
|
|
const secondAdminHeaders = { headers: {} }
|
|
const { user: secondAdminUser } = await createAdminUser(
|
|
dbConnection,
|
|
secondAdminHeaders,
|
|
container,
|
|
{ email: "admin2@test.com" }
|
|
)
|
|
secondAdminUserId = secondAdminUser.id
|
|
secondAdminHeader = secondAdminHeaders.headers
|
|
})
|
|
|
|
describe("POST /admin/views/{entity}/configurations", () => {
|
|
it("should create a personal view configuration", async () => {
|
|
const payload = {
|
|
name: "My Order View",
|
|
configuration: {
|
|
visible_columns: ["id", "display_id", "created_at"],
|
|
column_order: ["display_id", "id", "created_at"],
|
|
},
|
|
}
|
|
|
|
const response = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
payload,
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configuration).toMatchObject({
|
|
entity: "orders",
|
|
name: "My Order View",
|
|
user_id: secondAdminUserId,
|
|
configuration: payload.configuration,
|
|
})
|
|
expect(response.data.view_configuration.is_system_default).toBeFalsy()
|
|
})
|
|
|
|
it("should create a system default view as admin", async () => {
|
|
const payload = {
|
|
name: "Default Order View",
|
|
is_system_default: true,
|
|
configuration: {
|
|
visible_columns: ["id", "display_id", "created_at", "total"],
|
|
column_order: ["display_id", "created_at", "total", "id"],
|
|
},
|
|
}
|
|
|
|
const response = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
payload,
|
|
{
|
|
headers: adminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configuration).toMatchObject({
|
|
entity: "orders",
|
|
name: "Default Order View",
|
|
user_id: null,
|
|
is_system_default: true,
|
|
configuration: payload.configuration,
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("GET /admin/views/{entity}/configurations", () => {
|
|
let systemView
|
|
let personalView
|
|
let otherUserView
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
// Create system default view
|
|
systemView = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "System Default",
|
|
is_system_default: true,
|
|
user_id: null,
|
|
configuration: {
|
|
visible_columns: ["id", "display_id"],
|
|
column_order: ["display_id", "id"],
|
|
},
|
|
})
|
|
|
|
// Create personal view for non-admin user
|
|
personalView = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "My Personal View",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id", "total"],
|
|
column_order: ["total", "id"],
|
|
},
|
|
})
|
|
|
|
// Create view for another user
|
|
otherUserView = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Other User View",
|
|
is_system_default: false,
|
|
user_id: "other-user-id",
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
})
|
|
|
|
it("should list system defaults and personal views", async () => {
|
|
const response = await api.get("/admin/views/orders/configurations", {
|
|
headers: secondAdminHeader,
|
|
})
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configurations).toHaveLength(2)
|
|
expect(response.data.view_configurations).toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({ id: systemView.id }),
|
|
expect.objectContaining({ id: personalView.id }),
|
|
])
|
|
)
|
|
// Should not include other user's view
|
|
expect(response.data.view_configurations).not.toEqual(
|
|
expect.arrayContaining([
|
|
expect.objectContaining({ id: otherUserView.id }),
|
|
])
|
|
)
|
|
})
|
|
|
|
it("should filter by entity", async () => {
|
|
const response = await api.get(
|
|
"/admin/views/products/configurations",
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configurations).toHaveLength(0)
|
|
})
|
|
})
|
|
|
|
describe("GET /admin/views/{entity}/configurations/:id", () => {
|
|
let viewConfig
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
viewConfig = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Test View",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
})
|
|
|
|
it("should retrieve own view configuration", async () => {
|
|
const response = await api.get(
|
|
`/admin/views/orders/configurations/${viewConfig.id}`,
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configuration).toMatchObject({
|
|
id: viewConfig.id,
|
|
entity: "orders",
|
|
name: "Test View",
|
|
})
|
|
})
|
|
|
|
it("should prevent access to other user's view", async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
const otherView = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Other View",
|
|
is_system_default: false,
|
|
user_id: "other-user-id",
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
|
|
const response = await api
|
|
.get(`/admin/views/orders/configurations/${otherView.id}`, {
|
|
headers: secondAdminHeader,
|
|
})
|
|
.catch((e) => e.response)
|
|
|
|
expect(response.status).toBe(400)
|
|
})
|
|
})
|
|
|
|
describe("POST /admin/views/{entity}/configurations/:id", () => {
|
|
let viewConfig
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
viewConfig = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Test View",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
})
|
|
|
|
it("should update own view configuration", async () => {
|
|
const payload = {
|
|
name: "Updated View",
|
|
configuration: {
|
|
visible_columns: ["id", "total"],
|
|
column_order: ["total", "id"],
|
|
},
|
|
}
|
|
|
|
const response = await api.post(
|
|
`/admin/views/orders/configurations/${viewConfig.id}`,
|
|
payload,
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configuration).toMatchObject({
|
|
id: viewConfig.id,
|
|
name: "Updated View",
|
|
configuration: payload.configuration,
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("DELETE /admin/views/{entity}/configurations/:id", () => {
|
|
let viewConfig
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
viewConfig = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Test View",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
})
|
|
|
|
it("should delete own view configuration", async () => {
|
|
const response = await api.delete(
|
|
`/admin/views/orders/configurations/${viewConfig.id}`,
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data).toMatchObject({
|
|
id: viewConfig.id,
|
|
object: "view_configuration",
|
|
deleted: true,
|
|
})
|
|
|
|
// Verify it's deleted
|
|
const getResponse = await api
|
|
.get(`/admin/views/orders/configurations/${viewConfig.id}`, {
|
|
headers: secondAdminHeader,
|
|
})
|
|
.catch((e) => e.response)
|
|
|
|
expect(getResponse.status).toBe(404)
|
|
})
|
|
})
|
|
|
|
describe("GET /admin/views/{entity}/configurations/active", () => {
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
// Create and set active view
|
|
const viewConfig = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Active View",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id", "total"],
|
|
column_order: ["total", "id"],
|
|
},
|
|
})
|
|
|
|
await settingsService.setActiveViewConfiguration(
|
|
"orders",
|
|
secondAdminUserId,
|
|
viewConfig.id
|
|
)
|
|
})
|
|
|
|
it("should retrieve active view configuration", async () => {
|
|
const response = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configuration).toMatchObject({
|
|
entity: "orders",
|
|
name: "Active View",
|
|
user_id: secondAdminUserId,
|
|
})
|
|
})
|
|
|
|
it("should return null when no active view", async () => {
|
|
const response = await api.get(
|
|
"/admin/views/products/configurations/active",
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.view_configuration).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe("POST /admin/views/{entity}/configurations/active", () => {
|
|
let viewConfig
|
|
|
|
beforeEach(async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
viewConfig = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "Test View",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
})
|
|
|
|
it("should set active view configuration", async () => {
|
|
const response = await api.post(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
view_configuration_id: viewConfig.id,
|
|
},
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(response.data.success).toBe(true)
|
|
|
|
// Verify it's active
|
|
const activeResponse = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(activeResponse.data.view_configuration.id).toBe(viewConfig.id)
|
|
})
|
|
|
|
it("should clear active view and return to default when setting view_configuration_id to null", async () => {
|
|
// First set an active view
|
|
await api.post(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
view_configuration_id: viewConfig.id,
|
|
},
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
// Verify it's active
|
|
let activeResponse = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
expect(activeResponse.data.view_configuration.id).toBe(viewConfig.id)
|
|
|
|
// Now clear the active view
|
|
const clearResponse = await api.post(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
view_configuration_id: null,
|
|
},
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
expect(clearResponse.status).toBe(200)
|
|
expect(clearResponse.data.success).toBe(true)
|
|
|
|
// Verify the active view is cleared
|
|
activeResponse = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{
|
|
headers: secondAdminHeader,
|
|
}
|
|
)
|
|
|
|
// Debug output
|
|
if (activeResponse.data.view_configuration) {
|
|
console.log("Active view after clearing:", {
|
|
id: activeResponse.data.view_configuration.id,
|
|
name: activeResponse.data.view_configuration.name,
|
|
is_system_default:
|
|
activeResponse.data.view_configuration.is_system_default,
|
|
})
|
|
}
|
|
|
|
// Should either return null or a system default if one exists
|
|
if (activeResponse.data.view_configuration) {
|
|
expect(
|
|
activeResponse.data.view_configuration.is_system_default
|
|
).toBe(true)
|
|
} else {
|
|
expect(activeResponse.data.view_configuration).toBeNull()
|
|
}
|
|
expect(activeResponse.data.is_default_active).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe("System Default Views", () => {
|
|
it("should make system default views available to all users", async () => {
|
|
const container = getContainer()
|
|
|
|
// Create a third admin user
|
|
const thirdAdminHeaders = { headers: {} }
|
|
const { user: thirdAdminUser } = await createAdminUser(
|
|
dbConnection,
|
|
thirdAdminHeaders,
|
|
container,
|
|
{ email: "admin3@test.com" }
|
|
)
|
|
|
|
// Admin 1 creates a system default view
|
|
const systemDefaultView = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "System Default View",
|
|
configuration: {
|
|
visible_columns: ["id", "display_id", "created_at"],
|
|
column_order: ["display_id", "id", "created_at"],
|
|
},
|
|
is_system_default: true,
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
expect(systemDefaultView.status).toEqual(200)
|
|
expect(systemDefaultView.data.view_configuration.user_id).toBeNull()
|
|
|
|
// Admin 3 should be able to see this view
|
|
const viewsForAdmin3 = await api.get(
|
|
"/admin/views/orders/configurations",
|
|
thirdAdminHeaders
|
|
)
|
|
|
|
expect(viewsForAdmin3.status).toEqual(200)
|
|
const systemDefaults = viewsForAdmin3.data.view_configurations.filter(
|
|
(v: any) => v.is_system_default
|
|
)
|
|
expect(systemDefaults).toHaveLength(1)
|
|
expect(systemDefaults[0].name).toEqual("System Default View")
|
|
|
|
// Admin 3 should also be able to retrieve it directly
|
|
const directRetrieve = await api.get(
|
|
`/admin/views/orders/configurations/${systemDefaultView.data.view_configuration.id}`,
|
|
thirdAdminHeaders
|
|
)
|
|
|
|
expect(directRetrieve.status).toEqual(200)
|
|
expect(directRetrieve.data.view_configuration.name).toEqual(
|
|
"System Default View"
|
|
)
|
|
})
|
|
|
|
it("should allow creating system default without name", async () => {
|
|
// Create a system default view without providing a name
|
|
const systemDefaultView = await api.post(
|
|
"/admin/views/customers/configurations",
|
|
{
|
|
is_system_default: true,
|
|
configuration: {
|
|
visible_columns: ["id", "email", "first_name", "last_name"],
|
|
column_order: ["email", "first_name", "last_name", "id"],
|
|
},
|
|
// Note: no name field
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
expect(systemDefaultView.status).toEqual(200)
|
|
expect(systemDefaultView.data.view_configuration.user_id).toBeNull()
|
|
expect(
|
|
systemDefaultView.data.view_configuration.is_system_default
|
|
).toBe(true)
|
|
// Name should be undefined/null when not provided
|
|
expect(systemDefaultView.data.view_configuration.name).toBeFalsy()
|
|
})
|
|
|
|
it("should set view as active when created with set_active flag", async () => {
|
|
// Create a view with set_active = true
|
|
const viewConfig = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "Auto-Active View",
|
|
configuration: {
|
|
visible_columns: ["id", "display_id", "status"],
|
|
column_order: ["display_id", "status", "id"],
|
|
},
|
|
set_active: true,
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(viewConfig.status).toEqual(200)
|
|
|
|
// Verify the view is now active
|
|
const activeView = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(activeView.status).toEqual(200)
|
|
expect(activeView.data.view_configuration).toBeTruthy()
|
|
expect(activeView.data.view_configuration.id).toEqual(
|
|
viewConfig.data.view_configuration.id
|
|
)
|
|
expect(activeView.data.view_configuration.name).toEqual(
|
|
"Auto-Active View"
|
|
)
|
|
})
|
|
|
|
it("should set view as active when updated with set_active flag", async () => {
|
|
const container = getContainer()
|
|
const settingsService = container.resolve("settings")
|
|
|
|
// Create two views
|
|
const view1 = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "View 1",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id"],
|
|
column_order: ["id"],
|
|
},
|
|
})
|
|
|
|
const view2 = await settingsService.createViewConfigurations({
|
|
entity: "orders",
|
|
name: "View 2",
|
|
is_system_default: false,
|
|
user_id: secondAdminUserId,
|
|
configuration: {
|
|
visible_columns: ["id", "total"],
|
|
column_order: ["total", "id"],
|
|
},
|
|
})
|
|
|
|
// Set view1 as active initially
|
|
await settingsService.setActiveViewConfiguration(
|
|
"orders",
|
|
secondAdminUserId,
|
|
view1.id
|
|
)
|
|
|
|
// Update view2 with set_active flag
|
|
const updateResponse = await api.post(
|
|
`/admin/views/orders/configurations/${view2.id}`,
|
|
{
|
|
name: "Updated View 2",
|
|
set_active: true,
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(updateResponse.status).toEqual(200)
|
|
|
|
// Verify view2 is now the active view
|
|
const activeView = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(activeView.status).toEqual(200)
|
|
expect(activeView.data.view_configuration.id).toEqual(view2.id)
|
|
expect(activeView.data.view_configuration.name).toEqual(
|
|
"Updated View 2"
|
|
)
|
|
})
|
|
|
|
it("should allow resetting system default to code-level defaults", async () => {
|
|
// Create a system default view
|
|
const systemDefaultView = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "Custom System Default",
|
|
is_system_default: true,
|
|
configuration: {
|
|
visible_columns: ["id", "status", "total"],
|
|
column_order: ["status", "total", "id"],
|
|
},
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
expect(systemDefaultView.status).toEqual(200)
|
|
const viewId = systemDefaultView.data.view_configuration.id
|
|
|
|
// Verify it exists
|
|
let viewsList = await api.get(
|
|
"/admin/views/orders/configurations",
|
|
adminHeaders
|
|
)
|
|
expect(
|
|
viewsList.data.view_configurations.some((v: any) => v.id === viewId)
|
|
).toBe(true)
|
|
|
|
// Delete the system default view (reset to code defaults)
|
|
const deleteResponse = await api.delete(
|
|
`/admin/views/orders/configurations/${viewId}`,
|
|
adminHeaders
|
|
)
|
|
|
|
expect(deleteResponse.status).toEqual(200)
|
|
expect(deleteResponse.data.deleted).toBe(true)
|
|
|
|
// Verify it's gone
|
|
viewsList = await api.get(
|
|
"/admin/views/orders/configurations",
|
|
adminHeaders
|
|
)
|
|
expect(
|
|
viewsList.data.view_configurations.some((v: any) => v.id === viewId)
|
|
).toBe(false)
|
|
|
|
// Getting active view should return null (falls back to code defaults)
|
|
const activeView = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
adminHeaders
|
|
)
|
|
expect(activeView.data.view_configuration).toBeNull()
|
|
})
|
|
|
|
it("should return system default view when created and no user view is active", async () => {
|
|
// Step 1: Create a system default view
|
|
const systemDefaultView = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "System Default Orders",
|
|
is_system_default: true,
|
|
configuration: {
|
|
visible_columns: [
|
|
"id",
|
|
"display_id",
|
|
"created_at",
|
|
"customer",
|
|
"total",
|
|
],
|
|
column_order: [
|
|
"display_id",
|
|
"customer",
|
|
"total",
|
|
"created_at",
|
|
"id",
|
|
],
|
|
filters: {},
|
|
sorting: { id: "created_at", desc: true },
|
|
search: "",
|
|
},
|
|
},
|
|
adminHeaders
|
|
)
|
|
|
|
expect(systemDefaultView.status).toEqual(200)
|
|
expect(
|
|
systemDefaultView.data.view_configuration.is_system_default
|
|
).toBe(true)
|
|
|
|
// Step 2: Retrieve active view - should return the system default
|
|
const activeView = await api.get(
|
|
"/admin/views/orders/configurations/active",
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(activeView.status).toEqual(200)
|
|
expect(activeView.data.view_configuration).toBeTruthy()
|
|
expect(activeView.data.view_configuration.id).toEqual(
|
|
systemDefaultView.data.view_configuration.id
|
|
)
|
|
expect(activeView.data.view_configuration.name).toEqual(
|
|
"System Default Orders"
|
|
)
|
|
expect(activeView.data.view_configuration.is_system_default).toBe(
|
|
true
|
|
)
|
|
expect(activeView.data.is_default_active).toBe(true)
|
|
expect(activeView.data.default_type).toEqual("system")
|
|
})
|
|
})
|
|
|
|
describe("Filter, Sorting, and Search Persistence", () => {
|
|
it("should save and restore filters, sorting, and search configuration", async () => {
|
|
// Create a view with filters, sorting, and search
|
|
const viewConfig = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "Filtered View",
|
|
configuration: {
|
|
visible_columns: ["id", "status", "total", "created_at"],
|
|
column_order: ["status", "total", "created_at", "id"],
|
|
filters: {
|
|
status: ["pending", "completed"],
|
|
total: { gte: 100 },
|
|
},
|
|
sorting: { id: "created_at", desc: true },
|
|
search: "test search",
|
|
},
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(viewConfig.status).toEqual(200)
|
|
expect(
|
|
viewConfig.data.view_configuration.configuration.filters
|
|
).toEqual({
|
|
status: ["pending", "completed"],
|
|
total: { gte: 100 },
|
|
})
|
|
expect(
|
|
viewConfig.data.view_configuration.configuration.sorting
|
|
).toEqual({
|
|
id: "created_at",
|
|
desc: true,
|
|
})
|
|
expect(
|
|
viewConfig.data.view_configuration.configuration.search
|
|
).toEqual("test search")
|
|
|
|
// Retrieve the view and verify filters are preserved
|
|
const getResponse = await api.get(
|
|
`/admin/views/orders/configurations/${viewConfig.data.view_configuration.id}`,
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(getResponse.status).toEqual(200)
|
|
expect(
|
|
getResponse.data.view_configuration.configuration.filters
|
|
).toEqual({
|
|
status: ["pending", "completed"],
|
|
total: { gte: 100 },
|
|
})
|
|
})
|
|
|
|
it("should remove filters when updating a view without filters", async () => {
|
|
// Create a view with filters
|
|
const viewConfig = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "View with Filters",
|
|
configuration: {
|
|
visible_columns: ["id", "status", "total"],
|
|
column_order: ["status", "total", "id"],
|
|
filters: {
|
|
status: ["pending", "completed"],
|
|
total: { gte: 100 },
|
|
},
|
|
sorting: { id: "total", desc: true },
|
|
search: "initial search",
|
|
},
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(viewConfig.status).toEqual(200)
|
|
const viewId = viewConfig.data.view_configuration.id
|
|
|
|
// Update the view to remove filters
|
|
const updateResponse = await api.post(
|
|
`/admin/views/orders/configurations/${viewId}`,
|
|
{
|
|
configuration: {
|
|
visible_columns: ["id", "status", "total"],
|
|
column_order: ["status", "total", "id"],
|
|
filters: {}, // Empty filters object
|
|
sorting: null, // Remove sorting
|
|
search: "", // Clear search
|
|
},
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(updateResponse.status).toEqual(200)
|
|
|
|
// Verify filters were removed
|
|
expect(
|
|
updateResponse.data.view_configuration.configuration.filters
|
|
).toEqual({})
|
|
expect(
|
|
updateResponse.data.view_configuration.configuration.sorting
|
|
).toBeNull()
|
|
expect(
|
|
updateResponse.data.view_configuration.configuration.search
|
|
).toEqual("")
|
|
|
|
// Retrieve again to double-check persistence
|
|
const getResponse = await api.get(
|
|
`/admin/views/orders/configurations/${viewId}`,
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(getResponse.status).toEqual(200)
|
|
expect(
|
|
getResponse.data.view_configuration.configuration.filters
|
|
).toEqual({})
|
|
expect(
|
|
getResponse.data.view_configuration.configuration.sorting
|
|
).toBeNull()
|
|
expect(
|
|
getResponse.data.view_configuration.configuration.search
|
|
).toEqual("")
|
|
})
|
|
|
|
it("should update only specific filters while keeping others", async () => {
|
|
// Create a view with multiple filters
|
|
const viewConfig = await api.post(
|
|
"/admin/views/orders/configurations",
|
|
{
|
|
name: "Multi-Filter View",
|
|
configuration: {
|
|
visible_columns: ["id", "status", "total", "created_at"],
|
|
column_order: ["status", "total", "created_at", "id"],
|
|
filters: {
|
|
status: ["pending", "completed"],
|
|
total: { gte: 100, lte: 1000 },
|
|
created_at: { gte: "2024-01-01" },
|
|
},
|
|
sorting: { id: "created_at", desc: true },
|
|
search: "customer",
|
|
},
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(viewConfig.status).toEqual(200)
|
|
const viewId = viewConfig.data.view_configuration.id
|
|
|
|
// Update to remove only the 'total' filter
|
|
const updateResponse = await api.post(
|
|
`/admin/views/orders/configurations/${viewId}`,
|
|
{
|
|
configuration: {
|
|
visible_columns: ["id", "status", "total", "created_at"],
|
|
column_order: ["status", "total", "created_at", "id"],
|
|
filters: {
|
|
status: ["pending", "completed"],
|
|
created_at: { gte: "2024-01-01" },
|
|
// 'total' filter removed
|
|
},
|
|
sorting: { id: "created_at", desc: true },
|
|
search: "customer",
|
|
},
|
|
},
|
|
{ headers: secondAdminHeader }
|
|
)
|
|
|
|
expect(updateResponse.status).toEqual(200)
|
|
expect(
|
|
updateResponse.data.view_configuration.configuration.filters
|
|
).toEqual({
|
|
status: ["pending", "completed"],
|
|
created_at: { gte: "2024-01-01" },
|
|
})
|
|
expect(
|
|
updateResponse.data.view_configuration.configuration.filters.total
|
|
).toBeUndefined()
|
|
})
|
|
})
|
|
})
|
|
},
|
|
})
|