Files
medusa-store/packages/modules/settings/integration-tests/__tests__/settings-module.spec.ts
Sebastian Rindom f7fc05307f feat: add settings module (#13175)
* feat: add view_configurations feature flag

  - Add feature flag provider and hooks to admin dashboard
  - Add backend API endpoint for feature flags
  - Create view_configurations feature flag (disabled by default)
  - Update order list table to use legacy version when flag is disabled
  - Can be enabled with MEDUSA_FF_VIEW_CONFIGURATIONS=true env var

* fix: naming

* fix: feature flags unauthenticated

* fix: add test

* feat: add settings module

* fix: deps

* fix: cleanup

* fix: add more tetsts

* fix: rm changelog

* fix: deps

* fix: add settings module to default modules list

* fix: pr comments

* fix: deps,build

* fix: alias

* fix: tests

* fix: update snapshots
2025-08-15 10:59:54 +02:00

424 lines
16 KiB
TypeScript

import { Modules } from "@medusajs/utils"
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
import { SettingsTypes } from "@medusajs/types"
jest.setTimeout(30000)
moduleIntegrationTestRunner<SettingsTypes.ISettingsModuleService>({
moduleName: Modules.SETTINGS,
testSuite: ({ service }) => {
describe("SettingsModuleService", function () {
describe("ViewConfiguration", function () {
it("should create a view configuration", async () => {
const viewConfig = await service.createViewConfigurations({
entity: "orders",
name: "My Orders View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "status", "created_at"],
column_order: ["id", "status", "created_at"],
column_widths: { id: 100, status: 150 },
filters: { status: ["pending", "completed"] },
sorting: { id: "created_at", desc: true },
search: "",
},
})
expect(viewConfig).toEqual(
expect.objectContaining({
id: expect.any(String),
entity: "orders",
name: "My Orders View",
user_id: "user_123",
})
)
})
it("should update a view configuration and remove filters", async () => {
// Create a view with filters
const viewConfig = await service.createViewConfigurations({
entity: "products",
name: "Filtered Products View",
user_id: "user_456",
configuration: {
visible_columns: ["id", "title", "status"],
column_order: ["id", "title", "status"],
filters: {
status: ["draft", "published"],
collection_id: ["col_123", "col_456"],
},
sorting: { id: "created_at", desc: true },
},
})
expect(viewConfig.configuration.filters).toEqual({
status: ["draft", "published"],
collection_id: ["col_123", "col_456"],
})
// Update the view to remove filters
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: ["id", "title", "status"],
column_order: ["id", "title", "status"],
filters: {}, // Empty filters object
sorting: { id: "created_at", desc: true },
},
}
)
expect(updatedConfig.configuration.filters).toEqual({})
// Retrieve the view again to ensure filters were persisted as empty
const retrievedConfig = await service.retrieveViewConfiguration(
viewConfig.id
)
expect(retrievedConfig.configuration.filters).toEqual({})
})
it("should update view configuration with partial configuration updates", async () => {
// Create a view with full configuration
const viewConfig = await service.createViewConfigurations({
entity: "customers",
name: "Customer View",
user_id: "user_789",
configuration: {
visible_columns: ["id", "name", "email"],
column_order: ["id", "name", "email"],
filters: {
has_account: true,
groups: ["vip", "regular"],
},
sorting: { id: "created_at", desc: false },
search: "test search",
},
})
// Update only filters (should preserve other configuration)
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: ["id", "name", "email"],
column_order: ["id", "name", "email"],
filters: { has_account: false }, // Changed filters
sorting: { id: "created_at", desc: false },
search: "test search",
},
}
)
expect(updatedConfig.configuration).toEqual({
visible_columns: ["id", "name", "email"],
column_order: ["id", "name", "email"],
filters: { has_account: false },
sorting: { id: "created_at", desc: false },
search: "test search",
column_widths: {}, // Default value when not provided
})
})
it("should update only the name field without affecting configuration", async () => {
// Create a view with full configuration
const viewConfig = await service.createViewConfigurations({
entity: "orders",
name: "Original Name",
user_id: "user_123",
configuration: {
visible_columns: ["id", "status", "total"],
column_order: ["id", "status", "total"],
column_widths: { id: 100, status: 150, total: 200 },
filters: { status: ["pending", "completed"] },
sorting: { id: "created_at", desc: true },
search: "test search",
},
})
// Update only the name field
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{ name: "Updated Name" }
)
expect(updatedConfig.name).toBe("Updated Name")
expect(updatedConfig.configuration).toEqual(viewConfig.configuration)
})
it("should completely replace filters when updating configuration", async () => {
// Create a view with complex filters
const viewConfig = await service.createViewConfigurations({
entity: "products",
name: "Product View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "title"],
column_order: ["id", "title"],
filters: {
status: ["draft", "published"],
collection_id: ["col_123", "col_456"],
price_range: { min: 10, max: 100 },
},
sorting: { id: "created_at", desc: true },
},
})
// Update with new filters
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: ["id", "title"],
column_order: ["id", "title"],
filters: { category: ["electronics"] }, // Completely different filters
sorting: { id: "created_at", desc: true },
},
}
)
expect(updatedConfig.configuration.filters).toEqual({
category: ["electronics"],
})
// Verify old filters are gone
expect(updatedConfig.configuration.filters.status).toBeUndefined()
expect(updatedConfig.configuration.filters.collection_id).toBeUndefined()
expect(updatedConfig.configuration.filters.price_range).toBeUndefined()
})
it("should remove filters when explicitly set to empty object", async () => {
// Create a view with filters
const viewConfig = await service.createViewConfigurations({
entity: "customers",
name: "Customer View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "name", "email"],
column_order: ["id", "name", "email"],
filters: {
has_account: true,
groups: ["vip", "regular"],
},
sorting: { id: "created_at", desc: false },
},
})
// Update configuration with empty filters
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: ["id", "name", "email"],
column_order: ["id", "name", "email"],
filters: {}, // Empty filters
sorting: { id: "created_at", desc: false },
},
}
)
expect(updatedConfig.configuration.filters).toEqual({})
})
it("should preserve other configuration properties when updating specific ones", async () => {
// Create a view with full configuration
const viewConfig = await service.createViewConfigurations({
entity: "inventory",
name: "Inventory View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "sku", "quantity"],
column_order: ["id", "sku", "quantity"],
column_widths: { id: 80, sku: 120, quantity: 100 },
filters: { location: ["warehouse_1"] },
sorting: { id: "sku", desc: false },
search: "original search",
},
})
// Update only filters and sorting
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: viewConfig.configuration.visible_columns,
column_order: viewConfig.configuration.column_order,
filters: { location: ["warehouse_2"] },
sorting: { id: "quantity", desc: true },
// Note: not providing column_widths and search
},
}
)
expect(updatedConfig.configuration.filters).toEqual({
location: ["warehouse_2"],
})
expect(updatedConfig.configuration.sorting).toEqual({
id: "quantity",
desc: true,
})
// These should be preserved
expect(updatedConfig.configuration.visible_columns).toEqual(
viewConfig.configuration.visible_columns
)
expect(updatedConfig.configuration.column_order).toEqual(
viewConfig.configuration.column_order
)
// These should have default values since not provided
expect(updatedConfig.configuration.column_widths).toEqual({})
expect(updatedConfig.configuration.search).toBe("")
})
it("should handle missing configuration properties with defaults", async () => {
// Create a view with full configuration
const viewConfig = await service.createViewConfigurations({
entity: "payments",
name: "Payment View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "amount", "status"],
column_order: ["id", "amount", "status"],
column_widths: { id: 100, amount: 150, status: 120 },
filters: { status: ["completed"] },
sorting: { id: "created_at", desc: true },
search: "payment search",
},
})
// Update with partial configuration (only visible_columns)
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: ["id", "amount"],
column_order: ["id", "amount"],
// Not providing filters, sorting, search, column_widths
},
}
)
expect(updatedConfig.configuration).toEqual({
visible_columns: ["id", "amount"],
column_order: ["id", "amount"],
column_widths: {}, // Default
filters: {}, // Default
sorting: null, // Default
search: "", // Default
})
})
it("should update multiple view configurations when using selector", async () => {
// Create multiple views for the same entity
const view1 = await service.createViewConfigurations({
entity: "orders",
name: "Orders View 1",
user_id: "user_123",
configuration: {
visible_columns: ["id", "status"],
column_order: ["id", "status"],
filters: { status: ["pending"] },
},
})
const view2 = await service.createViewConfigurations({
entity: "orders",
name: "Orders View 2",
user_id: "user_456",
configuration: {
visible_columns: ["id", "total"],
column_order: ["id", "total"],
filters: { status: ["completed"] },
},
})
const view3 = await service.createViewConfigurations({
entity: "products", // Different entity
name: "Products View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "title"],
column_order: ["id", "title"],
},
})
// Update using selector for entity "orders"
const updatedConfigs = await service.updateViewConfigurations(
{ entity: "orders" },
{
configuration: {
visible_columns: ["id", "status", "total"],
column_order: ["id", "status", "total"],
filters: {},
},
}
)
// Should return an array
expect(Array.isArray(updatedConfigs)).toBe(true)
expect(updatedConfigs).toHaveLength(2)
// Both orders views should be updated
const updatedIds = updatedConfigs.map((v) => v.id).sort()
expect(updatedIds).toEqual([view1.id, view2.id].sort())
// All should have the new configuration
updatedConfigs.forEach((config) => {
expect(config.configuration.visible_columns).toEqual([
"id",
"status",
"total",
])
expect(config.configuration.filters).toEqual({})
})
// Products view should not be affected
const productView = await service.retrieveViewConfiguration(view3.id)
expect(productView.configuration.visible_columns).toEqual(["id", "title"])
})
it("should return empty array when no views match selector", async () => {
// Try to update with a selector that matches no views
const result = await service.updateViewConfigurations(
{ entity: "non_existent_entity" },
{ name: "New Name" }
)
expect(Array.isArray(result)).toBe(true)
expect(result).toHaveLength(0)
})
it("should handle null values in configuration", async () => {
// Create a view with sorting
const viewConfig = await service.createViewConfigurations({
entity: "shipping",
name: "Shipping View",
user_id: "user_123",
configuration: {
visible_columns: ["id", "carrier", "tracking"],
column_order: ["id", "carrier", "tracking"],
sorting: { id: "created_at", desc: true },
search: "fedex",
},
})
// Update with sorting: null
const updatedConfig = await service.updateViewConfigurations(
viewConfig.id,
{
configuration: {
visible_columns: viewConfig.configuration.visible_columns,
column_order: viewConfig.configuration.column_order,
sorting: null,
search: "", // Also test empty string
},
}
)
expect(updatedConfig.configuration.sorting).toBeNull()
expect(updatedConfig.configuration.search).toBe("")
})
})
})
},
})